I've been struggling to come up with this system architecture for a while now and got to a point where I thought it was perfect. The whole specification is fairly straightforward. We have something called an Extensions, holding core functionalities to interact with an API:
export abstract class Extension<ConfigType extends object, DataType extends object> {
    constructor(public definition: ExtensionDefinition<ConfigType, DataType>) {
        this.definition = definition;
    }
    abstract initilize(): this;
    abstract APIFetchSessionByID(sessionId: string) : Promise<ExtensionSession<ConfigType, DataType>>;
    abstract APIFetchSessionByToken(token: string) : Promise<ExtensionSession<ConfigType, DataType>>;
    abstract doSomethingAmazing() : any;
}
We then come into the main problem known as the ExtensionDefinition, holding the raw JSON data about the the extension we are creating: configuration, data, name, description....
export class ExtensionDefinition<ConfigType extends object, DataType extends object> implements IExtensionProperties<ConfigType, DataType> {
    constructor(data: IExtensionProperties<ConfigType, DataType>) {
        Object.assign(this, data);
    }
}
The problem occurs when we realise that the data passed in the ExtensionDefinition is asynchronous and stored on a third-party API and only needs to be obtained once or until the definition is changed. My current solution stores this data in a .JSON and I simply pass the data from the JSON file directly into the ExtensionDefinition constructor where I plan on updating the third-party API on start-up. This works but causes lots more errors than it solves. For example, the ExtensionDefinition data retrieved from the API is configurable via the API so if anything new is introduce, a fix needs to be implemented.
For further context, I have a service that manages and maintains all these extensions:
APIApplication.initilize({
    clientId: process.env.CLIENT_ID!,
    clientSecret: process.env.CLIENT_SECRET!,
    devToken: process.env.DEV_TOKEN!,
    tokenURL: "...URL",
    authorizationURL: "...URL",
    extensions: [
        new ExampleExtension(),
        new ExampleExtension(),
        new ExampleExtension(),
        ...MORE
    ]
});
A lot of other workarounds ive thought of have worked better but get slowed down by JavaScript inability to await asynchronous data in a class constructor. Some include passing the ExtensionDefinition as a promise and awaiting the property when needed which works but isnt ideal as I would need to obtain each definition individually from the API, resulting in a lot of overhead.
The entire application depends on these extensions so without them it wouldnt function. I can imagine this is a common problem that many developers have encountered and may have already tackled this problem and come up with a better solution.
