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

Bug TypeScript: Runtime error when executing generated code for Graph API #870

Closed
nikithauc opened this issue Nov 23, 2021 · 24 comments · Fixed by #1274
Closed

Bug TypeScript: Runtime error when executing generated code for Graph API #870

nikithauc opened this issue Nov 23, 2021 · 24 comments · Fixed by #1274
Assignees
Labels
type:bug A broken experience

Comments

@nikithauc
Copy link
Contributor

Steps to reproduce:

  1. Generate request builders for Graph v1.0.
  2. Use the generated code to create a request.
  3. Build and run the request

Expected: Result from Graph API.

Actual:

\lib\models\microsoft\graph\listItem.js:11
class ListItem extends baseItem_1.BaseItem {
TypeError: Class extends value undefined is not a constructor or null
@nikithauc nikithauc added the type:bug A broken experience label Nov 23, 2021
@baywet baywet assigned nikithauc and unassigned baywet Nov 23, 2021
@baywet
Copy link
Member

baywet commented Nov 23, 2021

Hey @nikithauc
Please provide more information like:

  • the call you were trying to make
  • the platform you were running on (node/browser)
  • the description you used for the generation

@nikithauc
Copy link
Contributor Author

Sample code :

const meRequestBuilder = client.me;
const me = await meRequestBuilder.get();

Platform: node

Generation command:
kiota.exe -d https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml --language typescript -o src -c GraphServiceClient -n MicrosoftGraph

@baywet
Copy link
Member

baywet commented Nov 24, 2021

thanks for the additional information, just checking you're using the latest version of kiota (building it) rather than downloading the binaries?

@nikithauc
Copy link
Contributor Author

I pulled the latest changes and rebuilt the project. Executed generation command under kiota\src\kiota\bin\Debug\net6.0.

You can find the generated request builders here..

To check the error, you can also clone the repo, switch to the test-cyclic-error branch and run:

  1. yarn install
  2. yarn compile
  3. yarn test

@nikithauc
Copy link
Contributor Author

When running the ESM compilation, the error that I get is

export class ListItem extends BaseItem {
                              
ReferenceError: Cannot access 'BaseItem' before initialization

The errors are liked to circular dependency.

@nikithauc
Copy link
Contributor Author

cc: @sebastienlevert

@sebastienlevert
Copy link
Contributor

I also saw something similar on my first attempt to generate the entire tree of request builders. Does it happen with only specific entities?

@nikithauc
Copy link
Contributor Author

I don't think so.

@nikithauc
Copy link
Contributor Author

nikithauc commented Feb 14, 2022

Used madge to track the circular dependencies.

The error in this issue is caused when a parent class has circular dependency and module loader fails to locate the extended parent class while initiating the child class.

✖ Found 42 circular dependencies!

  1. models/microsoft/graph/roleAssignment.ts > models/microsoft/graph/roleDefinition.ts
  2. models/microsoft/graph/termsAndConditions.ts > models/microsoft/graph/termsAndConditionsAcceptanceStatus.ts
  3. models/microsoft/graph/calendar.ts > models/microsoft/graph/event.ts
  4. models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts
  5. models/microsoft/graph/driveItem.ts > models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts
  6. models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts
  7. models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts > models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts
  8. models/microsoft/graph/notebook.ts > models/microsoft/graph/onenoteSection.ts
  9. models/microsoft/graph/notebook.ts > models/microsoft/graph/onenoteSection.ts > models/microsoft/graph/onenotePage.ts
  10. models/microsoft/graph/onenoteSection.ts > models/microsoft/graph/onenotePage.ts
  11. models/microsoft/graph/notebook.ts > models/microsoft/graph/onenoteSection.ts > models/microsoft/graph/sectionGroup.ts
  12. models/microsoft/graph/onenoteSection.ts > models/microsoft/graph/sectionGroup.ts
  13. models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts > models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts >
    models/microsoft/graph/group.ts > models/microsoft/graph/site.ts
  14. models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/site.ts
  15. models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/site.ts > models/microsoft/graph/contentType.ts
  16. models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/site.ts > models/microsoft/graph/contentType.ts > models/microsoft/graph/documentSet.ts
  17. models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts > models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/site.ts
  18. models/microsoft/graph/driveItem.ts > models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts > models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/site.ts > models/microsoft/graph/itemAnalytics.ts > models/microsoft/graph/itemActivityStat.ts > models/microsoft/graph/itemActivity.ts
  19. models/microsoft/graph/list.ts > models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/site.ts
  20. models/microsoft/graph/group.ts > models/microsoft/graph/site.ts > models/microsoft/graph/termStore/store.ts
  21. models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/site.ts > models/microsoft/graph/termStore/store.ts
  22. models/microsoft/graph/driveItem.ts > models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts > models/microsoft/graph/columnDefinition.ts > models/microsoft/graph/termColumn.ts > models/microsoft/graph/termStore/set.ts > models/microsoft/graph/group.ts > models/microsoft/graph/team.ts > models/microsoft/graph/channel.ts
  23. models/microsoft/graph/group.ts > models/microsoft/graph/team.ts
  24. models/microsoft/graph/termStore/set.ts > models/microsoft/graph/termStore/relation.ts
  25. models/microsoft/graph/termStore/relation.ts > models/microsoft/graph/termStore/term.ts
  26. models/microsoft/graph/termStore/set.ts > models/microsoft/graph/termStore/relation.ts > models/microsoft/graph/termStore/term.ts
  27. models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts
  28. models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts > models/microsoft/graph/listItem.ts
  29. models/microsoft/graph/driveItem.ts > models/microsoft/graph/baseItem.ts > models/microsoft/graph/user.ts > models/microsoft/graph/drive.ts > models/microsoft/graph/list.ts > models/microsoft/graph/listItem.ts
  30. models/microsoft/graph/userActivity.ts > models/microsoft/graph/activityHistoryItem.ts
  31. models/microsoft/graph/driveItem.ts > models/microsoft/graph/internal.ts
  32. models/microsoft/graph/workbookWorksheet.ts > models/microsoft/graph/workbookChart.ts
  33. models/microsoft/graph/workbookNamedItem.ts > models/microsoft/graph/workbookWorksheet.ts
  34. models/microsoft/graph/workbookWorksheet.ts > models/microsoft/graph/workbookPivotTable.ts
  35. models/microsoft/graph/workbookWorksheet.ts > models/microsoft/graph/workbookTable.ts
  36. models/microsoft/graph/educationClass.ts > models/microsoft/graph/educationSchool.ts
  37. models/microsoft/graph/educationClass.ts > models/microsoft/graph/educationSchool.ts > models/microsoft/graph/educationUser.ts
  38. models/microsoft/graph/educationSchool.ts > models/microsoft/graph/educationUser.ts
  39. models/microsoft/graph/accessPackage.ts > models/microsoft/graph/accessPackageCatalog.ts
  40. models/microsoft/graph/riskyUserHistoryItem.ts > models/microsoft/graph/riskyUser.ts
  41. models/microsoft/graph/printTask.ts > models/microsoft/graph/printTaskDefinition.ts
  42. models/microsoft/graph/printer.ts > models/microsoft/graph/printerShare.ts

@sebastienlevert
Copy link
Contributor

What would be the right approach then here? Would it be to create a barrel index.ts file with the right classes in the right order (example, printerShare before printer) or are there any other ways we could solve this? Would the use of interface simplifies this in the future also as they are not transpiled in the generated output? @nikithauc @baywet

@sebastienlevert
Copy link
Contributor

Also adding @RabebOthmani for visibility.

@nikithauc
Copy link
Contributor Author

What would be the right approach then here? Would it be to create a barrel index.ts file with the right classes in the right order (example, printerShare before printer) or are there any other ways we could solve this? Would the use of interface simplifies this in the future also as they are not transpiled in the generated output? @nikithauc @baywet

