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

https://github.com/featurevisor/featurevisor-roku

Roku (BrightScript) SDK for Featurevisor
https://github.com/featurevisor/featurevisor-roku

Last synced: 5 months ago
JSON representation

Roku (BrightScript) SDK for Featurevisor

Awesome Lists containing this project

README

          

[![Featurevisor](./assets/banner-bordered.png)](https://featurevisor.com)


Feature management for developers



Manage your feature flags and experiments declaratively from the comfort of your Git workflow.





NPM version



License




Website

|

Documentation

|

Issues

|

Contributing

|

Changelog


---

# @featurevisor/roku

BrightScript SDK for Roku is meant to be used with [kopytko-framework](https://github.com/getndazn/kopytko-framework).

However, if you don't use it, you can simply copy all SDK files and their dependencies to your project (a version will be prepared in the future if anyone is interested).

Visit [https://featurevisor.com/docs/sdks/roku](https://featurevisor.com/docs/sdks/roku) for more information.

- [Installation](#installation)
- [Usage](#usage)
- [Options](#options)
- [`bucketKeySeparator`](#bucketkeyseparator)
- [`configureAndInterceptStaticContext`](#configureandinterceptstaticcontext)
- [`configureBucketKey`](#configurebucketkey)
- [`configureBucketValue`](#configurebucketvalue)
- [`datafile`](#datafile)
- [`datafileUrl`](#datafileurl)
- [`initialFeatures`](#initialfeatures)
- [`interceptContext`](#interceptcontext)
- [`onActivation`](#onactivation)
- [`onReady`](#onready)
- [`onRefresh`](#onrefresh)
- [`onUpdate`](#onupdate)
- [`refreshInterval`](#refreshinterval)
- [`stickyFeatures`](#stickyfeatures)
- [API](#api)
- [`f.isEnabled`](#fisenabled)
- [`f.getVariation`](#fgetvariation)
- [`f.getVariable`](#fgetvariable)
- [`f.activate`](#factivate)
- [`f.onActivation`](#fonactivation)
- [`f.onReady`](#fonready)
- [`f.onRefresh`](#fonrefresh)
- [`f.onUpdate`](#fonupdate)
- [`f.clear`](#fclear)
- [`f.getRevision`](#fgetrevision)
- [`f.isReady`](#fisready)
- [`f.refresh`](#frefresh)
- [`f.setDatafile`](#fsetdatafile)
- [`f.setStickyFeatures`](#fsetstickyfeatures)
- [`f.startRefreshing`](#fstartrefreshing)
- [`f.stopRefreshing`](#fstoprefreshing)

## Installation

```bash
npm i -P @featurevisor/roku
```

## Usage

Initialize the SDK (creates `FeaturevisorInstance` node).
For example, in the new `MyFeaturevisorNode` created:

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
datafileUrl: "",
})
end sub
```

You can also pass an existing instance to SDK, to not create a new instance, but to use an existing one to use FeaturevisorSDK methods that are invoked on it.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
' options from an existing instance are kept but could be overridden
}, existingInstance)
end sub
```

## Options

Options you can pass when creating Featurevisor SDK instance:

### `bucketKeySeparator`

- Type: `string`
- Required: no
- Defaults to: `.`

### `configureAndInterceptStaticContext`

- Type: `associativeArray`
- Required: no

The context for `configureBucketKey`, `configureBucketValue`, and `interceptContext` functions,
this object will be accessible via `m` in those functions.

### `configureBucketKey`

- Type: `function`
- Required: no

Use it to take over bucketing key generation process.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
configureBucketKey: function (feature as Dynamic, context as Object, bucketKey as String) as String
return bucketKey
end function,
})
end sub
```

### `configureBucketValue`

- Type: `function`
- Required: no

Use it to take over bucketing process.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
configureBucketValue: function (feature as Dynamic, context as Object, bucketValue as String) as Integer
return bucketValue ' 0 to 100000
end function,
})
end sub
```

### `datafile`

- Type: `associativeArray`
- Required: either `datafile` or `datafileUrl` is required

Use it to pass the datafile object directly.

### `datafileUrl`

- Type: `string`
- Required: either `datafile` or `datafileUrl` is required

Use it to pass the URL to fetch the datafile from.

### `initialFeatures`

- Type: `associativeArray`
- Required: no

Pass set of initial features with their variation and (optional) variables that you want the SDK to return until the datafile is fetched and parsed:

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
initialFeatures: {
myFeatureKey: {
enabled: true,

' optional
variation: "treatment",
variables: {
myVariableKey: "my-variable-value",
},
},
},
})
end sub
```

### `interceptContext`

- Type: `function`
- Required: no

Intercept given context before they are used to bucket the user:

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
defaultContext = {
platform: "roku",
locale: "en_US",
country: "US",
timezone: "America/New_York",
}
f = FeaturevisorSDK()
f.createInstance({
configureAndInterceptStaticContext: defaultContext,
interceptContext: function (context as Object) as Object
joinedContext = {}
joinedContext.append(m)
joinedContext.append(context)

return joinedContext
end function,
})
end sub
```

### `onActivation`

- Type: `associativeArray`
- Required: no
- Structure: `{ callback: function, context?: associativeArray }`

Capture activated features along with their evaluated variation:

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
onActivation: {
callback: sub (data as Object)
' feature has been activated
end sub,
context: {}, ' optional context for the callback
},
})
end sub
```

`data` Object fields:

- `captureContext`
- `feature`
- `context`
- `variationValue`

`captureContext` will only contain attributes that are marked as `capture: true` in the Attributes' YAML files.

### `onReady`

- Type: `associativeArray`
- Required: no
- Structure: `{ callback: function, context?: associativeArray }`

Triggered maximum once when the SDK is ready to be used.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
onReady: {
callback: sub ()
' agent has been createInstanced and it is ready
end sub,
context: {}, ' optional context for the callback
},
})
end sub
```

### `onRefresh`

- Type: `associativeArray`
- Required: no
- Structure: `{ callback: function, context?: associativeArray }`

Triggered every time the datafile is refreshed.

Works only when `datafileUrl` and `refreshInterval` are set.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
onRefresh: {
callback: sub ()
' datafile has been refreshed
end sub,
context: {}, ' optional context for the callback
},
})
end sub
```

### `onUpdate`

- Type: `associativeArray`
- Required: no
- Structure: `{ callback: function, context?: associativeArray }`

Triggered every time the datafile is refreshed, and the newly fetched datafile is detected to have different content than last fetched one.

Works only when `datafileUrl` and `refreshInterval` are set.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
onUpdate: {
callback: sub ()
' datafile has been updated (the revision has changed)
end sub,
context: {}, ' optional context for the callback
},
})
end sub
```

### `refreshInterval`

- Type: `integer` (in seconds)
- Required: no

Set the interval grater than zero to refresh the datafile.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
datafileUrl: "",
refreshInterval: 60 * 5, ' every 5 minutes
})
end sub
```

### `stickyFeatures`

- Type: `associativeArray`
- Required: no

If set, the SDK will skip evaluating the datafile and return variation and variable results from this object instead.

If a feature key is not present in this object, the SDK will continue to evaluate the datafile.

```brightscript
' @import /components/libs/featurevisor/FeaturevisorSDK.brs from @featurevisor/roku

sub init()
f = FeaturevisorSDK()
f.createInstance({
stickyFeatures: {
myFeatureKey: {
enabled: true,

' optional
variation: "treatment",
variables: {
myVariableKey: "my-variable-value",
},
},
},
})
end sub
```

## API

### `f.isEnabled`

Check if a feature is enabled or not.

> `f.isEnabled(featureKey as String, context = {} as Object) as Boolean`

### `f.getVariation`

Get feature variation.

> `f.getVariation(feature as Dynamic, context = {} as Object) as Dynamic`

### `f.getVariable`

Get feature variable.

> `f.getVariable(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`

Also supports additional type specific methods, returns the value of the desired type, or Invalid if the value does not exist or it does not have a desired type:

- `f.getVariableBoolean(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`
- `f.getVariableString(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`
- `f.getVariableInteger(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`
- `f.getVariableDouble(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`
- `f.getVariableArray(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`
- `f.getVariableObject(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`
- `f.getVariableJSON(feature as Dynamic, variableKey as String, context = {} as Object) as Dynamic`

### `f.activate`

Same as `getVariation`, but also calls the `onActivation` callback.

This is a convenience method meant to be called when you know the User has been exposed to your Feature, and you also want to track the activation.

> `f.activate(feature as Dynamic, context = {} as Object) as Object`

### `f.onActivation`

Adds on activation callback which will be called after an feature activation.

> `f.onActivation(func as Function, context = Invalid as Object)`

### `f.onReady`

Adds on ready callback which will be called after an instance is ready (datafile is saved).

**It should be called before `createInstance`**

> `f.onReady(func as Function, context = Invalid as Object)`

### `f.onRefresh`

Adds on refresh callback which will be called after a successful datafile refresh. But the file doesn't need to change.

> `f.onRefresh(func as Function, context = Invalid as Object)`

### `f.onUpdate`

Adds on update callback which will be called after a successful datafile refresh when it has been changed compared to the previous one.

> `f.onUpdate(func as Function, context = Invalid as Object)`

### `f.clear`

Stop refreshing and clear the whole instance. It needs to be initialized once again.

> `f.clear()`

### `f.getRevision`

Get the datafile revision.

> `f.getRevision() as String`

### `f.isReady`

Check if the instance is ready to be used (the datafile is set).

> `f.isReady() as Boolean`

### `f.refresh`

Manually refresh datafile.

> `f.refresh()`

### `f.setDatafile`

Set datafile manually.

> `f.setDatafile(datafile as Object)`

### `f.setStickyFeatures`

Set sticky features.

> `f.setStickyFeatures(stickyFeatures as Object)`

### `f.startRefreshing`

Resume or start refreshing if refreshInterval was provided.

> `f.startRefreshing()`

### `f.stopRefreshing`

Stop refreshing.

> `f.stopRefreshing()`

## License

MIT © Błażej Chełkowski