{"id":27950668,"url":"https://github.com/open-feature/dart-server-sdk","last_synced_at":"2025-05-07T16:15:17.982Z","repository":{"id":264037248,"uuid":"892164751","full_name":"open-feature/dart-server-sdk","owner":"open-feature","description":"Experimential ServerSide Dark SDK For OpenFeature","archived":false,"fork":false,"pushed_at":"2025-04-08T14:11:39.000Z","size":14215,"stargazers_count":3,"open_issues_count":1,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-07T16:15:10.068Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://openfeature.dev/","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/open-feature.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-21T16:09:31.000Z","updated_at":"2025-04-16T20:19:30.000Z","dependencies_parsed_at":"2024-12-07T19:18:22.380Z","dependency_job_id":"df7613b9-6318-45fd-8b43-4a9559a00afd","html_url":"https://github.com/open-feature/dart-server-sdk","commit_stats":null,"previous_names":["open-feature/dart-server-sdk"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-feature%2Fdart-server-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-feature%2Fdart-server-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-feature%2Fdart-server-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-feature%2Fdart-server-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/open-feature","download_url":"https://codeload.github.com/open-feature/dart-server-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252912964,"owners_count":21824066,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-07T16:15:17.330Z","updated_at":"2025-05-07T16:15:17.967Z","avatar_url":"https://github.com/open-feature.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable MD033 --\u003e\n\u003c!-- x-hide-in-docs-start --\u003e\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/open-feature/community/0e23508c163a6a1ac8c0ced3e4bd78faafe627c7/assets/logo/horizontal/white/openfeature-horizontal-white.svg\" /\u003e\n    \u003cimg align=\"center\" alt=\"OpenFeature Logo\" src=\"https://raw.githubusercontent.com/open-feature/community/0e23508c163a6a1ac8c0ced3e4bd78faafe627c7/assets/logo/horizontal/black/openfeature-horizontal-black.svg\" /\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003ch2 align=\"center\"\u003eOpenFeature Dart Server SDK\u003c/h2\u003e\n\n\u003c!-- x-hide-in-docs-end --\u003e\n\u003cp align=\"center\" class=\"github-badges\"\u003e\n  \u003c!-- Specification Badge --\u003e\n  \u003ca href=\"https://github.com/open-feature/spec/releases/tag/v0.8.0\"\u003e\n    \u003cimg alt=\"Specification\" src=\"https://img.shields.io/static/v1?label=specification\u0026message=v0.8.0\u0026color=yellow\u0026style=for-the-badge\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- x-release-please-start-version --\u003e\n  \u003ca href=\"https://github.com/open-feature/dart-server-sdk/releases/tag/v0.0.9\"\u003e\n    \u003cimg alt=\"Release\" src=\"https://img.shields.io/static/v1?label=release\u0026message=v0.0.9\u0026color=blue\u0026style=for-the-badge\" /\u003e\n\n  \u003c/a\u003e\n  \u003ca href=\"https://dart.dev/\"\u003e\n    \u003cimg alt=\"Built with Dart\" src=\"https://img.shields.io/badge/Built%20with-Dart-blue.svg?style=for-the-badge\" /\u003e\n  \u003c/a\u003e\n  \u003c!-- x-release-please-end --\u003e\n  \u003cbr/\u003e\n  \u003c!-- Dart-Specific Badges --\u003e\n  \u003ca href=\"https://pub.dev/packages/openfeature_dart_server_sdk\"\u003e\n    \u003cimg alt=\"Pub Version\" src=\"https://img.shields.io/pub/v/openfeature_dart_server_sdk.svg?style=for-the-badge\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://openfeature.dev/docs/reference/intro\"\u003e\n    \u003cimg alt=\"API Reference\" src=\"https://img.shields.io/badge/API-reference-blue.svg?style=for-the-badge\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/open-feature/dart-server-sdk\"\u003e\n    \u003cimg alt=\"Code Coverage\" src=\"https://codecov.io/gh/open-feature/dart-server-sdk/branch/main/graph/badge.svg?token=FZ17BHNSU5\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/open-feature/dart-server-sdk/actions/workflows/validation-workflow.yml\"\u003e\n    \u003cimg alt=\"GitHub CI Status\" src=\"https://github.com/open-feature/dart-server-sdk/actions/workflows/validation-workflow.yml/badge.svg?style=for-the-badge\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003c!-- x-hide-in-docs-start --\u003e\n\n:warning: This repository is a work in progress repository for an implementation of the `dart-server-sdk`.\n\n[OpenFeature](https://openfeature.dev) is an open specification that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool.\n\n\u003c!-- x-hide-in-docs-end --\u003e\n\n## 🚀 Quick start\n\n### Requirements\n\nDart language version: [3.7.2](https://dart.dev/get-dart/archive)\n\n\u003e [!NOTE]\n\u003e The OpenFeature DartServer SDK only supports the latest currently maintained Dart language versions.\n\n### Install\n\n```yaml\ndependencies:\n  openfeature_dart_server_sdk: ^0.0.6\n```\n\n### Then run:\n\n```\ndart pub get\n```\n\n### Usage\n\n```dart\nimport 'dart:async';\nimport 'package:openfeature_dart_server_sdk/client.dart';\nimport 'package:openfeature_dart_server_sdk/open_feature_api.dart';\nimport 'package:openfeature_dart_server_sdk/feature_provider.dart';\nimport 'package:openfeature_dart_server_sdk/evaluation_context.dart';\nimport 'package:openfeature_dart_server_sdk/hooks.dart';\n\nvoid main() async {\n  // Register your feature flag provider\n  final api = OpenFeatureAPI();\n  api.setProvider(InMemoryProvider({\n    'new-feature': true,\n    'welcome-message': 'Hello, OpenFeature!'\n  }));\n\n  // Create a client\n  final client = FeatureClient(\n    metadata: ClientMetadata(name: 'my-app'),\n    hookManager: HookManager(),\n    defaultContext: EvaluationContext(attributes: {}),\n  );\n\n  // Evaluate your feature flags\n  final newFeatureEnabled = await client.getBooleanFlag(\n    'new-feature',\n    defaultValue: false,\n  );\n\n  // Use the returned flag value\n  if (newFeatureEnabled) {\n    print('New feature is enabled!');\n\n    final welcomeMessage = await client.getStringFlag(\n      'welcome-message',\n      defaultValue: 'Welcome!',\n    );\n\n    print(welcomeMessage);\n  }\n}\n```\n\n### API Reference\n\nSee [here](https://pub.dev/documentation/openfeature_dart_server_sdk/latest/) for the complete API documentation.\n\n## 🌟 Features\n\n| Status | Features                                                            | Description                                                                                                                                                  |\n| ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| ✅     | [Providers](#providers)                                             | Integrate with a commercial, open source, or in-house feature management tool.                                                                               |\n| ✅     | [Targeting](#targeting)                                             | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context).                           |\n| ✅     | [Hooks](#hooks)                                                     | Add functionality to various stages of the flag evaluation life-cycle.                                                                                       |\n| ✅     | [Logging](#logging)                                                 | Integrate with popular logging packages.                                                                                                                     |\n| ✅     | [Domains](#domains)                                                 | Logically bind clients with providers.                                                                                                                       |\n| ✅     | [Eventing](#eventing)                                               | React to state changes in the provider or flag management system.                                                                                            |\n| ✅     | [Shutdown](#shutdown)                                               | Gracefully clean up a provider during application shutdown.                                                                                                  |\n| ✅     | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |\n| ✅     | [Extending](#extending)                                             | Extend OpenFeature with custom providers and hooks.                                                                                                          |\n\n\u003csub\u003eImplemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌\u003c/sub\u003e\n\n### Providers\n\n[Providers](https://openfeature.dev/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK.\nLook [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider\u0026instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Dart) for a complete list of available providers.\nIf the provider you're looking for hasn't been created yet, see the [develop a provider](#develop-a-provider) section to learn how to build it yourself.\n\nOnce you've added a provider as a dependency, it can be registered with OpenFeature like this:\n\n```dart\nfinal api = OpenFeatureAPI();\napi.setProvider(MyProvider());\n```\n\n### Targeting\n\nSometimes, the value of a flag must consider some dynamic criteria about the application or user, such as the user's location, IP, email address, or the server's location.\nIn OpenFeature, we refer to this as [targeting](https://openfeature.dev/specification/glossary#targeting).\nIf the flag management system you're using supports targeting, you can provide the input data using the [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context).\n\n```dart\n// Set a value to the global context\nfinal api = OpenFeatureAPI();\napi.setGlobalContext(OpenFeatureEvaluationContext({\n  'region': 'us-east-1-iah-1a',\n}));\n\n// Create a client with a specific evaluation context\nfinal client = FeatureClient(\n  metadata: ClientMetadata(name: 'my-app'),\n  hookManager: HookManager(),\n  defaultContext: EvaluationContext(attributes: {\n    'version': '1.4.6',\n  }),\n);\n\n// Set a value to the invocation context\nfinal result = await client.getBooleanFlag(\n  'feature-flag',\n  defaultValue: false,\n  context: EvaluationContext(attributes: {\n    'user': 'user-123',\n    'company': 'Initech',\n  }),\n);\n```\n\n### Hooks\n\n[Hooks](https://openfeature.dev/docs/reference/concepts/hooks) allow for custom logic to be added at well-defined points of the flag evaluation life-cycle\nLook [here](https://openfeature.dev/ecosystem/?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Hook\u0026instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Dart) for a complete list of available hooks.\nIf the hook you're looking for hasn't been created yet, see the [develop a hook](#develop-a-hook) section to learn how to build it yourself.\n\nOnce you've added a hook as a dependency, it can be registered at the global, client, or flag invocation level.\n\n```dart\n// Add a hook globally, to run on all evaluations\nfinal api = OpenFeatureAPI();\napi.addHooks([MyGlobalHook()]);\n\n// Add a hook on this client, to run on all evaluations made by this client\nfinal hookManager = HookManager();\nhookManager.addHook(MyClientHook());\n\nfinal client = FeatureClient(\n  metadata: ClientMetadata(name: 'my-app'),\n  hookManager: hookManager,\n  defaultContext: EvaluationContext(attributes: {}),\n);\n\n// Create a hook for a specific evaluation\nfinal myHook = MyHook();\n// You can use the hook with a specific evaluation\n```\n\n### Tracking\n\nThe [tracking API](https://openfeature.dev/specification/sections/tracking/) allows you to use OpenFeature abstractions and objects to associate user actions with feature flag evaluations.\nThis is essential for robust experimentation powered by feature flags.\nFor example, a flag enhancing the appearance of a UI component might drive user engagement to a new feature; to test this hypothesis, telemetry collected by a [hook](#hooks) or [provider](#providers) can be associated with telemetry reported in the client's `track` function.\n\nNote that some providers may not support tracking; check the documentation for your provider for more information.\n\n### Logging\n\nNote that in accordance with the OpenFeature specification, the SDK doesn't generally log messages during flag evaluation.\n\n#### Logging Hook\n\nThe Dart SDK includes a `LoggingHook`, which logs detailed information at key points during flag evaluation, using [TBD](TBD) structured logging API.\nThis hook can be particularly helpful for troubleshooting and debugging; simply attach it at the global, client or invocation level and ensure your log level is set to \"debug\".\n\n##### Usage example\n\n```dart\nimport 'package:logging/logging.dart';\nimport 'package:openfeature_dart_server_sdk/hooks.dart';\n\n// Configure logging\nLogger.root.level = Level.ALL;\nLogger.root.onRecord.listen((record) {\n  print('${record.time} [${record.level.name}] ${record.message}');\n});\n\n// Create a logging hook\nfinal loggingHook = LoggingHook();\n\n// Add the hook to your hook manager\nfinal hookManager = HookManager();\nhookManager.addHook(loggingHook);\n\n// Create a client using this hook manager\nfinal client = FeatureClient(\n  metadata: ClientMetadata(name: 'test-client'),\n  hookManager: hookManager,\n  defaultContext: EvaluationContext(attributes: {}),\n);\n\n// Evaluate a flag\nfinal result = await client.getBooleanFlag('my-flag', defaultValue: false);\n```\n\n###### Output\n\n```sh\n{\"time\":\"2024-10-23T13:33:09.8870867+03:00\",\"level\":\"DEBUG\",\"msg\":\"Before stage\",\"domain\":\"test-client\",\"provider_name\":\"InMemoryProvider\",\"flag_key\":\"not-exist\",\"default_value\":true}\n{\"time\":\"2024-10-23T13:33:09.8968242+03:00\",\"level\":\"ERROR\",\"msg\":\"Error stage\",\"domain\":\"test-client\",\"provider_name\":\"InMemoryProvider\",\"flag_key\":\"not-exist\",\"default_value\":true,\"error_message\":\"error code: FLAG_NOT_FOUND: flag for key not-exist not found\"}\n```\n\nSee [hooks](#hooks) for more information on configuring hooks.\n\n### Domains\n\nClients can be assigned to a domain. A domain is a logical identifier that can be used to associate clients with a particular provider. If a domain has no associated provider, the default provider is used.\n\n```dart\nimport 'package:openfeature_dart_server_sdk/domain_manager.dart';\nimport 'package:openfeature_dart_server_sdk/feature_provider.dart';\nimport 'package:openfeature_dart_server_sdk/open_feature_api.dart';\n\n// Get the OpenFeature API instance\nfinal api = OpenFeatureAPI();\n\n// Register the default provider\napi.setProvider(InMemoryProvider({'default-flag': true}));\n\n// Register a domain-specific provider\napi.bindClientToProvider('cache-domain', 'CachedProvider');\n\n// Client backed by default provider\napi.evaluateBooleanFlag('my-flag', 'default-client');\n\n// Client backed by CachedProvider\napi.evaluateBooleanFlag('my-flag', 'cache-domain');\n```\n\n### Eventing\n\nEvents allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions.\nInitialization events (`PROVIDER_READY` on success, `PROVIDER_ERROR` on failure) are dispatched for every provider.\nSome providers support additional events, such as `PROVIDER_CONFIGURATION_CHANGED`.\n\nPlease refer to the documentation of the provider you're using to see what events are supported.\n\n```dart\nimport 'package:openfeature_dart_server_sdk/open_feature_api.dart';\nimport 'package:openfeature_dart_server_sdk/open_feature_event.dart';\n\n// Get the OpenFeature API instance\nfinal api = OpenFeatureAPI();\n\n// Listen for provider change events\napi.events.listen((event) {\n  if (event.type == OpenFeatureEventType.providerChanged) {\n    print('Provider changed: ${event.message}');\n  }\n});\n\n// Listen for flag evaluation events\napi.events.listen((event) {\n  if (event.type == OpenFeatureEventType.flagEvaluated) {\n    print('Flag evaluated: ${event.data['flagKey']} = ${event.data['result']}');\n  }\n});\n```\n\n### Shutdown\n\nThe OpenFeature API provides mechanisms to perform a cleanup of all registered providers.\nThis should only be called when your application is in the process of shutting down.\n\n```dart\nimport 'package:openfeature_dart_server_sdk/open_feature_api.dart';\nimport 'package:openfeature_dart_server_sdk/shutdown_manager.dart';\n\n// Get the OpenFeature API instance\nfinal api = OpenFeatureAPI();\n\n// Register shutdown hooks\nfinal shutdownManager = ShutdownManager();\nshutdownManager.registerHook(ShutdownHook(\n  name: 'provider-cleanup',\n  phase: ShutdownPhase.PROVIDER_SHUTDOWN,\n  execute: () async {\n    // Clean up provider resources\n    await api.dispose();\n  },\n));\n\n// During application shutdown\nawait shutdownManager.shutdown();\n```\n\n### Transaction Context Propagation\n\nTransaction context is a container for transaction-specific evaluation context (e.g. user id, user agent, IP).\nTransaction context can be set where specific data is available (e.g. an auth service or request handler), and by using the transaction context propagator, it will automatically be applied to all flag evaluations within a transaction (e.g. a request or thread).\n\n```dart\nimport 'package:openfeature_dart_server_sdk/transaction_context.dart';\n\n// Create a transaction context manager\nfinal transactionManager = TransactionContextManager();\n\n// Set the transaction context\nfinal context = TransactionContext(\n  transactionId: 'request-123',\n  attributes: {\n    'user': 'user-456',\n    'region': 'us-west-1',\n  },\n);\ntransactionManager.pushContext(context);\n\n// The transaction context will automatically be applied to flag evaluations\nawait client.getBooleanFlag('my-flag', defaultValue: false);\n\n// Execute code with a specific transaction context\nawait transactionManager.withContext(\n  'transaction-id',\n  {'user': 'user-123'},\n  () async {\n    await client.getBooleanFlag('my-flag', defaultValue: false);\n  },\n);\n\n// When the transaction is complete, pop the context\ntransactionManager.popContext();\n```\n\n## Extending\n\n### Develop a provider\n\nTo develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency.\nThis can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/dart-server-sdk-contrib) available under the OpenFeature organization.\nYou’ll then need to write the provider by implementing the `FeatureProvider` interface exported by the OpenFeature SDK.\n\n```dart\nimport 'dart:async';\nimport 'package:openfeature_dart_server_sdk/feature_provider.dart';\n\nclass MyCustomProvider implements FeatureProvider {\n  @override\n  String get name =\u003e 'MyCustomProvider';\n\n  @override\n  ProviderState get state =\u003e ProviderState.READY;\n\n  @override\n  ProviderConfig get config =\u003e ProviderConfig();\n\n  @override\n  Future\u003cvoid\u003e initialize([Map\u003cString, dynamic\u003e? config]) async {\n    // Initialize your provider\n  }\n\n  @override\n  Future\u003cvoid\u003e connect() async {\n    // Connection logic if needed\n  }\n\n  @override\n  Future\u003cvoid\u003e shutdown() async {\n    // Clean up resources\n  }\n\n  @override\n  Future\u003cFlagEvaluationResult\u003cbool\u003e\u003e getBooleanFlag(\n    String flagKey,\n    bool defaultValue, {\n    Map\u003cString, dynamic\u003e? context,\n  }) async {\n    // Evaluate boolean flag\n    return FlagEvaluationResult(\n      flagKey: flagKey,\n      value: true, // Your implementation here\n      evaluatedAt: DateTime.now(),\n      evaluatorId: name,\n    );\n  }\n\n  @override\n  Future\u003cFlagEvaluationResult\u003cString\u003e\u003e getStringFlag(\n    String flagKey,\n    String defaultValue, {\n    Map\u003cString, dynamic\u003e? context,\n  }) async {\n    // Evaluate string flag\n    return FlagEvaluationResult(\n      flagKey: flagKey,\n      value: 'value', // Your implementation here\n      evaluatedAt: DateTime.now(),\n      evaluatorId: name,\n    );\n  }\n\n  @override\n  Future\u003cFlagEvaluationResult\u003cint\u003e\u003e getIntegerFlag(\n    String flagKey,\n    int defaultValue, {\n    Map\u003cString, dynamic\u003e? context,\n  }) async {\n    // Evaluate integer flag\n    return FlagEvaluationResult(\n      flagKey: flagKey,\n      value: 42, // Your implementation here\n      evaluatedAt: DateTime.now(),\n      evaluatorId: name,\n    );\n  }\n\n  @override\n  Future\u003cFlagEvaluationResult\u003cdouble\u003e\u003e getDoubleFlag(\n    String flagKey,\n    double defaultValue, {\n    Map\u003cString, dynamic\u003e? context,\n  }) async {\n    // Evaluate double flag\n    return FlagEvaluationResult(\n      flagKey: flagKey,\n      value: 3.14, // Your implementation here\n      evaluatedAt: DateTime.now(),\n      evaluatorId: name,\n    );\n  }\n\n  @override\n  Future\u003cFlagEvaluationResult\u003cMap\u003cString, dynamic\u003e\u003e\u003e getObjectFlag(\n    String flagKey,\n    Map\u003cString, dynamic\u003e defaultValue, {\n    Map\u003cString, dynamic\u003e? context,\n  }) async {\n    // Evaluate object flag\n    return FlagEvaluationResult(\n      flagKey: flagKey,\n      value: {'key': 'value'}, // Your implementation here\n      evaluatedAt: DateTime.now(),\n      evaluatorId: name,\n    );\n  }\n}\n```\n\n\u003e Built a new provider? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=\u0026labels=provider\u0026projects=\u0026template=document-provider.yaml\u0026title=%5BProvider%5D%3A+) so we can add it to the docs!\n\n### Develop a hook\n\nTo develop a hook, you need to create a new project and include the OpenFeature SDK as a dependency.\nThis can be a new repository or included in [the existing contrib repository](https://github.com/open-feature/dart-server-sdk-contrib) available under the OpenFeature organization.\nImplement your own hook by conforming to the [Hook interface](./pkg/openfeature/hooks.dart).\nTo satisfy the interface, all methods (`Before`/`After`/`Finally`/`Error`) need to be defined.\nTo avoid defining empty functions make use of the `UnimplementedHook` struct (which already implements all the empty functions).\n\n```dart\nimport 'dart:async';\nimport 'package:openfeature_dart_server_sdk/hooks.dart';\n\nclass MyCustomHook extends BaseHook {\n  MyCustomHook()\n    : super(metadata: HookMetadata(name: 'MyCustomHook'));\n\n  @override\n  Future\u003cvoid\u003e before(HookContext context) async {\n    // Code to run before flag evaluation\n    print('Before evaluating flag: ${context.flagKey}');\n  }\n\n  @override\n  Future\u003cvoid\u003e after(HookContext context) async {\n    // Code to run after successful flag evaluation\n    print('After evaluating flag: ${context.flagKey}, result: ${context.result}');\n  }\n\n  @override\n  Future\u003cvoid\u003e error(HookContext context) async {\n    // Code to run when an error occurs during flag evaluation\n    print('Error evaluating flag: ${context.flagKey}, error: ${context.error}');\n  }\n\n  @override\n  Future\u003cvoid\u003e finally_(\n    HookContext context,\n    EvaluationDetails? evaluationDetails, [\n    HookHints? hints,\n  ]) async {\n    // Code to run regardless of success or failure\n    print('Finished evaluating flag: ${context.flagKey}');\n  }\n}\n```\n\n\u003e Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=\u0026labels=hook\u0026projects=\u0026template=document-hook.yaml\u0026title=%5BHook%5D%3A+) so we can add it to the docs!\n\n## Testing\n\nThe SDK provides a `NewTestProvider` which allows you to set flags for the scope of a test.\nThe `TestProvider` is thread-safe and can be used in tests that run in parallel.\n\nCall `testProvider.UsingFlags(t, tt.flags)` to set flags for a test, and clean them up with `testProvider.Cleanup()`\n\n```dart\nimport 'package:test/test.dart';\nimport 'package:openfeature_dart_server_sdk/open_feature_api.dart';\nimport 'package:openfeature_dart_server_sdk/feature_provider.dart';\n\nvoid main() {\n  late OpenFeatureAPI api;\n  late InMemoryProvider testProvider;\n\n  setUp(() {\n    api = OpenFeatureAPI();\n    testProvider = InMemoryProvider({\n      'test-flag': true,\n      'string-flag': 'test-value',\n    });\n    api.setProvider(testProvider);\n  });\n\n  tearDown(() {\n    OpenFeatureAPI.resetInstance();\n  });\n\n  test('evaluates boolean flag correctly', () async {\n    final client = api.getClient('test-client');\n    final result = await client.getBooleanFlag('test-flag', defaultValue: false);\n    expect(result, isTrue);\n  });\n\n  test('evaluates string flag correctly', () async {\n    final client = api.getClient('test-client');\n    final result = await client.getStringFlag('string-flag', defaultValue: 'default');\n    expect(result, equals('test-value'));\n  });\n}\n```\n\n\u003c!-- x-hide-in-docs-start --\u003e\n\n## ⭐️ Support the project\n\n- Give this repo a ⭐️!\n- Follow us on social media:\n  - Twitter: [@openfeature](https://twitter.com/openfeature)\n  - LinkedIn: [OpenFeature](https://www.linkedin.com/company/openfeature/)\n- Join us on [Slack](https://cloud-native.slack.com/archives/C0344AANLA1)\n- For more, check out our [community page](https://openfeature.dev/community/)\n\n## 🤝 Contributing\n\nInterested in contributing? Great, we'd love your help! To get started, take a look at the [CONTRIBUTING](CONTRIBUTING.md) guide.\n\n### Thanks to everyone that has already contributed\n\n\u003ca href=\"https://github.com/open-feature/dart-server-sdk/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=open-feature/dart-server-sdk\" alt=\"Pictures of the folks who have contributed to the project\" /\u003e\n\u003c/a\u003e\n\nMade with [contrib.rocks](https://contrib.rocks).\n\n\u003c!-- x-hide-in-docs-end --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-feature%2Fdart-server-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopen-feature%2Fdart-server-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-feature%2Fdart-server-sdk/lists"}