{"_id":"@openfeature/multi-provider","_rev":"6-c659855dd0971024b904e34625ed2cfb","name":"@openfeature/multi-provider","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.1":{"name":"@openfeature/multi-provider","version":"0.1.1","_id":"@openfeature/multi-provider@0.1.1","maintainers":[{"name":"beeme1mr","email":"beeme1mr@gmail.com"},{"name":"toddbaert","email":"toddbaert@gmail.com"}],"dist":{"shasum":"9244a33592c4c6649b8bf3624e0d9f25d0cf9c7d","tarball":"https://registry.npmjs.org/@openfeature/multi-provider/-/multi-provider-0.1.1.tgz","fileCount":20,"integrity":"sha512-yrFYIKkoBK9DHmU80HFTXMxZx5QkIvW5uC5ePHf1Rvbh4GgnATnaAYmTkjUTs9kfmW2STEtnxQVYwTD09K5tAg==","signatures":[{"sig":"MEQCIF6AeqpR7j32eSolPILjl4tScTuI2YSELjIboY3oyTL2AiBVCBDcslnxXvmRvIDoNVEODtnmQZQp8v2MWhFgZ+mSyw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":75518},"main":"./index.cjs.js","module":"./index.esm.js","exports":{".":{"import":"./index.cjs.mjs","module":"./index.esm.js","default":"./index.cjs.js"},"./package.json":"./package.json"},"gitHead":"c68695e5328fe2f250b78a4d625b72421c2b1633","scripts":{"current-version":"echo $npm_package_version","publish-if-not-exists":"cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi"},"typings":"./src/index.d.ts","_npmUser":{"name":"beeme1mr","email":"beeme1mr@gmail.com"},"_npmVersion":"10.7.0","description":"The Multi-Provider allows you to use multiple underlying providers as sources of flag data for the OpenFeature server SDK. When a flag is being evaluated, the Multi-Provider will consult each underlying provider it is managing in order to determine the fi","directories":{},"_nodeVersion":"18.20.3","dependencies":{"tslib":"^2.3.0"},"_hasShrinkwrap":false,"peerDependencies":{"@openfeature/server-sdk":"^1.6.0"},"_npmOperationalInternal":{"tmp":"tmp/multi-provider_0.1.1_1717699435327_0.6812892702648607","host":"s3://npm-registry-packages"},"deprecated":"This package is deprecated. The Multi-Provider is now included in @openfeature/server-sdk. Please migrate to use the SDK directly."},"0.1.2":{"name":"@openfeature/multi-provider","version":"0.1.2","_id":"@openfeature/multi-provider@0.1.2","maintainers":[{"name":"toddbaert","email":"toddbaert@gmail.com"},{"name":"beeme1mr","email":"beeme1mr@gmail.com"}],"dist":{"shasum":"f68f3605b390f6927b7d52f3dd35f88273e87f9f","tarball":"https://registry.npmjs.org/@openfeature/multi-provider/-/multi-provider-0.1.2.tgz","fileCount":20,"integrity":"sha512-u9pOekclHeRs7TEFY1wbVhFcSNl7VarJOjy8aoZcKIABujVcRKFZ2ZDuFOwFOfrn4trZ0adg/XNWq7sgBQVm5Q==","signatures":[{"sig":"MEUCIF+E5guTsSNYn0kfkIa9D83SUVdp1nhMD6o2mJ6fvcw+AiEAnE1JZKzGBSlG5GsSNbkXyGYsHNsrHuUU5gmo6ZyNss4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76834},"main":"./index.cjs.js","module":"./index.esm.js","exports":{".":{"import":"./index.cjs.mjs","module":"./index.esm.js","default":"./index.cjs.js"},"./package.json":"./package.json"},"gitHead":"06ffd65fb3dbc180953104d31cd4c7e68e6ac498","scripts":{"current-version":"echo $npm_package_version","publish-if-not-exists":"cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi"},"typings":"./src/index.d.ts","_npmUser":{"name":"beeme1mr","email":"beeme1mr@gmail.com"},"_npmVersion":"10.8.2","description":"The Multi-Provider allows you to use multiple underlying providers as sources of flag data for the OpenFeature server SDK. When a flag is being evaluated, the Multi-Provider will consult each underlying provider it is managing in order to determine the fi","directories":{},"_nodeVersion":"18.20.5","dependencies":{"tslib":"^2.3.0"},"_hasShrinkwrap":false,"peerDependencies":{"@openfeature/server-sdk":"^1.17.0"},"_npmOperationalInternal":{"tmp":"tmp/multi-provider_0.1.2_1735050735035_0.04456076167687861","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is deprecated. The Multi-Provider is now included in @openfeature/server-sdk. Please migrate to use the SDK directly."},"0.1.3":{"name":"@openfeature/multi-provider","version":"0.1.3","license":"Apache-2.0","_id":"@openfeature/multi-provider@0.1.3","maintainers":[{"name":"toddbaert","email":"toddbaert@gmail.com"},{"name":"beeme1mr","email":"beeme1mr@gmail.com"},{"name":"lukas.reining","email":"lukas.reining@aol.com"},{"name":"jonathannorris","email":"jonathannorris@gmail.com"}],"dist":{"shasum":"fe62426cdea106f09e1f4eefd62693dc136184c0","tarball":"https://registry.npmjs.org/@openfeature/multi-provider/-/multi-provider-0.1.3.tgz","fileCount":21,"integrity":"sha512-XpHVg0c9B5e28vtfnoOEGFTbAPuUZXF/vSS0RB576lmml2jW9zhYgbimvcJzK4YQ3HSh1KdOAC9bubaND4LmNw==","signatures":[{"sig":"MEQCIGTRsbSVj4m5eFJt7knhSvsFW9Jxmlsj6qNTF5k5ZilEAiAWyWGLBmeGPhRr3jQDQ0ZZ1dd93paeNU+512vttptySw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":87105},"main":"./index.cjs.js","types":"./index.esm.d.ts","module":"./index.esm.js","exports":{".":{"types":"./index.esm.d.ts","import":"./index.cjs.mjs","module":"./index.esm.js","default":"./index.cjs.js"},"./package.json":"./package.json"},"gitHead":"3b052eae1751103c45fb5f3cea9e2ed471c8f834","scripts":{"current-version":"echo $npm_package_version","publish-if-not-exists":"cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi"},"typings":"./src/index.d.ts","_npmUser":{"name":"toddbaert","email":"toddbaert@gmail.com"},"deprecated":"This package is deprecated. The Multi-Provider is now included in @openfeature/server-sdk. Please migrate to use the SDK directly.","_npmVersion":"11.6.1","description":"> **⚠️ DEPRECATED**: This package is deprecated. The Multi-Provider is now included in `@openfeature/server-sdk`. Please migrate to use the SDK directly. See [Multi-Provider in @openfeature/server-sdk](https://github.com/open-feature/js-sdk/blob/main/pack","directories":{},"_nodeVersion":"24.10.0","dependencies":{},"_hasShrinkwrap":false,"peerDependencies":{"@openfeature/server-sdk":"^1.17.0"},"_npmOperationalInternal":{"tmp":"tmp/multi-provider_0.1.3_1761326210441_0.7692634386471633","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2024-06-06T18:43:55.202Z","modified":"2025-10-24T17:18:23.043Z","0.1.1":"2024-06-06T18:43:55.491Z","0.1.2":"2024-12-24T14:32:15.210Z","0.1.3":"2025-10-24T17:16:50.615Z"},"license":"Apache-2.0","description":"> **⚠️ DEPRECATED**: This package is deprecated. The Multi-Provider is now included in `@openfeature/server-sdk`. Please migrate to use the SDK directly. See [Multi-Provider in @openfeature/server-sdk](https://github.com/open-feature/js-sdk/blob/main/pack","maintainers":[{"name":"beeme1mr","email":"beeme1mr@gmail.com"},{"name":"jonathannorris","email":"jonathannorris@gmail.com"},{"name":"lukas.reining","email":"lukas.reining@aol.com"},{"name":"toddbaert","email":"toddbaert@gmail.com"}],"readme":"# OpenFeature Multi-Provider\n\n> **⚠️ DEPRECATED**: This package is deprecated. The Multi-Provider is now included in `@openfeature/server-sdk`. Please migrate to use the SDK directly. See [Multi-Provider in @openfeature/server-sdk](https://github.com/open-feature/js-sdk/blob/main/packages/server/README.md#multi-provider).\n\nThe Multi-Provider allows you to use multiple underlying providers as sources of flag data for the OpenFeature server SDK.\nWhen a flag is being evaluated, the Multi-Provider will consult each underlying provider it is managing in order to determine\nthe final result. Different evaluation strategies can be defined to control which providers get evaluated and which result is used.\n\nThe Multi-Provider is a powerful tool for performing migrations between flag providers, or combining multiple providers into a single\nfeature flagging interface. For example:\n\n- *Migration*: When migrating between two providers, you can run both in parallel under a unified flagging interface. As flags are added to the\nnew provider, the Multi-Provider will automatically find and return them, falling back to the old provider if the new provider does not have\n- *Multiple Data Sources*: The Multi-Provider allows you to seamlessly combine many sources of flagging data, such as environment variables,\nlocal files, database values and SaaS hosted feature management systems.\n\n## Installation\n\n```bash\n$ npm install @openfeature/multi-provider\n```\n\n> [!TIP]\n> This provider is designed to be used with the [Node.js SDK](https://openfeature.dev/docs/reference/technologies/server/javascript/).\n\n## Usage\n\nThe Multi-Provider is initialized with an array of providers it should evaluate:\n\n```typescript\nimport { MultiProvider } from '@openfeature/multi-provider'\nimport { OpenFeature } from '@openfeature/server-sdk'\n\nconst multiProvider = new MultiProvider([\n  { provider: new ProviderA() },\n  { provider: new ProviderB() }\n])\n\nawait OpenFeature.setProviderAndWait(multiProvider)\n\nconst client = OpenFeature.getClient()\n\nconsole.log(\"Evaluating flag\")\nconsole.log(await client.getBooleanDetails(\"my-flag\", false));\n```\n\nBy default, the Multi-Provider will evaluate all underlying providers in order and return the first successful result. If a provider indicates\nit does not have a flag (FLAG_NOT_FOUND error code), then it will be skipped and the next provider will be evaluated. If any provider throws\nor returns an error result, the operation will fail and the error will be thrown. If no provider returns a successful result, the operation\nwill fail with a FLAG_NOT_FOUND error code.\n\nTo change this behaviour, a different \"strategy\" can be provided:\n\n```typescript\nimport { MultiProvider, FirstSuccessfulStrategy } from '@openfeature/multi-provider'\n\nconst multiProvider = new MultiProvider(\n    [\n      { provider: new ProviderA() },\n      { provider: new ProviderB() }\n    ], \n    new FirstSuccessfulStrategy()\n)\n```\n\nThe Multi-Provider comes with three strategies out of the box:\n\n- `FirstMatchStrategy` (default): Evaluates all providers in order and returns the first successful result. Providers that indicate FLAG_NOT_FOUND error will be skipped and the next provider will be evaluated. Any other error will cause the operation to fail and the set of errors to be thrown.\n- `FirstSuccessfulStrategy`: Evaluates all providers in order and returns the first successful result. Any error will cause that provider to be skipped.\nIf no successful result is returned, the set of errors will be thrown.\n- `ComparisonStrategy`: Evaluates all providers in parallel. If every provider returns a successful result with the same value, then that result is returned.\nOtherwise, the result returned by the configured \"fallback provider\" will be used. When values do not agree, an optional callback will be executed to notify\nyou of the mismatch. This can be useful when migrating between providers that are expected to contain identical configuration. You can easily spot mismatches\nin configuration without affecting flag behaviour.\n\nThis strategy accepts several arguments during initialization:\n\n```typescript\nimport { MultiProvider, ComparisonStrategy } from '@openfeature/multi-provider'\n\nconst providerA = new ProviderA()\nconst multiProvider = new MultiProvider(\n  [\n    { provider: providerA },\n    { provider: new ProviderB() }\n  ],\n  new ComparisonStrategy(providerA, (details) => {\n      console.log(\"Mismatch detected\", details)\n  })\n)\n```\n\nThe first argument is the \"fallback provider\" whose value to use in the event that providers do not agree. It should be the same object reference as one of the providers in the list. The second argument is a callback function that will be executed when a mismatch is detected. The callback will be passed an object containing the details of each provider's resolution, including the flag key, the value returned, and any errors that were thrown.\n\n## Tracking Support\n\nThe Multi-Provider supports tracking events across multiple providers. When you call the `track` method, it will by default send the tracking event to all underlying providers that implement the `track` method.\n\n```typescript\nimport { OpenFeature } from '@openfeature/server-sdk'\nimport { MultiProvider } from '@openfeature/multi-provider'\n\nconst multiProvider = new MultiProvider([\n  { provider: new ProviderA() },\n  { provider: new ProviderB() }\n])\n\nawait OpenFeature.setProviderAndWait(multiProvider)\nconst client = OpenFeature.getClient()\n\n// Tracked events will be sent to all providers by default\nclient.track('purchase', { targetingKey: 'user123' }, { value: 99.99, currency: 'USD' })\n```\n\n### Tracking Behavior\n\n- **Default**: All providers receive tracking calls by default\n- **Error Handling**: If one provider fails to track, others continue normally and errors are logged\n- **Provider Status**: Providers in `NOT_READY` or `FATAL` status are automatically skipped\n- **Optional Method**: Providers without a `track` method are gracefully skipped\n\n### Customizing Tracking with Strategies\n\nYou can customize which providers receive tracking calls by overriding the `shouldTrackWithThisProvider` method in your custom strategy:\n\n```typescript\nimport { BaseEvaluationStrategy, StrategyPerProviderContext } from '@openfeature/multi-provider'\n\nclass CustomTrackingStrategy extends BaseEvaluationStrategy {\n  shouldTrackWithThisProvider(\n    strategyContext: StrategyPerProviderContext,\n    context: EvaluationContext,\n    trackingEventName: string,\n    trackingEventDetails: TrackingEventDetails,\n  ): boolean {\n    // Only track with the primary provider\n    if (strategyContext.providerName === 'primary-provider') {\n      return true;\n    }\n    \n    // Skip tracking for analytics events on backup providers\n    if (trackingEventName.startsWith('analytics.')) {\n      return false;\n    }\n    \n    return super.shouldTrackWithThisProvider(strategyContext, context, trackingEventName, trackingEventDetails);\n  }\n}\n```\n\n## Custom Strategies\n\nIt is also possible to implement your own strategy if the above options do not fit your use case. To do so, create a class which implements the \"BaseEvaluationStrategy\":\n\n```typescript\nexport abstract class BaseEvaluationStrategy {\n    public runMode: 'parallel' | 'sequential' = 'sequential';\n\n    abstract shouldEvaluateThisProvider(strategyContext: StrategyPerProviderContext, evalContext: EvaluationContext): boolean;\n\n    abstract shouldEvaluateNextProvider<T extends FlagValue>(\n        strategyContext: StrategyPerProviderContext,\n        context: EvaluationContext,\n        result: ProviderResolutionResult<T>,\n    ): boolean;\n\n    abstract shouldTrackWithThisProvider(\n        strategyContext: StrategyPerProviderContext,\n        context: EvaluationContext,\n        trackingEventName: string,\n        trackingEventDetails: TrackingEventDetails,\n    ): boolean;\n\n    abstract determineFinalResult<T extends FlagValue>(\n        strategyContext: StrategyEvaluationContext,\n        context: EvaluationContext,\n        resolutions: ProviderResolutionResult<T>[],\n    ): FinalResult<T>;\n}\n```\n\nThe `runMode` property determines whether the list of providers will be evaluated sequentially or in parallel.\n\nThe `shouldEvaluateThisProvider` method is called just before a provider is evaluated by the Multi-Provider. If the function returns `false`, then\nthe provider will be skipped instead of being evaluated. The function is called with details about the evaluation including the flag key and type.\nCheck the type definitions for the full list.\n\nThe `shouldEvaluateNextProvider` function is called after a provider is evaluated. If it returns `true`, the next provider in the sequence will be called,\notherwise no more providers will be evaluated. It is called with the same data as `shouldEvaluateThisProvider` as well as the details about the evaluation result. This function is not called when the `runMode` is `parallel`.\n\nThe `shouldTrackWithThisProvider` method is called before sending a tracking event to each provider. Return `false` to skip tracking with that provider. By default, it only tracks with providers that are in a ready state (not `NOT_READY` or `FATAL`). Override this method to implement custom tracking logic based on the tracking event name, details, or provider characteristics.\n\nThe `determineFinalResult` function is called after all providers have been called, or the `shouldEvaluateNextProvider` function returned false. It is called\nwith a list of results from all the individual providers' evaluations. It returns the final decision for evaluation result, or throws an error if needed.\n\n## Building\n\nRun `nx package providers-multi-provider` to build the library.\n\n## Running unit tests\n\nRun `nx test providers-multi-provider` to execute the unit tests via [Jest](https://jestjs.io).\n","readmeFilename":"README.md"}