{"id":10657,"library":"componentsjs","title":"Components.js","description":"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.","status":"active","version":"6.4.0","language":"javascript","source_language":"en","source_url":"https://github.com/LinkedSoftwareDependencies/Components.js","tags":["javascript","lsd","linked software dependencies","components","dependency injection","typescript"],"install":[{"cmd":"npm install componentsjs","lang":"bash","label":"npm"},{"cmd":"yarn add componentsjs","lang":"bash","label":"yarn"},{"cmd":"pnpm add componentsjs","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Components.js primarily uses ESM imports since v3 and later, with `require` being a common pitfall.","wrong":"const ComponentsManager = require('componentsjs');","symbol":"ComponentsManager","correct":"import { ComponentsManager } from 'componentsjs';"},{"note":"Used for programmatic compilation of configurations, part of the main `componentsjs` package.","wrong":"const { compileConfig } = require('componentsjs');","symbol":"compileConfig","correct":"import { compileConfig } from 'componentsjs';"},{"note":"The static `build` method is the entry point for creating a ComponentsManager instance, requiring configuration via an options object.","symbol":"build","correct":"await ComponentsManager.build({ mainModulePath: __dirname });"}],"quickstart":{"code":"import { ComponentsManager } from 'componentsjs';\nimport { writeFileSync, readFileSync, mkdirSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\n// Create a dummy TypeScript class and compile it (in a real project, this would be part of your build process)\nconst myClassCode = `\nexport class MyClass {\n  public readonly name: string;\n  constructor(name: string) {\n    this.name = name;\n  }\n}\n`;\nconst tsOutputDirectory = resolve(process.cwd(), 'lib');\nmkdirSync(tsOutputDirectory, { recursive: true });\nwriteFileSync(resolve(tsOutputDirectory, 'my-package.d.ts'), myClassCode);\nwriteFileSync(resolve(tsOutputDirectory, 'my-package.js'), myClassCode.replace('export class', 'class').replace(/\\: string/g, '')); // Basic JS output\n\n// 1. Define package.json (simulating a module)\nconst packageJson = {\n  name: 'my-package',\n  version: '2.3.4',\n  \"lsd:module\": true,\n  main: 'lib/my-package.js',\n  types: 'lib/my-package.d.ts'\n};\nwriteFileSync(resolve(process.cwd(), 'package.json'), JSON.stringify(packageJson, null, 2));\n\n// 2. Create a configuration file\nconst configContent = `\n{\n  \"@context\": [\n    \"https://linkedsoftwependencies.org/bundles/npm/componentsjs/^6.0.0/components/context.jsonld\",\n    \"https://linkedsoftwependencies.org/bundles/npm/my-package/^2.0.0/components/context.jsonld\"\n  ],\n  \"@id\": \"urn:my-package:myInstance\",\n  \"@type\": \"MyClass\",\n  \"name\": \"John Doe\"\n}\n`;\nconst configPath = resolve(process.cwd(), 'config.jsonld');\nwriteFileSync(configPath, configContent);\n\nasync function runComponentsJs() {\n  // In a real setup, `__dirname` would point to the package root, not this script's directory.\n  // For this example, we mock `mainModulePath` to the current working directory\n  // where we've created the dummy package.json and lib directory.\n  const manager = await ComponentsManager.build({\n    mainModulePath: process.cwd(),\n  });\n\n  await manager.configRegistry.register(configPath);\n  const myInstance = await manager.instantiate('urn:my-package:myInstance');\n\n  console.log('Instantiated object:', myInstance);\n  console.log('Name property:', myInstance.name);\n  \n  if (myInstance.name === 'John Doe') {\n    console.log('Quickstart successful: Instance created and property accessed.');\n  } else {\n    console.error('Quickstart failed: Unexpected instance property.');\n  }\n}\n\nrunComponentsJs().catch(console.error);\n","lang":"typescript","description":"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."},"warnings":[{"fix":"Review configuration files and update parameter definitions to use explicit RDF lists for arrays and new parameter range syntax. Consult the official v6 migration guide.","message":"Components.js v6.0.0 introduced breaking changes to parameter range definition within JSON-LD configuration files. Previously, `required` and `unique` flags were used; these have been removed in favor of explicit parameter ranges. Arrays must now be explicitly defined using an RDF list (`@list` in JSON-LD). Incorrectly defined parameters will lead to configuration parsing errors.","severity":"breaking","affected_versions":">=6.0.0"},{"fix":"For upgrades from v4, configurations must be updated to align with the v5 parameter range and RDF list changes. Consult the official v5 migration guide.","message":"Components.js v5.0.0 also introduced significant changes to parameter definition, including the removal of `required` and `unique` flags in favor of parameter ranges, similar to v6. This change also impacted how arrays are handled, requiring explicit RDF list definitions.","severity":"breaking","affected_versions":">=5.0.0 <6.0.0"},{"fix":"Ensure that all `@context` URLs in `config.jsonld` (and other configuration files) use the correct major version range for `componentsjs` and any custom modules. For example, `https://linkedsoftwependencies.org/bundles/npm/componentsjs/^6.0.0/components/context.jsonld`.","message":"Configuration context URLs are version-specific and should always refer to the major version range of a package (e.g., `^6.0.0`). Using an exact version or an incorrect range in `@context` URLs within your JSON-LD configuration can lead to modules and components not being found.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Add `\"lsd:module\": true` to your `package.json` and ensure `componentsjs-generator` is installed as a dev dependency and run as part of your build process, usually via an `npm run build:components` script. Verify the output directory for TypeScript (`.d.ts`) files aligns with the generator's expected input (default `lib/`) or use the `-s` flag.","message":"For Components.js to automatically discover and use your components, your `package.json` must include the `\"lsd:module\": true` entry. Additionally, the `componentsjs-generator` tool (typically run via a build script) is required to generate the necessary component metadata files from your TypeScript (`.d.ts`) or JavaScript source. Skipping these steps will prevent Components.js from finding your defined components.","severity":"gotcha","affected_versions":">=2.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure `npm run build:components` (or equivalent) has been executed after compiling TypeScript/JavaScript. Verify that the generator is targeting the correct source files and outputting metadata to the expected location.","cause":"The `componentsjs-generator` tool has not been run, or its output path is misconfigured, preventing Components.js from discovering the component metadata.","error":"ReferenceError: MyClass is not defined (or similar for other component names)"},{"fix":"Add `\"lsd:module\": true` to the `package.json` of the module containing the component. Double-check that `mainModulePath` passed to `ComponentsManager.build()` correctly points to the root of the npm package.","cause":"Components.js cannot find the module definition. This often happens if `\"lsd:module\": true` is missing from the `package.json` of the component's package, or if `mainModulePath` in `ComponentsManager.build()` is incorrect.","error":"Error: Could not resolve module for component 'urn:my-package:myInstance'"},{"fix":"Ensure your project's `package.json` includes `\"type\": \"module\"` if you intend to use ESM globally, or rename files using `import` to `.mjs`. For older Node.js, stick to CommonJS `require()` or transpile your code.","cause":"Attempting to use ESM `import` syntax in a Node.js environment configured for CommonJS, or in an older Node.js version without proper ESM setup.","error":"SyntaxError: Cannot use import statement outside a module"},{"fix":"Refer to the `CHANGELOG` for your Components.js major version (v5 or v6) and update your component configuration to align with the new parameter range and RDF list requirements. Ensure all array values are explicitly defined with `@list`.","cause":"This error typically indicates that a parameter in your component's configuration (JSON-LD) is not defined correctly according to the current Components.js version's parameter range specification, or an array is not explicitly wrapped in an RDF list (`@list`).","error":"Error: Parameter 'myParameter' has no associated range"}],"ecosystem":"npm"}