Overview

When using Components.js in a TypeScript project, several steps can be skipped compared to using Components.js in pure JavaScript.

In order to inject dependencies with Components.js in non-TypeScript projects, several elements are required:

  1. Setup module and component generation
  2. Component configuration file
  3. Programatic instantiation

These will be explained in detail in the following sections.

1. Setup module and component generation

Using the componentsjs-generator tool, our declarative components from our TypeScript classes.

1. Install as a dev dependency

npm install -D componentsjs-generator

or

yarn add -D componentsjs-generator

2. Declare components in package.json

If you are already using Components.js, you already have this.

Add the following entry to package.json:

{
  ...
  "lsd:module": true,
  ...
}

3. (optional) Add generate script

Call componentsjs-generator as a npm script by adding a scripts entry to your package.json:

{
  ...,
  "scripts": {
    ...
    "build": "npm run build:ts && npm run build:components",
    "build:ts": "tsc",
    "build:components": "componentsjs-generator",
    "prepare": "npm run build",
    ...
  }
}

This is only a recommended way of calling componentsjs-generator, you are free to call it in a different way that better suits your pipeline. By default, componentsjs-generator will output generated components into the components/ directory.

Please refer to the README of componentsjs-generator for more details on how to change the default options of this tool.

4. (optional) Ignore generated components files

Since we automatically generate the components files, we do not have to check them into version control systems like git. So we can add the following line to .gitignore:

components

If you do this, make sure that the components folder is published to npm by adding the following to your package.json:

{
  ...
  "files": [
    ....
    "components/**/*.jsonld",
    "config/**/*.json",
    ....
  ],
  ....
}

2. Component configuration file

Component configuration files represent the semantic instantiation of a component. These can look as follows:

{
  "@context": [
    "https://linkedsoftwaredependencies.org/bundles/npm/componentsjs/^6.0.0/components/context.jsonld",
    "https://linkedsoftwaredependencies.org/bundles/npm/my-package/^2.0.0/components/context.jsonld"
    { "ex": "http://example.org/" }
  ],
  "@id": "ex:myInstance",
  "@type": "MyComponent",
  "MyComponent:_name": "John"
}

This config file represents the instantiation of the class MyComponent with the parameter name set to "John". As mentioned in Home, you can also write "name": "John" (which is the more preferred way) instead of "MyComponent:_name": "John" for the same purpose.

In order to refer to this declarative instantiation later, it must have a unique @id URI.

The @type of our instance ex:myInstance simply refers to the component that must be instantiated, which is MyComponent in this case.

The parameters that were defined by the component in its config file, can now be used as keys in the configuration file.

The context file for the module is normally generated by invoking componentsjs-generator. See here for more information on context lookup.

More details on component instantiation and on how to instantiate classes that have no explicit components file can be found here.

3. Programatic instantiation

Up until now, modules and components are just defined semantically, and can be created without any external dependencies. However, in order to instantiate such declarative components programamatically, Components.js must be installed as a dependency.

Note

The npm package name of Components.js is componentsjs.

Components.js exposes a ComponentsManager module, which is responsible for loading modules, components and instantiating them. A new components manager instance is simply created as follows:

import { ComponentsManager } from 'componentsjs';

const manager = await ComponentsManager.build({
  mainModulePath: __dirname, // Path to your npm package's root
  moduleLoader: (registry) => registry.registerModule('path/or/url/to/my-module.jsonld'),
});

The invocation of registry.registerModule will register our module and all discoverable attached components. All other available registration methods can be found at here.

In order to instantiate a component, we must first register its declarative config file:

await manager.configRegistry.register('path/or/url/to/config-my-component.jsonld');

Next, we create an actual instantiation of our declarative config instance:

const myInstance = await manager.instantiate('http://example.org/myInstance');

The instantiate method takes as first argument the IRI (@id) of a component configuration. This method resolves to an instance of the given component, as it has been instantiated according to the config file. In this example, the MyComponent constructor as exported by my-module will be called with single argument "John".

All other available instantiation methods can be found at here.

Example Source