  • I strongly recommend using interfaces. Definitely solves this issue and more optimal.
  • Adding an index barrel with the right ordering import is a solution but that would fail if there is a circular loop in the inheritance pattern too.
  • We will need an index file irrespective of this problem so that we can export the models.

@baywet
Copy link
Member

baywet commented Feb 15, 2022

Thanks for the patience on this, I haven't had time to look into this in details yet.
If the issue cannot be solved by changing the module types, the ES version output or making a light change on the generation, we could consider doing the following.

  • Models would be represented by both an interface and a class.
  • The inheritance relationship would be ONLY represented via the interfaces, not in the classes. (no more super, which might be the source of our troubles here)
  • The classes would only serve as for the default values and things like additional data manager, backing store & go.
  • The classes would implement their corresponding interface.
  • The classes would have to redefine all the properties in the inheritance tree to properly implement their corresponding interface.
  • Up/down casting would be achieved through the interfaces
  • Properties/fluent API return types/fluent API bodies would be interfaces types (and instantiate the class under the covers), related to Implement constructor to accept partials in typescript to make models initialization easier #1008

Thoughts?

@nikithauc
Copy link
Contributor Author

Do we have a spec on backing store to go through to understand in detail about the need of classes in detail?

@sebastienlevert
Copy link
Contributor

+1 on the ask from @nikithauc here. Also, what are the default values we are talking about? This is a great move forward, but I'm afraid this doesn't solve the underlying issues... Adding @darrelmiller to this thread for a deeper understanding of the requirement for the backing store and help with resolving this issue.

@baywet
Copy link
Member

baywet commented Feb 16, 2022

We do have some documentation here but I'm afraid there's no written spec for the time being.
Default are things like default values for some properties, instantiating the additional property manager so the client doesn't have to do it, instantiating the backing store, etc.

@sebastienlevert
Copy link
Contributor

@baywet, can we split this in 2 parts?

  • Support for interfaces only for our Preview as this would not require backing store yet
  • Support for backing stores (with interfaces and potentially classes) for the v1

This would unlock us to be able to ship a version of the SDK that works on the entire surface. Thanks!

@baywet
Copy link
Member

baywet commented Feb 18, 2022

before we commit to that, I'd like to have time for a few things:

  • investigate whether changing the module types, the ES targets, adding barrels, testing on different JS engines makes any difference, so we have a better understanding of the root cause. I believe @nikithauc is already doing some of that at the moment
  • time to complete adds support for type discriminator during deserialization #1174 as I'm adding infrastructure work to support generating interfaces in this PR (didn't exist previously in Kiota)

@sebastienlevert
Copy link
Contributor

I think some of that work should be done with @nikithauc but I agree with your approach!

@baywet
Copy link
Member

baywet commented Feb 18, 2022

I didn't express myself clearly, apologies. My thoughts were also along the lines of Nikitha exploring the avenues listed in bullet point 1

@sebastienlevert
Copy link
Contributor

Some work happened, yes. But the current state of things is still making things hard. I don't think we achieved anything regarding the circular references, which creates a big road block for us to even explore other ideas. It's not a module or TypeScript thing... It's a JavaScript runtime issue...

@nikithauc
Copy link
Contributor Author

investigate whether changing the module types, the ES targets, adding barrels, testing on different JS engines makes any difference, so we have a better understanding of the root cause. I believe @nikithauc is already doing some of that at the moment

The circular issue exists with ES modules too. I had tested CJS and ES at the time I faced this issue. Sorry I should have mentioned this earlier.

What I am currently working on is generating index.ts (which is also related to #938 ). The exports in the index file should be ordered based on the order of inheritance.

I was able to get through this error with some manual modifications :) but now I am facing a new error :( . Investigating this !

@baywet
Copy link
Member

baywet commented Feb 22, 2022

that good news! thanks for looking into this. Would you mind sharing the details of that new error please?

@nikithauc
Copy link
Contributor Author

nikithauc commented Feb 28, 2022

#1275 this is the new minor error.

With changes in #1274 and #1275 I was able to run the code for the entire API successfully :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:bug A broken experience
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants