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

Singletons are not singletons in Typescript #1244

Open
andreaTP opened this issue Jun 21, 2024 · 4 comments
Open

Singletons are not singletons in Typescript #1244

andreaTP opened this issue Jun 21, 2024 · 4 comments
Labels
bug Something isn't working type:bug A broken experience

Comments

@andreaTP
Copy link
Contributor

In Apicurio Registry we are attempting to use the client SDK generated for Typescript ( link ).

More specifically, we are following the consolidated pattern of:

  • generating the SDK standalone (we will publish it eventually)
  • use it as a package from the UI application

Although we started running into issues:
Screenshot from 2024-06-21 15-46-31

After much research and debugging we found out that ParseNodeFactoryRegistry.defaultInstance doesn't always refer to the same object, and, depending on: "from which module are you invoking it" you get a different instance of it ( there are multiple resources in SO that refer to this e.g. ).

Workaround

Running kiota generate --serializer none --deserializer none and registering manually the serializers and deserializers in the end module, i.e.:

const pnfr = new ParseNodeFactoryRegistry();
const json = new JsonParseNodeFactory();
...
    
pnfr.contentTypeAssociatedFactories.set(json.getValidContentType(), json);
...

new FetchRequestAdapter(new AnonymousAuthenticationProvider(), pnfr, ...);

Solution?

This bug is hard to discover and track down, and it easily compromises the "getting started" experience.
There are a few options on how to solve it, but I'm happy to listen to a proposal from someone more expert than me in TS.

@github-project-automation github-project-automation bot moved this to Needs Triage 🔍 in Kiota Jun 21, 2024
@andreaTP
Copy link
Contributor Author

cc. @EricWittmann

@baywet
Copy link
Member

baywet commented Jun 21, 2024

Thanks for bringing this up. It's most likely caused because the bundled application actually has two copies of the abstractions, and yes that's a pain. Hard to investigate for people new to kiota and/or to JavaScript.

As part of making the clients truly portable, we're planning to build bundle packages which would do two things:

  • refer to abstractions + all the default implementations (except for auth maybe)
  • register the serialization providers (through a derived request adapter, not through the singleton registry anymore)
    This should solve this issue. We'll still have a singleton for the backing store factory, which could pause similar issues, but we don't have plans for that yet.

@baywet baywet added bug Something isn't working type:bug A broken experience labels Jun 21, 2024
@baywet baywet moved this from Needs Triage 🔍 to Todo 📃 in Kiota Jun 21, 2024
@andreaTP
Copy link
Contributor Author

It's most likely caused because the bundled application actually has two copies of the abstractions

Haven't realized! Why?

register the serialization providers through a derived request adapter

Do you mean attaching the defaultInstance to the adapter?
In this case, everything will flow from the instantiation of the adapter.
Would this work even in case instantiation happens in a factory distributed along the SDK? I mean in a separate module.

@baywet
Copy link
Member

baywet commented Jun 21, 2024

Haven't realized! Why?

If you run npm list @microsoft/kiota-abstractions (or equivalent with your package manager) it's likely that it'll list two versions that haven't been deduped.

Do you mean attaching the defaultInstance to the adapter?

No I meant basically moving the code that's in the client now to register the providers to this new adapter's constructor. And change it a little bit so it'd:

  1. accept providers passed to the constructor by the developer, and use those if any.
  2. if none, use what's in the default instance if any.
  3. if none, use the providers to register, and set that for the default instance at the same occasion.

Would this work even in case instantiation happens in a factory distributed along the SDK? I mean in a separate module.

I'm not sure I follow the question?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working type:bug A broken experience
Projects
Status: Todo 📃
Development

No branches or pull requests

2 participants