npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@featurevisor/roku

v1.1.0

Published

Roku FeatureVisor SDK

Downloads

14

Readme

Featurevisor


@featurevisor/roku

BrightScript SDK for Roku is meant to be used with 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 for more information.

Installation

npm i -P @featurevisor/roku

Usage

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

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

sub init()
  f = FeaturevisorSDK()
  f.createInstance({
    datafileUrl: "<featurevisor-datafile-url>",
  })
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.

' @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.

' @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.

' @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:

' @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:

' @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:

' @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.

' @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.

' @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.

' @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.

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

sub init()
  f = FeaturevisorSDK()
  f.createInstance({
    datafileUrl: "<featurevisor-datafile-url>",
    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.

' @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