LinkedSoftwareDependencies / Components.js

🧩 A semantic dependency injection framework
https://componentsjs.readthedocs.io/
Other
41 stars 6 forks source link

Passing a ComponentsManager as Variable #44

Closed woutermont closed 3 years ago

woutermont commented 3 years ago

Not sure if we want this as a feature; more a question whether this would be possible.

This thought arose as an alternative to passing a ComponentsManager through function calls, or keeping it statically reachable. It seems quite obvious that Components.js cannot inject itself, but I wondered whether it could be passed as a variable during instantiation.

For example, take the following component and configuration:

export class SomeService {
  constructor( private managerParam: ComponentsManager<any> )
}
{
    "@context": [ ... ],
    "@graph": [
       ...
       {
         "@id": "urn:SomeServiceId",
         "@type": "SomeService",
         "SomeService:_managerParam": {
            "@id": "urn:variables:managerVariable",
            "@type": "Variable"
          }
       }
       ...
    ]
}

Would it be possible to do the following?

...

const manager = await ComponentsManager.build({ mainModulePath });

await manager.configRegistry.register(configPath);

const settings = { 
    variables: { 
        'urn:variables:managerVariable': manager
    } 
};

const service: SomeService = await manager.instantiate('urn:SomeService', settings);

...

When trying to build this, I currently get stuck on generating the component file of SomeService with components-generator.js, because:

Could not load class or interface ComponentsManager from [path-to-SomeService-dist]/componentsjs:
ENOENT: no such file or directory, open '[path-to-SomeService-dist]/componentsjs.d.ts'

I'm not quite sure what causes components-generator.js to look for components.js types on the path of the service, but I would guess it's because the components for those types should be reachable from there via the context?

Any thoughts on whether this is possible, and whether it would be possible with a generated component of components.js itself? Do such component files already exist somewhere? Can I import them in the local config somehow?

joachimvh commented 3 years ago

I can't comment on why this fails, might be because Components.js also needs the context for objects that are already instantiated.

But one thing you can do is wrap it in a class that can be passed to Components.js as is done in https://github.com/solid/community-server/blob/594cf27696a7c8a59231b8e3e593089816459811/src/pods/generate/BaseComponentsJsFactory.ts

rubensworks commented 3 years ago

When trying to build this, I currently get stuck on generating the component file of SomeService with components-generator.js, because:

The problem you are experiencing is because the generator does not yet support cross-package imports (https://github.com/LinkedSoftwareDependencies/Components-Generator.js/issues/39). But once that's supported, your workflow should be perfectly possible.

As an alternative, @joachimvh's suggestion to work with a wrapper component seems like a good solution to me.