anymaniax / orval

orval is able to generate client with appropriate type-signatures (TypeScript) from any valid OpenAPI v3 or Swagger v2 specification, either in yaml or json formats. 🍺
https://orval.dev
MIT License
2.49k stars 273 forks source link

Not able to use the orval API. #129

Closed hhimanshu closed 3 years ago

hhimanshu commented 3 years ago

Hello @anymaniax, I am interested in using orval and also gave it a shot. Unfortunately, it did not work even for a single time. I wonder if I am unsure about using Orval at all.

My spec is available at https://github.com/hhimanshu/rapid-front-end-development/tree/openapi3/src/openapi for the context.

I will fill the sections next

What are the steps to reproduce this issue?

I run the following command

➜  openapi git:(openapi3) npx orval --input spec.yaml --output business.ts
🍻 Start orval v4.2.1 - A swagger client generator for typescript
Oups... 🍻

This does not give me any indication on what went wrong, no debug logs either

What happens?

It fails it Oups. I also tried with a specific version, not sure if that is stable, but that doesn't works either

➜  openapi git:(openapi3) npx orval@5.2.0 --input spec.yaml --output business.ts
Need to install the following packages:
  orval@5.2.0
Ok to proceed? (y) y
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
🍻 Start orval v5.2.0 - A swagger client generator for typescript
/Users/hhimanshu/.npm/_npx/08ae492f93714e2b/node_modules/orval/dist/chunk-4LSQHVTZ.js:11
    }`});return[{method:"POST",hostname:"api.github.com",path:"/graphql",headers:{"content-type":"application/json","user-agent":"orval-importer",authorization:`bearer ${e}`,"Content-Length":s.length}},s]},ys=async e=>{if(await _fsextra.pathExists.call(void 0, e))return _fsextra.readFile.call(void 0, e,"utf-8");{let t=await _inquirer2.default.prompt([{type:"input",name:"githubToken",message:"Please provide a GitHub token with `repo` rules checked (https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/)"},{type:"confirm",name:"saveToken",message:"Would you like to store your token for the next time? (stored in your node_modules)"}]);return t.saveToken&&await _fsextra.outputFile.call(void 0, e,t.githubToken),t.githubToken}},ds=async e=>{var m;let t=_upath.join.call(void 0, __dirname,".githubToken"),r=await ys(t),[n]=e.split("github.com/").slice(-1),[o,s,,a,...i]=n.split("/"),p=i.join("/");try{let{body:c}=await Zt(...gs({accessToken:r,repo:s,owner:o,branch:a,path:p}));return(m=c.data)==null?void 0:m.repository.object.text}catch(c){throw c.body?(c.body.message==="Bad credentials"&&(await _inquirer2.default.prompt([{type:"confirm",name:"removeToken",message:"Your token doesn't have the correct permissions, should we remove it?"}])).removeToken&&await _fsextra.unlink.call(void 0, t),c.body.message||`Oups... \u{1F37B}. ${c}`):`Oups... \u{1F37B}. ${c}`}},tr={order:199,canRead(e){return e.url.includes("github.com")},read(e){return ds(e.url)}};var Ee=e=>e&&typeof e=="object";function V(e,t){return!Ee(t)||!Ee(e)?e:Object.entries(t).reduce((r,[n,o])=>{let s=r[n];return Array.isArray(s)&&Array.isArray(o)?u(u({},r),{[n]:[...s,...o]}):Ee(s)&&Ee(o)?u(u({},r),{[n]:V(s,o)}):u(u({},r),{[n]:o})},e)}var pe=e=>{try{return new URL(e),!0}catch(t){return!1}};var $=(e,t,r)=>e.reduce(async(n,...o)=>t(await n,...o),Promise.resolve(r));var _swagger2openapi = require('swagger2openapi'); var _swagger2openapi2 = _interopRequireDefault(_swagger2openapi);var rr=(e,t={})=>{try{return new Promise((r,n)=>{!e.openapi||!e.openapi.startsWith("3.0")?_swagger2openapi2.default.convertObj(e,t,(o,{openapi:s})=>{o?n(o):r(s)}):r(e)})}catch(r){throw`Oups... \u{1F37B}. Parsing Error: ${r}`}};var me=async(e,t=process.cwd())=>{if(!e)return e;try{if(M(e)){let r=_upath.resolve.call(void 0, t,e),n=await Promise.resolve().then(()=>Ce(require(r)));return R(n)&&n.default?n.default:n}return Promise.resolve(e)}catch(r){throw`Oups... \u{1F37B}. Path: ${e} => ${r}`}};var _lodashget = require('lodash.get'); var _lodashget2 = _interopRequireDefault(_lodashget);var N=e=>{if(!(Lt(e)||Ht(e)))return M(e)?`'${e}'`:Ut(e)||ae(e)||ie(e)?`${e}`:Array.isArray(e)?`[${e.map(N).join(", ")}]`:Object.entries(e).reduce((t,[r,n],o,s)=>{let a=N(n);return s.length===1?`{ ${r}: ${a}, }`:o?s.length-1===o?t+`${r}: ${a}, }`:t+`${r}: ${a}, `:`{ ${r}: ${a}, `},"")},k=(e,t)=>{let{whitespace:r="",underscore:n=""}=t||{},o=e.replace(/[^\w\s]/g,"");return r!==!0&&(o=o.replace(/[\s]/g,r)),n!==!0&&(o=o.replace(/['_']/g,n)),o},q=(e,t)=>e.length?(t?e.map(n=>_lodashget2.default.call(void 0, n,t)):e).join(`,

TypeError: Cannot destructure property 'openapi' of 'undefined' as it is undefined.
    at /Users/hhimanshu/.npm/_npx/08ae492f93714e2b/node_modules/orval/dist/chunk-4LSQHVTZ.js:11:2132
    at /Users/hhimanshu/.npm/_npx/08ae492f93714e2b/node_modules/call-me-maybe/index.js:13:28
    at processTicksAndRejections (internal/process/task_queues.js:75:11)

What were you expecting to happen?

I expected for API and models to be generated for TypeScript and React-Query

Any logs, error output, etc?

I added all of what I saw above, and I hope that helps.

Any other comments?

Do you see any issues in my approach? Does Orval only work if the $ref is in the same file? How can I resolve this issue my friend? Thank you

What versions are you using?

Operating System: Mac 10.15.7 Package Version:

➜  openapi git:(openapi3) npm -v
7.5.6
➜  openapi git:(openapi3) node -v
v14.16.0

Browser Version: N/A since I am not doing anything related to browser, yet.

anymaniax commented 3 years ago

Hello, sorry for your problem. With version 5, orval support multi-files when I read the other files I also try to resolve them as open API files. Which cause a problem in your case. I updated your specification to solve the problem (spec). I will think about a better solution in the future but at the moment it's the only solution sorry :(.

hhimanshu commented 3 years ago

@anymaniax, thank you for your response. It does generate the file now. However, I have not used it yet. I am going to try now to thank you first for your work. Is it possible to make it work with fetch instead of axios?

anymaniax commented 3 years ago

Hello, sure. You can use a mutator checkout the doc here and example

hhimanshu commented 3 years ago

Thank you @anymaniax , I will take a look

hhimanshu commented 3 years ago

Hello @anymaniax , I tried using it again with configuration file, and now it fails with the following error. I used the same files that you added to GitHub gist earlier.

➜  mock-service-worker-rest git:(openapi3) βœ— npx orval@5.2.0 --config ./orval.config.js
🍻 Start orval v5.2.0 - A swagger client generator for typescript
TypeError: Cannot read property 'components' of undefined

The latest code is available on the branch https://github.com/hhimanshu/rapid-front-end-development/tree/openapi3 Have I missed something?

hhimanshu commented 3 years ago

And if I use it without 5.2.0 version, I see other errors

➜  mock-service-worker-rest git:(openapi3) βœ— npx orval --config ./orval.config.js
🍻 Start orval v4.2.1 - A swagger client generator for typescript
Error: Every path must have a operationId - No operationId set for get /api/businesses
➜  mock-service-worker-rest git:(openapi3) βœ— npx orval --config ./orval.config.js
🍻 Start orval v4.2.1 - A swagger client generator for typescript
Error: This library only resolve $ref that are include into `#/components/*` for now

My intention is to generate TypeScript code with react-query and msw at this time. Let me know if I have missed something. Thanks

anymaniax commented 3 years ago

Can you try with the 5.3.0 was a bug with the mock generation when you have multiple files specification

hhimanshu commented 3 years ago

Hey @anymaniax , thanks for the fix. It now generates methods. I have been able to use them as well. One oddity that I found was that it did not honor the config to create a file of my choice

module.exports = {
  businesses: {
    output: {
      mode: 'tags-split',
      target: 'src/openapi/generated/interface.ts',
      schemas: 'src/openapi/generated/model',
      client: 'react-query',
      mock: true,
    },
    input: {
      target: './src/openapi/spec.yaml',
    },
  },
};

In config, I mentioned I want name of 'src/openapi/generated/interface.ts' - reference, but it created file called default.ts in a default named directory - reference.

Do you know if I am missing something?

Also, how does msw act here? Currently, my own handlers are intercepting the request, how do I make use of the ones created by orval? Thanks. much again!

hhimanshu commented 3 years ago

I figured how to use fake data using msw, however, it is not closer to my domain model so I will leave it for now. When you get a chance, please let me know how to honor the name of the output.target file instead of using default/default.ts. Thank you

anymaniax commented 3 years ago

Hello, it's because you use the mode tags-split. You maybe want the default mode 'single'? or 'split' depending on if you are using the mock.

hhimanshu commented 3 years ago

Thank you @anymaniax, with mode: single, I was able to generate a single file. reference