Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/horvathandris/openfeature-gleam-sdk

Gleam implementation of the OpenFeature SDK
https://github.com/horvathandris/openfeature-gleam-sdk

gleam openfeature sdk

Last synced: 7 days ago
JSON representation

Gleam implementation of the OpenFeature SDK

Awesome Lists containing this project

README

        

# OpenFeature Gleam SDK

[![Package Version](https://img.shields.io/hexpm/v/openfeature)](https://hex.pm/packages/openfeature)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/openfeature/)

[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.

This repository contains the unofficial SDK implementation of the [specification](https://openfeature.dev/specification/) for the [Gleam](https://gleam.run/) programming language.

## 🚀 Quick start

### Requirements

- Gleam [1+](https://github.com/gleam-lang/gleam/releases/tag/v1.0.0)

### Install

```sh
gleam add openfeature
```

### Usage

```gleam
import gleam/bool
import gleam/dict
import gleam/dynamic
import gleam/io
import gleam/option.{None}
import openfeature
import openfeature/client
import openfeature/evaluation_context
import openfeature/providers/in_memory

pub fn main() {
// flags defined in memory
let v2_flag =
in_memory.Flag(
default_variant: "off",
variants: dict.from_list([
#("off", dynamic.from(False)),
#("on", dynamic.from(True)),
]),
context_evaluator: None,
)
let flags = dict.from_list([#("v2_enabled", v2_flag)])

// configure a provider
let _ = openfeature.set_provider(in_memory.provider(flags))

// get a bool flag value
let flag_value =
openfeature.get_client()
|> client.get_bool_value("v2_enabled", False, evaluation_context.empty())

// use the returned flag value
io.println("`v2_enabled` evaluated to: " <> bool.to_string(flag_value))
}
```

Further documentation can be found at .

## 🌟 Features

| Status | Features | Description |
| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
| ❌ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
| ❌ | [Logging](#logging) | Integrate with popular logging packages. |
| ✅ | [Domains](#domains) | Logically bind clients with providers. |
| ❌ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
| ⚠️ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |

Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌

### Providers

[Providers](https://openfeature.dev/docs/reference/concepts/provider) are an abstraction between a flag management system and the OpenFeature SDK. Look [here](https://openfeature.dev/ecosystem?instant_search%5BrefinementList%5D%5Btype%5D%5B0%5D=Provider&instant_search%5BrefinementList%5D%5Btechnology%5D%5B0%5D=Gleam) for a complete list of available providers. If 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.

Once you've added a provider as a dependency, it can be registered with OpenFeature like this:

```gleam
import openfeature

openfeature.set_provider(my_provider())
```

In some situations, it may be beneficial to register multiple providers in the same application. This is possible using [domains](#domains), which is covered in more details below.

### Targeting

Sometimes, 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. In OpenFeature, we refer to this as [targeting](https://openfeature.dev/specification/glossary#targeting). If 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).

```gleam
import gleam/dynamic
import gleam/option.{None}
import openfeature
import openfeature/client
import openfeature/evaluation_context.{EvaluationContext}

// set the global evaluation context
openfeature.set_context(
evaluation_context.targetless([
#("region", dynamic.from("us-east-1-iah-1a")),
])
)

// set the client evaluation context
let my_app_client =
openfeature.get_domain_client("my-app")
|> client.set_context(
evaluation_context.targetless([
#("version", dynamic.from("1.4.6")),
])
)

// set the invocation context
client.get_bool_details(
my_app_client,
"bool-flag",
False,
evaluation_context.targeted(
"userId:1234",
[#("company", dynamic.from("Wise"))]
),
)
```

### Hooks

TODO

### Logging

TODO

### Domains

Clients can be assigned to a domain. A domain is a logical identifier which can be used to associate clients with a particular provider. If a domain has no associated provider, the default provider is used.

```gleam
import openfeature

// registering the default provider
openfeature.set_provider(local_provider())
// registering a domain provider
openfeature.set_domain_provider("cached-domain", cached_provider())

// a client bound to the default provider
openfeature.get_client()
// a client bound to the cached provider
openfeature.get_domain_client("cached-domain")
```

### Eventing

TODO

### Shutdown

The OpenFeature API provides a close function to perform a cleanup of all registered providers. This should only be called when your application is in the process of shutting down.

```gleam
import openfeature

openfeature.shutdown()
```

## Extending

### Develop a provider

To develop a provider, you need to create a new project and include the OpenFeature SDK as a dependency. This can be a new repository ~~or included in the existing contrib repository available under the OpenFeature organization~~. You’ll then need to write the provider by exporting a function that returns a value of type `FeatureProvider`, exported by the OpenFeature SDK.

```gleam
import gleam/dynamic.{type Dynamic}
import openfeature/evaluation_context.{type EvaluationContext}
import openfeature/provider.{type FeatureProvider, FeatureProvider}

pub fn my_provider() -> FeatureProvider {
FeatureProvider(
get_metadata: fn() { provider.Metadata("My Provider") },
initialize: fn(evaluation_context: EvaluationContext) {
// code to initialize your provider
todo
},
shutdown: fn() {
// code to shutdown your provider
todo
},
resolve_bool_evaluation: fn(
flag: String,
default_value: Bool,
evaluation_context: EvaluationContext,
) {
// code to evaluate a boolean value
todo
},
resolve_string_evaluation: fn(
flag: String,
default_value: String,
evaluation_context: EvaluationContext,
) {
// code to evaluate a string value
todo
},
resolve_int_evaluation: fn(
flag: String,
default_value: Int,
evaluation_context: EvaluationContext,
) {
// code to evaluate an integer value
todo
},
resolve_float_evaluation: fn(
flag: String,
default_value: Float,
evaluation_context: EvaluationContext,
) {
// code to evaluate a float value
todo
},
resolve_dynamic_evaluation: fn(
flag: String,
default_value: Dynamic,
evaluation_context: EvaluationContext,
) {
// code to evaluate a dynamic value
todo
},
)
}
```

### Develop a hook

TODO