ng-openapi-gen icon indicating copy to clipboard operation
ng-openapi-gen copied to clipboard

Re-exporting a type when 'isolatedModules' is enabled requires using 'export type'. [plugin angular-compiler]

Open marcschroeder opened this issue 1 year ago • 6 comments

Angular seems to default to "isolatedModules": true.

This causes an issue for the generated files:

X [ERROR] TS1205: Re-exporting a type when 'isolatedModules' is enabled requires using 'export type'. [plugin angular-compiler]

Is there a workaround available or should the export be changed to "export type"? Happy to provide a PR if the requirements are clear.

marcschroeder avatar Sep 14 '24 07:09 marcschroeder

One of the highlights in the README:

Generated files should compile using strict TypeScript compiler flags [...]

That's why I expected this scenario to already be handled. Would be great if this could be handled by the library.

I'm willing to provide help with this issue as well if required.

xDivisionByZerox avatar Oct 09 '24 14:10 xDivisionByZerox

Here is my temporary fix. Create a new file "fix-openapi-exports.js"

const path = require('path');

// Define the directory where ng-openapi-gen generates files
const dir = './src/app/api'; // Adjust this path to match your actual generated directory

function updateExports(directory) {
  fs.readdir(directory, (err, files) => {
    if (err) throw err;

    files.forEach(file => {
      const filePath = path.join(directory, file);
      if (fs.lstatSync(filePath).isDirectory()) {
        // Recursively update exports in subdirectories
        updateExports(filePath);
      } else if (file.endsWith('.ts')) {
        // Read the TypeScript file
        fs.readFile(filePath, 'utf8', (err, data) => {
          if (err) throw err;

          const updatedData = data.replace(/export \{ ([\w, ]+) \} from/g, 'export type { $1 } from');

          // Write the updated content back to the file
          fs.writeFile(filePath, updatedData, 'utf8', err => {
            if (err) throw err;
            console.log(`Updated exports in: ${filePath}`);
          });
        });
      }
    });
  });
}
updateExports(dir);

then you add "post-process-openapi": "node fix-openapi-exports.js", to your package.json

for reference, my scripts are as follows

"post-process-openapi": "node fix-openapi-exports.js",
"api": "ng-openapi-gen -c swagger-gen.json && npm run post-process-openapi"

cjackson234 avatar Oct 10 '24 04:10 cjackson234

The easiest fix is to use a custom template for it. Just create a folder in your project, copy the modelIndex.handlebars file from the original templates and reference that folder in you ng-openapi-gen.json file ("templates": "your-folder"). Then modify that file and add the type to exports.

I'll have to think in a solution for this, because by default ng-openapi-gen generates model enums as actual typescript enums with pascal case. Those are not strict type aliases, but actual enum classes, and exporting them as type would result in build errors.

Another option is to skip the model index altogether (you can disable its generation in the configuration options) and deep-import all entities directly.

luisfpg avatar Oct 14 '24 17:10 luisfpg

For your interest, I do this in TypeScript. That could be interesting as an alternative to @cjackson234 answer if you want to keep only TypeScript in your project:

import fs from 'fs';
import path from 'path';

const modelsPath = path.join(__dirname, '..', 'src', 'app', 'api', 'models.ts');
const models = fs.readFileSync(modelsPath, 'utf-8');
const fixedModels = models.replace(/^export\s+/gm, 'export type ');
fs.writeFileSync(modelsPath, fixedModels);

I only added this in a "scripts" directory at the project root, and added this in my package.json file:

  "scripts": {
    "openapi": "npm run openapi:gen && npm run openapi:fix",
    "openapi:gen": "ng-openapi-gen --input http://localhost:8000/api/schema",
    "openapi:fix": "tsx scripts/fixup-models.ts",

metal3d avatar Oct 28 '24 22:10 metal3d

(of course, I added tsx in devDependencies: npm install --save-dev tsx)

metal3d avatar Oct 28 '24 22:10 metal3d

I was able to work around this issue by changing the import so that the reexport is never loaded by typescript/angular

-import { User } from '../api/models';
+import { User } from '../api/models/user';

or alternatively

"scripts": {
  "api": "ng-openapi-gen --input myInput.yaml --output src/app/api && rm src/app/api/models.ts"
},

So you can't even import from the wrong place. Better if you have multiple devs working

aceArt-GmbH avatar Feb 17 '25 15:02 aceArt-GmbH

this seems to be resolved with #344 right?

aceArt-GmbH avatar May 09 '25 12:05 aceArt-GmbH

Yes I think you are right - should be fixed. I will see if I can also have a test sometime. If it's not working yet I will reopen the ticket.

EDIT: Can confirm - setting isolatedModules to true fails for version 52 but works great for 53. Thanks @mumenthalers!

marcschroeder avatar May 09 '25 13:05 marcschroeder