Components.js

6.4.0 · active · verified Sun Apr 19

Components.js is a semantic dependency injection framework for TypeScript and JavaScript projects, leveraging JSON-LD or other RDF serializations for declarative component configuration. It allows developers to define and wire software components using unique, globally identifiable URIs, promoting modular and easily reconfigurable applications. The current stable version is 6.4.0, with major releases occurring periodically, introducing breaking changes primarily related to configuration file syntax and API usage. A key differentiator is its reliance on semantic configuration, enabling dynamic component injection without hard-coding dependencies. This makes it suitable for complex applications requiring flexible component orchestration, such as the Comunica query engine.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to set up a minimal Components.js module, define a class, create a semantic JSON-LD configuration, and then instantiate that class using the ComponentsManager. It includes a simulated `package.json` and TypeScript compilation step for a self-contained example.

import { ComponentsManager } from 'componentsjs';
import { writeFileSync, readFileSync, mkdirSync } from 'node:fs';
import { resolve } from 'node:path';

// Create a dummy TypeScript class and compile it (in a real project, this would be part of your build process)
const myClassCode = `
export class MyClass {
  public readonly name: string;
  constructor(name: string) {
    this.name = name;
  }
}
`;
const tsOutputDirectory = resolve(process.cwd(), 'lib');
mkdirSync(tsOutputDirectory, { recursive: true });
writeFileSync(resolve(tsOutputDirectory, 'my-package.d.ts'), myClassCode);
writeFileSync(resolve(tsOutputDirectory, 'my-package.js'), myClassCode.replace('export class', 'class').replace(/\: string/g, '')); // Basic JS output

// 1. Define package.json (simulating a module)
const packageJson = {
  name: 'my-package',
  version: '2.3.4',
  "lsd:module": true,
  main: 'lib/my-package.js',
  types: 'lib/my-package.d.ts'
};
writeFileSync(resolve(process.cwd(), 'package.json'), JSON.stringify(packageJson, null, 2));

// 2. Create a configuration file
const configContent = `
{
  "@context": [
    "https://linkedsoftwependencies.org/bundles/npm/componentsjs/^6.0.0/components/context.jsonld",
    "https://linkedsoftwependencies.org/bundles/npm/my-package/^2.0.0/components/context.jsonld"
  ],
  "@id": "urn:my-package:myInstance",
  "@type": "MyClass",
  "name": "John Doe"
}
`;
const configPath = resolve(process.cwd(), 'config.jsonld');
writeFileSync(configPath, configContent);

async function runComponentsJs() {
  // In a real setup, `__dirname` would point to the package root, not this script's directory.
  // For this example, we mock `mainModulePath` to the current working directory
  // where we've created the dummy package.json and lib directory.
  const manager = await ComponentsManager.build({
    mainModulePath: process.cwd(),
  });

  await manager.configRegistry.register(configPath);
  const myInstance = await manager.instantiate('urn:my-package:myInstance');

  console.log('Instantiated object:', myInstance);
  console.log('Name property:', myInstance.name);
  
  if (myInstance.name === 'John Doe') {
    console.log('Quickstart successful: Instance created and property accessed.');
  } else {
    console.error('Quickstart failed: Unexpected instance property.');
  }
}

runComponentsJs().catch(console.error);

view raw JSON →