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

Most types on $ are typed as never #787

Closed
programm-ingovals opened this issue Mar 9, 2024 · 16 comments
Closed

Most types on $ are typed as never #787

programm-ingovals opened this issue Mar 9, 2024 · 16 comments
Labels
brainstorm Ideas that aren't fully baked bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request

Comments

@programm-ingovals
Copy link

This means typescript will cry if we try to access something here.
Is this intended, it doesn't fit with the documentations ( which also names $.header as $.headers )

export type HTTP_GET = ({
  query,
  path,
  header,
  body,
  context,
  proxy,
}: {
  query: never;
  path: never;
  header: never;
  body: undefined;
  context: Context;
  response: ResponseBuilderFactory<{
@pmcelhaney
Copy link
Owner

That's intentional but let's talk about it...

Assuming the OpenAPI document is correct, if it doesn't specify any parameters, there's no reason to call $.query(), and $.query doesn't show up as an option in autocomplete. (The same logic applies to $.path, $.header, and $.body.)

Does that make sense? What would you expect to see there instead of never? We could put Record<string, string> instead of never, so that TypeScript doesn't complain about $.query("my-undocumented-query-param"). If that makes sense to you, I'm open to making the change. I'll put it behind a CLI flag at first and see what others think.

@pmcelhaney pmcelhaney added brainstorm Ideas that aren't fully baked bug Something isn't working enhancement New feature or request documentation Improvements or additions to documentation labels Mar 12, 2024
@dethell
Copy link
Collaborator

dethell commented Mar 12, 2024

I have run into this as well, but it was always because the OpenApi doc was incorrect. At first I wanted a way to stop Counterfact from fussing about the never types and then I realized the better fix was to have our API team just fix the annotations that generate the OpenApi doc.

@dethell
Copy link
Collaborator

dethell commented Mar 12, 2024

Well, I'm going to take that back. I have paths in the OpenApi spec that define a body for a POST call as undefined, but the schema actual does show a request type for that path.

@pmcelhaney
Copy link
Owner

pmcelhaney commented Mar 12, 2024

I thought about adding a type parameter to set a "loose" mode.

export const GET: HTTP_GET ($) // has never types

export const GET: HTTP_GET<"loose"> ($) // has Record<string, string> types

But if we make "loose" mode loose enough to compensate for incomplete OpenAPI, you might as well replace HTTP_GET with any.

@pmcelhaney
Copy link
Owner

Maybe instead we should add a comment to the file with a link to a page that explains the relationship between that file and OpenAPI?

@pmcelhaney
Copy link
Owner

BTW, did you know? If your OpenAPI file is local, while Counterfact is running, a change to the OpenAPI file will immediately be reflected in the type definition.

@pmcelhaney
Copy link
Owner

the documentations ( which also names $.header as $.headers )

Thanks! The documentation is fixed.

@dethell
Copy link
Collaborator

dethell commented Mar 12, 2024

BTW, did you know? If your OpenAPI file is local, while Counterfact is running, a change to the OpenAPI file will immediately be reflected in the type definition.

This is one of the single best features of CF.

@pmcelhaney
Copy link
Owner

Maybe instead we should add a comment to the file with a link to a page that explains the relationship between that file and OpenAPI?

Done. Check out this PR: #796

@IngoVals
Copy link

IngoVals commented Mar 14, 2024

Wow, sorry this discussion somehow totally went past me.

So I guess my use case isn't the intended one. I'm working against an api I do not have ownership over, and need to work/test against data that might not be present or available to me. This is why I like to use this mock server. So I can easily create the scenarios and edge cases to test out my frontend.

I'm assuming then that in OpenApi definitions even specific header parameters are defined, which is not the case for the openapi i'm working against. However it does define basic auth which would include the auth header right?

I was hoping to take a look at the user making the request and returning different mocked data based on that. So I could have a test user that has more of a happy path, another I could use when I want things to go wrong etc.

I could also see that case of perhaps wanting to add a custom header for dev, testing purposes, f.e. to specifically target Counterfact. X-TEST-USER=happypath. This wouldn't apply to prod and would be left out of OpenApi def.

I can't say I have a silver bullet of an solution. We have options like unknown, but I agree that never makes sense at least in the case of no defined query params, path params.

One thing could be having a --not-strict option when running which would generate the code more open, using any or better yet Record<string, string> so it is the option.

@pmcelhaney
Copy link
Owner

Thanks. Okay, you've convinced me that --not-strict is worth having.

A couple other workarounds to consider:

  1. Make a copy of the OpenAPI file that you can control.
  2. Change all the files from .ts to .js

Counterfact can technically be used without OpenAPI at all. You can create all of the files manually in the paths directory -- either ts or js files. (Currently the CLI requires an OpenAPI file. I need to fix that, but in the meantime a dummy OpenAPI file will work.)

@pmcelhaney
Copy link
Owner

pmcelhaney commented Mar 14, 2024

However it does define basic auth which would include the auth header right?

I'm embarrassed to say Counterfact doesn't support that yet. I'll make it a priority.

@pmcelhaney
Copy link
Owner

I was hoping to take a look at the user making the request and returning different mocked data based on that. So I could have a test user that has more of a happy path, another I could use when I want things to go wrong etc.

That makes sense, and TypeScript errors notwithstanding you should be able to do that now.

However, as you get to know Counterfact, I think you'll find there are easier ways to test different scenarios.

First, you can change the code and see the results without restarting. (To toggle between error and no error you might comment / uncomment a return statement that has the error response.)

Second, instead of looking at the user you can look at the context object.

if (context.error.duplicateProductName) {
  return $.response[400].json({ error: `A product named ${body.name} already exists.`});
}

The you can use the REPL to set the value of context.error.duplicateProductName.

Much faster and more flexible than logging out and logging in with a different user!

@pmcelhaney
Copy link
Owner

I can't say I have a silver bullet of an solution. We have options like unknown, but I agree that never makes sense at least in the case of no defined query params, path params.

Okay, I think I have an elegant solution in #801

I added a new $.x object. At runtime it's an alias of $. But its types are wider. So if TypeScript complains about $.header["undocumented-header"], you can change it to $.x.header["undocumented-header"] and TypeScript is happy.

@IngoVals
Copy link

I can't say I have a silver bullet of an solution. We have options like unknown, but I agree that never makes sense at least in the case of no defined query params, path params.

Okay, I think I have an elegant solution in #801

I added a new $.x object. At runtime it's an alias of $. But its types are wider. So if TypeScript complains about $.header["undocumented-header"], you can change it to $.x.header["undocumented-header"] and TypeScript is happy.

Yeah, I think this is a decent solution. We can still enjoy the type safety but opt into edge cases where we don´t fully control the OpenAPI def.
Thank you

@pmcelhaney
Copy link
Owner

The $.x object is in 0.38.1 along with a few other improvements to the type system. Let me know how that works for you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
brainstorm Ideas that aren't fully baked bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants