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

"Exported APIs cannot use un-exported type", even though the type IS exported #1818

Closed
udondan opened this issue Jul 26, 2020 · 10 comments · Fixed by #1829
Closed

"Exported APIs cannot use un-exported type", even though the type IS exported #1818

udondan opened this issue Jul 26, 2020 · 10 comments · Fixed by #1829
Assignees
Labels
bug This issue is a bug. module/compiler Issues affecting the JSII compiler p1

Comments

@udondan
Copy link
Contributor

udondan commented Jul 26, 2020

🐛 Bug Report

General Information

  • JSII Version: 1.9.0 (build 5c646d5), typescript 3.9.7
  • Platform: MacOS 19.6.0 Darwin Kernel Version 19.6.0: Sun Jul 5 00:43:10 PDT 2020; root:xnu-6153.141.1~9/RELEASE_X86_64 x86_64

What is the problem?

I'm having trouble building a package with multiple exports that depend on one another. One exported class uses another one of the same package. Both classes are exported. JSII though fails with Exported APIs cannot use un-exported type.

For code reference I point to my PR of iam-floyd where I'm facing this problem https://github.com/udondan/iam-floyd/pull/22/files

My package index looks like this:

export { AccessLevel, All, Operator, OperatorModifier } from './shared';
export * from './generated';
export * from './collection';

The ./generated sub-package (do you actually call it like that?) has an export Ec2.

The ./collection sub-package uses this Ec2 Class.

Now when running jsii it complains about Ec2 not being exported:

error TS0: Exported APIs cannot use un-exported type iam-floyd.Ec2

I also tried to:

  • import and use Ec2 directly instead of the index: import {Ec2} from '../generated/amazonec2'
  • export Ec2 in the Collection sub-package, even though it wouldn't be needed outside.
  • Add an explicit export to the index.ts: export { Ec2 } from './generated';

All the same.

Verbose Log

[2020-07-26T13:04:44.007] [DEBUG] jsii/compiler - Creating or updating /Users/daniel.schroeder/code/iam-floyd/tsconfig.json
[2020-07-26T13:04:52.710] [TRACE] jsii/assembler - Processing source file: lib/index.ts
[2020-07-26T13:04:52.713] [TRACE] jsii/assembler - Processing class: .Collection
[2020-07-26T13:04:52.714] [TRACE] jsii/assembler - Processing method: iam-floyd.Collection#allowEc2InstanceDeleteByOwner
[2020-07-26T13:04:52.735] [INFO] jsii/assembler - Registering JSII class: iam-floyd.Collection
[2020-07-26T13:04:52.737] [ERROR] jsii/compiler - Type model errors prevented the JSII assembly from being created
error TS0: Exported APIs cannot use un-exported type iam-floyd.Ec2

Now here's the interesting thing. If I remove the export of Collection from the index.ts file, it runs through, but the verbose output looks like this:

[2020-07-26T13:04:27.755] [DEBUG] jsii/compiler - Creating or updating /Users/daniel.schroeder/code/iam-floyd/tsconfig.json
[2020-07-26T13:04:35.888] [TRACE] jsii/assembler - Processing source file: lib/index.ts
[2020-07-26T13:04:35.892] [TRACE] jsii/assembler - Emitting assembly: /Users/daniel.schroeder/code/iam-floyd/.jsii

Even though the index.ts contains more exports, I do not see them mentioned at all. To me this looks like something is wrong with detecting the other exports. Though the resulting package works and is perfectly usable. We're using the published package in the latest version w/o issues.

@udondan udondan added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jul 26, 2020
@RomainMuller
Copy link
Contributor

Turns out the issue is with how you use export { Name } from './place'; is a syntax style we've not quite been using, and the compiler happens to incorrectly process those...

Basically, the TypeScript compiler does not report the ts.ModifierFlags.Export modifier on the declarations exported this way... because their SyntaxKind is actually ts.SyntaxKind.ExportSpecifier... That's a little silly 🙃

Thankfully, it looks like a trivial fix!

@udondan
Copy link
Contributor Author

udondan commented Jul 29, 2020

Indeed, I've just figured out the other exports are not available in the Python, Nuget, Maven packages. I was just experimenting with the export definitions. export * from './place'; seems to work, because now I get a ton of compile issues I hadn't seen before. 😁

@RomainMuller
Copy link
Contributor

I'm preparing a PR with a fix that'll make the export { ... } from ... declarations be processed correctly.

There's a secondary issue here which is a little trickier... those types you are not exporting from the module's entry point (lib/index.ts) cannot be used anywhere in exported declarations... But their TypeScript AST nodes have the Export modifier (since they are internally exported). The jsii compiler normally erases unexpected types from the exported API definition (so you can have "private base classes" and it "just works", however for those cases it requires the declarations to have @internal as part of their JSDoc.

RomainMuller added a commit that referenced this issue Jul 29, 2020
When specific symbols are exported from a module using the
*ExportDeclaration* syntax:

```ts
export { Foo } from './foo';
```

Those declarations would not be processed at all, because they lack the
`ts.ModifierFlags.Export` modifier (which is to be expected from a
declaration that **is** an export statement).

Added the necessary code (and a test) to ensure these statements are
correctly detected, and the exported symbols are correctly processed
into the output assembly.

Fixes #1818
@udondan
Copy link
Contributor Author

udondan commented Jul 29, 2020

Thanks Romain, that's super helpful. I was preparing a PR on my end with export * and came across those problematic base classes. I just exported them, but keeping them @internal is much better, Thanks!

@RomainMuller
Copy link
Contributor

Yeah - I've been thinking that I'd want the @internal trick to not be necessary (after all, you chose not to export those types from the root), however I ended up thinking that it might be useful to require being explicit about that (maybe you have forgotten to export this type!).

So basically at this point I reckon the error message you'd be getting is awkward and possibly needs improving - but I'm not too sure how to make it relevant & actionnable. I was looking to improve the locality of the source reference of it, too (this usually helps improve actionability of the error message) - but it turns out to be tricky enough that I don't want to commingle in #1829.

@RomainMuller RomainMuller added p1 module/compiler Issues affecting the JSII compiler and removed needs-triage This issue or PR still needs to be triaged. labels Jul 29, 2020
@udondan
Copy link
Contributor Author

udondan commented Jul 29, 2020

Looks like i have a billion issues like method names not allowed by jsii... I think I have to change the complete API of the package. 😆

I tried to set the @internal in the tsdoc, but now it just throws a whole bunch of these lines:

error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithActions
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithActions
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithEffect
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithEffect
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithCondition
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithActions
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithPrincipal
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithResources
error TS0: Exported APIs cannot use un-exported type iam-floyd.PolicyStatementWithResources

Anyway, I'll wait for your PR getting merged then, so I can keep my export statements the way I had them. Maybe this now comes from the export * while at the same time having @internal...

@mergify mergify bot closed this as completed in #1829 Jul 29, 2020
mergify bot pushed a commit that referenced this issue Jul 29, 2020
When specific symbols are exported from a module using the
*ExportDeclaration* syntax:

```ts
export { Foo } from './foo';
```

Those declarations would not be processed at all, because they lack the
`ts.ModifierFlags.Export` modifier (which is to be expected from a
declaration that **is** an export statement).

Added the necessary code (and a test) to ensure these statements are
correctly detected, and the exported symbols are correctly processed
into the output assembly.

Fixes #1818



---

By submitting this pull request, I confirm that my contribution is made under the terms of the [Apache 2.0 license].

[Apache 2.0 license]: https://www.apache.org/licenses/LICENSE-2.0
@udondan
Copy link
Contributor Author

udondan commented Aug 7, 2020

Thanks @RomainMuller - I tested this today 👍

@icj217
Copy link
Contributor

icj217 commented Sep 14, 2022

This issue seems to have cropped back up for me despite using versions of JSII well past when the fix was introduced

// from package.json
"jsii": "^1.63.2",
"jsii-diff": "^1.63.2",
"jsii-docgen": "^7.0.67",
"jsii-pacmak": "^1.63.2"

Given the following directory structure:

/src
   index.ts
   /modules
      index.ts
      /payload-storage
         index.ts
         payload-storage.ts

And the following export statements:

// src/index.ts
export * as modules from './modules';

// src/modules/index.ts
export * from './payload-storage';

// src/modules/payload-storage/index.ts
export { MyConstruct, MyConstructProps } from './payload-storage';

I get this error:

👾 build » compile | jsii --silence-warnings=reserved-word
[2022-09-14T15:59:16.455] [ERROR] jsii/compiler - Type model errors prevented the JSII assembly from being created
src/modules/payload-storage/payload-storage.ts:66:53 - error JSII3000: Exported APIs cannot use un-exported type "@<organization>/<my-module-name>.MyConstructProps"

66   constructor(scope: Construct, id: string, props?: MyConstructProps) {
                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~
👾 Task "build » compile" failed when executing "jsii --silence-warnings=reserved-word"

@ganeshgk
Copy link

@icj217 were you able to fix this? I got a similar issue for cdk8s

@icj217
Copy link
Contributor

icj217 commented Apr 24, 2024

@ganeshgk I was not. I ended up doing a * export instead of enumerating the specific classes/types. I'm not sure if the modules folder was also messing things up, since I now use the following dir structure:

/src
    index.ts
    /payload-storage
       index.ts
       payload-storage.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. module/compiler Issues affecting the JSII compiler p1
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants