{"id":10591,"library":"broccoli-bridge","title":"Broccoli Bridge","description":"The `broccoli-bridge` package, currently at version 1.0.0, provides a specific utility for managing dependencies between Broccoli build system nodes. Its primary function is to allow developers to define dependencies between Broccoli plugins (`nodes`) even when those nodes are instantiated in different parts of an application's codebase or at different times, thus addressing potential circular dependency issues or inconvenient instantiation order. It achieves this by offering `placeholderFor(name)` to create a temporary node and `fulfill(name, node)` to later link that placeholder to an actual Broccoli node. This enables a more flexible composition of complex Broccoli build pipelines. The package has not seen a new major release, remaining at 1.0.0. A key architectural note is its reliance on internal details of the Broccoli `Plugin` API, meaning its stability is inherently tied to the evolution of the core Broccoli project and it carries a risk of breaking changes if Broccoli's internals change.","status":"maintenance","version":"1.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/dfreeman/broccoli-bridge","tags":["javascript"],"install":[{"cmd":"npm install broccoli-bridge","lang":"bash","label":"npm"},{"cmd":"yarn add broccoli-bridge","lang":"bash","label":"yarn"},{"cmd":"pnpm add broccoli-bridge","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"This utility operates within the Broccoli build system and depends on its core APIs and node structure. While not a direct runtime dependency in `package.json`, it is a fundamental peer/conceptual dependency.","package":"broccoli","optional":false}],"imports":[{"note":"The package is published as CommonJS. ESM import syntax is not directly supported by this version (v1.0.0). TypeScript users would typically rely on `@types/broccoli-bridge` for type declarations.","wrong":"import BroccoliBridge from 'broccoli-bridge';","symbol":"BroccoliBridge","correct":"const BroccoliBridge = require('broccoli-bridge');"}],"quickstart":{"code":"class MockBroccoliNode {\n  constructor(name) {\n    this.name = name;\n    this.inputPaths = []; // Mock required property for some Broccoli contexts\n    this.outputPath = `/tmp/broccoli-${name}`;\n  }\n}\n\n// Mock Broccoli Plugin classes for demonstration\nclass PluginA {\n  constructor(inputNodes) {\n    this.inputNodes = inputNodes;\n    this.name = 'PluginA_Node';\n    console.log('PluginA instantiated with inputs:', inputNodes.map(n => n.name || 'placeholder'));\n  }\n  // In a real scenario, PluginA would implement a `build` method.\n}\n\nclass PluginB {\n  constructor(inputNodes) {\n    this.inputNodes = inputNodes;\n    this.name = 'PluginB_Node';\n    console.log('PluginB instantiated with inputs:', inputNodes.map(n => n.name || 'unknown'));\n  }\n  // In a real scenario, PluginB would implement a `build` method.\n}\n\nconst BroccoliBridge = require('broccoli-bridge');\n\n// Stash your bridge instance somewhere central for later access\nlet bridge = new BroccoliBridge();\nconsole.log('BroccoliBridge instance created.\\n');\n\n// Create your `PluginA` instance using a placeholder for PluginB's output\nconst inputOne = new MockBroccoliNode('InputOne');\nconst placeholderForB = bridge.placeholderFor('plugin-b');\nconsole.log('Placeholder for \"plugin-b\" created.');\n\nlet a = new PluginA([\n  inputOne,\n  placeholderForB // PluginA depends on the future output of 'plugin-b'\n]);\nconsole.log('PluginA created, its second input is currently a placeholder.\\n');\n\n// Instantiate PluginB and fulfill the placeholder with its actual instance\nconst inputTwo = new MockBroccoliNode('InputTwo');\nconst inputThree = new MockBroccoliNode('InputThree');\nlet b = new PluginB([inputTwo, inputThree]);\nconsole.log('PluginB created with its own inputs.');\n\nbridge.fulfill('plugin-b', b);\nconsole.log('Placeholder \"plugin-b\" fulfilled with the actual PluginB instance.\\n');\n\n// At this point, if a Broccoli build process were to start,\n// PluginA would correctly receive the output of PluginB\n// via the fulfilled placeholder. The conceptual dependency is resolved.\nconsole.log('During a Broccoli build, PluginA will effectively receive the node named: ' + b.name + ' as its second input.');\nconsole.log('The order of instantiation for PluginA and PluginB did not matter thanks to broccoli-bridge.');","lang":"javascript","description":"Demonstrates how to use `broccoli-bridge` to manage dependencies between Broccoli nodes, allowing for flexible instantiation order by using named placeholders that are later fulfilled."},"warnings":[{"fix":"Monitor Broccoli releases closely for changes that might impact this utility. Consider this package for short-term solutions or prototypes rather than critical, long-term infrastructure. Evaluate direct Broccoli dependency management or alternative build system architectures if long-term stability and maintainability are paramount.","message":"This package explicitly relies on internal, undocumented details of the Broccoli `Plugin` API. This makes it inherently unstable and highly susceptible to breaking changes with any updates to the core Broccoli library, as internal APIs can change without warning or adherence to semantic versioning.","severity":"breaking","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Check the `broccoli` changelog for breaking changes related to its Plugin API. Verify if a newer version of `broccoli-bridge` or a patch exists, or if a manual update to your build configuration is required to adapt to Broccoli's new internal structure.","cause":"The underlying internal Broccoli Plugin API that `broccoli-bridge` relies on has changed, making the placeholders incompatible with how Broccoli nodes are expected to be processed.","error":"TypeError: node.inputPaths is not a function"},{"fix":"Ensure you are using the correct CommonJS `require` syntax: `const BroccoliBridge = require('broccoli-bridge');`.","cause":"This error typically occurs when attempting to use ESM `import` syntax (`import BroccoliBridge from 'broccoli-bridge'`) with `broccoli-bridge` v1.0.0, which is a CommonJS package, or if the `require` statement itself is missing or malformed.","error":"ReferenceError: BroccoliBridge is not defined"},{"fix":"Confirm that every `bridge.placeholderFor(name)` call has a corresponding `bridge.fulfill(name, node)` call with a valid Broccoli node for that exact `name` before your Broccoli build command is executed.","cause":"While `placeholderFor(name)` can be called before `fulfill(name, node)`, the Broccoli build process expects all node dependencies to be resolvable. If a placeholder is created but never fulfilled with an actual Broccoli node before the build begins, it will result in a build-time error.","error":"Error: Placeholder 'some-name' was never fulfilled before build started."}],"ecosystem":"npm"}