readmeio / api

🚀 Automatic SDK generation from an OpenAPI definition
https://api.readme.dev
MIT License
568 stars 25 forks source link

Issue with NestJS #604

Open bennettl opened 1 year ago

bennettl commented 1 year ago

Trying to use this for my NestJS project, and when running got the following compilation error

import type * as types from './types'; ^^^^^^

SyntaxError: Cannot use import statement outside a module

It seems like this sits outside the src folder, not sure if it can be an issue. Any help is appreciated!!!

erunion commented 1 year ago

I'm not at all familiar with NestJS but I have some questions about your install.

  1. How did you install your API SDK?
  2. Did you install it as JS or TypeScript?
  3. CJS or ESM?
  4. How are you loading your API SDK?
murtinha commented 1 year ago

edited: The problem seems to be that nest dist output main.js file is trying to access the ts file com the .app folder... So since js is trying to access a ts file it doesnt work. I could get it partially fixed using ts-node to run the main.js file

Im also having this problem after adding resolveJsonModule to my ts.config to fix the json import from the generated .api folder.

Answering @erunion

  1. npx api install @open-api-docs/MYAPI
  2. Typescript
  3. When running on typescript it doesnt ask that actually but on tsconfig is commonjs
  4. importing it directly from the generated .api folder
erunion commented 1 year ago

I don't use NestJS so I'm not sure how to solve this. Do you know why it's trying to use the TS file directly instead of compiling it into your app when you build your main output main.js file?

linzera commented 1 year ago

Probably because the .api directory is not being included in the build phase.

murtinha commented 1 year ago

Im not 100% sure but it seems to have to do with nest dependency injection

Cmoen11 commented 1 year ago

This is the same issue in next.js

erunion commented 1 year ago

For what it's worth, if you're generating a JS SDK api will still generate TS types for you to use in local development. You don't need to generate a TS SDK to get TS types.

As for why Nest and Next aren't factoring these non-d.ts .ts files into your compilation processes I'm not sure.

Cmoen11 commented 1 year ago

An update, if i run yarn install after i have generated the .api folder, I get these errors locally as well. It works again if I delete the folder and generate them once more.. @erunion

Cmoen11 commented 1 year ago

Alright, @erunion I think I've found out what's causing this. And it is neither next.js nor nuxt.js, it is for the project which uses yarn instead of npm.

It seems like the lib is forcing on npm, and it's creating conflicting package-lock.json with the yarn.lock file. switching over to npm instead seems to solve my problem.

Cmoen11 commented 1 year ago

I think i've located the problem.

https://github.com/readmeio/api/blob/ebb90af3605cb522f4aafaba75b9c9fe581b6534/packages/api/src/cli/codegen/languages/typescript.ts#LL156C21-L156C21

So if you're using a different package manager you may stumble on some problems caused by this.

erunion commented 1 year ago

Besides @Cmoen11, is everyone else in this thread using Yarn?

afreemanio commented 1 year ago

Alright, so, I ran into this one today. Can confirm, not using Yarn, not using Nest or Next or anything, just plain node.

Got around this issue by copy-pasting the generated code from the .api folder to a new api folder in my src directory, and importing it directly (so, import x from '../api/apis/example' rather than import x from '@api/example') Interested to see how this could be avoided in future.

Pretty sure it has to do with tsconfig and module resolution

yangricardo commented 1 year ago

Also with issues when need to use client side nextjs. Have tried several things, but it keeps trying to import fs library, that is not available for browsers. Just importing an sdk object causes: image

erunion commented 1 year ago

@yangricardo That prepareParams file uses fs in order to handle file uploads through SDKs. If you're just using this in the browser you should be able to safely polyfill fs in your Webpack config.

https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application

erunion commented 1 year ago

@afreemanio Would you be willing to share a working broken example of this in an isolated repository that I can play around with? Would be immensely helpful in figuring out what the heck the library is doing that's causing this.

Cmoen11 commented 1 year ago

There may be multiple issues here. I use it server side, and I did not get this issue at first, but when I did yarn install to install another package. the problem occurred server side. I was deleting the .API folder and reinit the API SDK at it was working again.

also my deployment on vercel got this problem when vercel did yarn install instead of npm install.

When switching over to npm, all these problem was removed.

yangricardo commented 1 year ago

@yangricardo That prepareParams file uses fs in order to handle file uploads through SDKs. If you're just using this in the browser you should be able to safely polyfill fs in your Webpack config.

https://stackoverflow.com/questions/64926174/module-not-found-cant-resolve-fs-in-next-js-application

@erunion , i have already tried that, but it keeps trying to access fs functionalities...

image

afreemanio commented 1 year ago

@afreemanio Would you be willing to share a working broken example of this in an isolated repository that I can play around with? Would be immensely helpful in figuring out what the heck the library is doing that's causing this.

https://github.com/afreemanio/api-604

As an update, looks like this is an issue for me specifically with ts-node (building and running normally seems to work fine). This might be related to other peoples issues, depending on the tool used to run the different frameworks.

I also ran into a few pain points when trying to use this library for the first time, so it might be worth considering having the option to install not as a separate package but as a subdirectory as I posted above. I was also running into some pain points with getting the ActiveCampaign API to install, and I think changes to the docs might be able to make things more clear for new users (I'd love to help). I'm considering opening another issue for these - you can see more details my README.md and notes.md file from the repo above.

maggo commented 1 year ago

Got the same issues with yarn, nextjs, typescript target. Had to add the generated module to transpilePackages, then update webpack config to replace fs with an empty implementation. But now it's still failing because datauri seems to use fs/promises

nextjs config:

transpilePackages: ['@api/center-api'],
webpack(config) {
  config.resolve.fallback = {
    ...config.resolve.fallback,
    fs: false,
  }

  return config
},
JPCanaverde commented 1 year ago

For anyone using Vite, this works:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
import { nodePolyfills } from "vite-plugin-node-polyfills";

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        react(),
        nodePolyfills({
            // To exclude specific polyfills, add them to this list.
            exclude: [
                'fs', // Excludes the polyfill for `fs` and `node:fs` (which is empty)
            ],
            // Whether to polyfill `node:` protocol imports.
            protocolImports: true,
        }),
    ],
    resolve: {
        alias: {
            // The fs polyfill in vite-plugin-node-polyfills is empty; use this, which contains promises needed by datauri
            fs: 'memfs'
        }
    }
});
pnedelko commented 1 year ago

Had the same issue with Nest.js and yarn, when generating a typescript version of code. Switched to the JS version and it works fine, types are still there.

I think it happens because the generated TS code lands to node_modules, but default TS config in Nest.js doesn't compile TS files in node_modules. Probably could be solved by changing tsconfig file. But as JS version works well, I don't care.

ctsstc commented 1 year ago

The original error is due to trying to load ESM in a CommonJS environment. Even with node 18 it requires many hoops to get ESM running and I don't recommend it given the ecosystem is a nightmare of blood, sweat, and tears; it's a time sink in terms of Jest + TS + ESM to get things working properly.

This is a classic error in the node ecosystem trying to import an ESM module outside of your build pipeline [of ESM -> Common JS]. We all often write ESM, but there's normally some transpilation step that turns it into Common JS before loading it through node whether that be Vite, SWC, TS-Node, TS-Jest, etc. You could likely get this working by including the .api directory into the tsconfig includes section to make it part of the transpilation from ESM to Common JS.

As for the fs not found on client-side code that's another problem [given fs is for the server-side] :P

kanadgupta commented 11 months ago

Hey folks 👋🏽 we've been cooking up some exciting stuff for the next major release of api and we'd love if you could provide us with feedback! We've overhauled our code generation strategy so you no longer have to specify your SDK type (ESM, CommonJS, TS, etc.). Thanks to a new build/export strategy that leverages tsup, it should hopefully just work in your modern[^1] JS environment of choice, including NestJS! You can test it out now by running the following:

npx api@next install [your API definition here]

We'd love to hear what you think over at https://github.com/readmeio/api/discussions/791, where I also wrote up a little preview of all the changes coming in api v7 👀

Just note that it's still in beta so we don't recommend using this in production since we may ship more breaking changes as we approach a general release. Thanks y'all!

[^1]: Note that api now requires Node.js v18 or greater if you're a Node.js user, and TypeScript 5.2 if you're a TypeScript user.

chelorope commented 5 months ago

Got the same issues with yarn, nextjs, typescript target. Had to add the generated module to transpilePackages, then update webpack config to replace fs with an empty implementation. But now it's still failing because datauri seems to use fs/promises

nextjs config:

transpilePackages: ['@api/center-api'],
webpack(config) {
  config.resolve.fallback = {
    ...config.resolve.fallback,
    fs: false,
  }

  return config
},

@maggo A simple workaround to solve this issue is to create a file named fs-polyfill.js in your root directory (or any other preferred location), containing the following content:

module.exports = { promises: { readFile: {} } };

and inside the next.config.js file add:

transpilePackages: ['@api/center-api'],
webpack(config) {
  config.resolve.fallback = {
    ...config.resolve.fallback,
    fs: path.join(__dirname, "fs-polyfill.js"),
  }
  return config
},