@creative-realities/vue-rvhost-plugin
v2.0.0
Published
Vue plugin for CRI Vue3
Downloads
5
Readme
RVHost Plugin 2.0.0
Breaking changes! Plugin has been adapted to use the getContentSnapshot call to RVHost. This will change data parsing in all associated 'boilerplate/plugin' based architectured apps. For apps using instanceProperties, use v1.6.3
as of 4/22/24, VZW Promo-15 and VZW 39" apps have been updated to this version of the plugin. A Vue3 plugin for the CRI ReflectView player ecosystem.
Features
- Pulls channel and feed containers from instance properties and makes them available to app developers.
- Highly configurable developer options through a factory method flow.
- Architected as a factory function that retrieves data, configures the app, and exposes APIs and data sets through provide/inject.
- Supports Matomo Analytics configurable via instance properties.
- Fires realtime
containerUpdated
event bus events when channel and feed containers are updated. - Supports user-defined update interval for single container apps.
- Supports multi-container apps and their intervals through configuration and user-defined properties.
- Provides unit testing of all API calls.
- Instance properties can be mocked by providing a
userDefinedProperties
object.
Installation & Setup
Install PNPM:
pnpm add @creative-realities/vue-rvhost-plugin
Install Yarn:
yarn add @creative-realities/vue-rvhost-plugin
Install NPM:
npm i @creative-realities/vue-rvhost-plugin
Setup Main.js:
import { rvHostPluginFactory } from "@creative-realities/vue-rvhost-plugin";
// factory configuration object
rvHostPluginFactory({
logLevel: 'verbose', 'error', 'none',
getHost: boolean,
getLocation: boolean,
getInstanceProperties: boolean,
getLocationClassifications: boolean,
getChannelClassifications: Number[],
feedDetails: Array<{channel: number, interval?: number, instanceUID?: string, feedChannelName?: string,}>,
containerDetails: Array<{channel: number, interval?: number}>,
}).then((plugin) => {
const app = createApp(App);
// mock user-defined properties
app.use(plugin, {
userDefinedProperties: Record<string,string,
});
// mount vue
app.mount("#app");
});
Setup Main.js (Async/Await):
import { rvHostPluginFactory } from "@creative-realities/vue-rvhost-plugin";
const app = createApp(App);
// factory configuration object
const plugin = await rvHostPluginFactory({
logLevel: 'verbose', 'error', 'none',
getHost: boolean,
getLocation: boolean,
getInstanceProperties: boolean,
getLocationClassifications: boolean,
getChannelClassifications: Number[],
feedDetails: Array<{channel: number, interval?: number, instanceUID?: string, feedChannelName?: string,}>,
containerDetails: Array<{channel: number, interval?: number}>,
})
// mock user-defined properties
app.use(plugin, {
userDefinedProperties: Record<string,string,
});
// mount vue
app.mount("#app");
Usage & Configuration
The plugin will provide three important objects that are able to be injected through the vue provide/inject pattern: rvData
, rvHost
, and logger
. These are described below:
1. rvData: This object encapsulates all of the data that will update on the configurable interval. The response will include the following data, contingent on the Options
object that is passed into the rvHostPluginFactory
(see plugin instantiation section for field descriptions):
export interface InitialData extends Options {
matomoHost?: string
matomoSiteId?: number
hostInfo?: IHostInfo | null
locationInfo?: ILocationInfo | null
locationClassifications?: string[] | null
channelClassifications?: ChannelClassification[]
userDefinedProperties?: Record<string, string>
containers?: Container[]
feedContainers?: Container[]
}
Following is the prototype for the IHostInfo
interface:
interface IHostInfo {
ChannelNumber: string
LocationCode: string
PlayerID: string
PlayerName: string
PlayerNetworkName: string
PlayerVersion?: string
DeviceFamily?: string
DeviceModel?: string
DeviceSerial?: string
}
Following is the prototype for the ILocationInfo
interface:
interface ILocationInfo {
Address: string
AddressLine2: string
AdvertisementText?: string
AdvertisementTempo?: string
AtomicDuration?: string
BaseCPM?: string
City: string
CloseDate?: string
CreationDate?: string
Currency?: string
DeletionDate?: string
DeniesAudio?: string
Description: string
FaxNumber: string
Filter1?: string
Filter2?: string
Filter3?: string
ID?: string
ImageURL?: string
Latitude: string
LocationActive?: string
LocationManaged?: string
LocationTag: string
Longitude: string
ManagingEntity?: string
Market: string
Name: string
OpenDate?: string
PhoneNumber: string
PhoneNumber2: string
PostalCode: string
Production?: string
SiteOwner?: string
StateOrProvince: string
Tempo?: string
TimeZone: string
Traffic?: string
}
Following is the prototype for the Container
Interface:
export interface Container {
guid: string | null
container: IContainer | null
instanceUID?: string | null
feedChannelName?: string | null
newContainer: IContainer | null
containerInterval: NodeJS.Timer | null
hydrateContainer(): boolean
updateMethod(): Promise<void>
}
The Container
interface initalizes the container
member to container data defined by the IContainer
interface, shown below:
interface IContainer {
ContainerType: string
Creator: string
CreatorVersion: string
DataVersion: string
FeedContainer: IFeedItem
IsEventList: boolean
IsSubList: boolean
Items: IContainerItem[]
Name: string
RejectAuthority: boolean
Schedule: string | null
ShufflePercentage?: string | null
SyncUID?: string | null
UID: string
UnconfiguredItem?: null
version: string
}
A containerUpdated
bus event fires when container
data is refreshed. This will occur on a default interval of one hour, or at the override interval that may be provided via an updateInterval
value exposed by Publisher.xml
, or by passing in a UserDefinedProperties
object with an updateInterval
member initialized to the desired number of milliseconds. See the section titled "User Defined Property config" for more information about the UserDefinedProperties
object. When this event fires, calling hydrateContainer()
on the desired channelContainerData
index will synchronize the app
data against the refreshed data for that channel container.
import { useEventBus } from '@vueuse/core'
pluginBus.on(event => {
switch (event.type) {
case 'containerUpdated':
console.log(event.info)
// this bus notifies the app that there is new container data to be consumed.
// Call the hydrateContainer Method for the container in rvData that matches the guid when desired by your application.
break
default:
break
}
})
2. RVHost:
Various API calls are provided by the RVHost. Not all of them are currently supported by the plugin. Following is the list of those that are currently supported:
RV_GetClassifications
(asynchronous):
Purpose: Get the ReflectView Location Classifications associated with the ReflectView Location the Player is in.
Parameters:
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: If no callback is provided, it returns a Promise that will resolve with an Array of String classifications. Otherwise, this gets passed into the callback.
RV_GetChannelClassifications
(asynchronous):
Purpose: Get the ReflectView Channel Classifications for channel and location.
Parameters:
- {Number} channel Channel number, starting from a base of 1.
- {Boolean} merge Get location classifications as well, defaults to false.
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: If no callback is provided, it returns a Promise that will resolve with an Array of String classifications. Otherwise, this gets passed into the callback.
RV_GetLocationInfo
(asynchronous)
Purpose: Get the ReflectView Location info.
Parameters:
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: If no callback is provided, it returns a Promise that will resolve with an Object with details about the player location. Otherwise, this gets passed into the callback.
RV_GetHostInfo
(asynchronous):
Purpose: Returns host information
Parameters:
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: If no callback is provided, it returns a Promise that will resolve with an Object with details about the ReflectView Player hosting the application. Otherwise, this gets passed into the callback.
RV_GetChannelContainers
(asynchronous):
Purpose: Get a list of Guids for Pending, Playing, Playlist, and Validated channel container statuses. Playing is generally the GUID you will want to use when calling getContainer.
Parameters:
- {Number} channel Channel number, starting from a base of 1.
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: If no callback is provided, it returns a Promise that will resolve with an Object with GUIDs for containers by Status. Otherwise, this gets passed into the callback.
RV_GetContainer
(asynchronous):
Purpose: Returns container information for the provided channel and Guid. A container could be a ReflectView Playlist or Catalog, or data generated from a ReflectView Feedsource module. The example given uses it in combination with getChannelContainers. It would also commonly be used with the result from getFeedChannelContainers. The example also shows a common pattern where an application would exit if its required playlist content and data are not available. If an app exits immediately, it will be unnoticable and the player moves on to its next content item.
Parameters
- {Number} channel Channel number, starting from a base of 1.
- {String} guid The Playing guid for the associated channel. See getChannelContainers
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: If no callback is provided, it returns a Promise that will resolve with an Object representation of a Container. Otherwise, this gets passed into the callback.
RV_GetFeedChannelContainers
(asynchronous):
Purpose: Get a list of GUIDs by status, for Activated, Pending and Validated. Activated is generally the GUID you will want to use when calling getContainer. Feed containers are generated by ReflectView Feedsource modules.
Parameters:
- {Number} channel Channel number, starting from a base of 1.
- {String} instanceUID
- {String} feedChannelName
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: If no callback is provided, it returns a Promise that will resolve with an Object with GUIDs for containers by Status. Otherwise, this gets passed into the callback.
RV_GetInstanceProperties
(asynchronous):
Purpose: Returns instance properties associated with an instance of an application in a Playlist. Instance properties can be set in the ReflectView Publisher on a Playlist item. This allows you to schedule the same application multiple times in a Playlist, while assigning different data for each instance of the application in that Playlist.
Parameters:
- {Function} callback Function to execute on completion or error.
- {Object} thisArgument The "this" value when the callback is executed.
- {Object} context An optional context object that is passed to the callback.
Return Value: {object} associated properties.
RV_Trace
(asynchronous):
Purpose: Writes output to the host logfile.
Parameters:
- {Any}
Return Value: None.
3. logger:
The logger utility is available via provide / inject as follows:
const logger = inject('logger')
const rvHost = RVHost.getRVHost()
if (rvHost.isRunnable) rvHost.log(message)
Entries may be written to the Developer's Console and the RVHost log file, or to neither if logging is turned off. The log level is determined by the Options.logLevel
that is passed into the rvHostPluginFactory
when it is instantiated. Available levels are:
none
or undefined: calls to log
will not write to the console or call the RVHost log
API.
error
: calls to log
will write to the console.
verbose
: calls to log
will write to the console and also call the RVHost log
API.
Example:
In a .vue file the APIs, data sets, and logging capabilities may then be injected into the app as follows:
const logger = inject('logger')
log('This is an app log entry.');
Plugin instantiation
Instantiate the plugin with an Options object which may include any of the following optional members. For those calls that call APIs, the response data will be made available to the app in the rvData
object, which is provided and here and injected into the app:
getHost: boolean - if true then
hostInfo
will be pulled and returned. This will expose the following:channelNumber
: the channel on which the app is runningDeviceFamily
: the player OS (e.g., "malibu")DeviceFirmware
: the player firmware versionDeviceModel
: the player model (e.g., "XD1034")DeviceSerial
: the player serial numberLocationCode
: the player Location Code as assigned in PublisherPlayerID
: the unique UID that identifies the playerPlayerName
: the player name as assigned in PublisherPlayerNetworkName
: the player name as assigned in the RV ServerPlayerVersion
: the Reflect Player versiongetLocation: boolean - if true then player location info will be pulled and returned. The response object will include the following:
Address
,AddressLine2
,City
,Description
,FaxNumber
,Latitude
,LocationTag
,Longitude
,Market
,Name
,PhoneNumber
,PhoneNumber2
,PostalCode
,StateOrProvince
,TimeZone
getInstanceProperties: boolean - if true then
userDefinedProperties
will be pulled and returned.getLocationClassifications: boolean - if true then
locationClassifications
will be pulled and returned as an array of location classification objects.getChannelClassifications: number array -
channelClassifications
will be pulled and returned as an array of channel classification objects having the shape:{[channel: number, classifications: [string]]}
containerDetails: ChannelContainerOptions -
container
details will be pulled and returned as an array of objects. TheChannelContainerOptions
object has the shape:{channel: number, interval: number | undefined }
feedDetails:
FeedChannelOptions
array -feedContainers
details will be pulled and returned as an array of objects.FeedChannelOptions
are a modifiedChannelContainerOptions
object:
ChannelContainerOptions {
channel: number
interval: number | undefined
}
FeedChannelOptions = {
ChannelContainerOptions,
{
type: 'Activated'
instanceUID?: string
feedChannelName?: string
}
}
matomoOptions:
PluginOptions
, defined as follows:immediateSession
: boolean - if true then the session will start immediately after loading the Matomo libraries; otherwise it will wait 200 milliseconds.isDevelopment
: boolean - if true then calls togetMatomoHost
will return the default Matomo host and siteId; otherwise the actual Matomo host info will be returned.matomoHost
: string - the Matomo host URI.matomoSiteId
: string | number - the Matomo Site Id as defined in the Matomo portal.debugMatomo
: boolean - sets the value of the VueMatomo plugindebug
flag.useHttp
: boolean - if true then Matomo will be setup using the fully qualified base URL. Otherwise it will setup using host and siteId.dimensions
: Record<number, string> - an array of key/value pairs of custom dimensions.userDefinedProperties: Record<string, string> - an array of key/value pairs with custom user-defined properties. See the section titled "User Defined Property config" for more information.
logLevel: string | undefined - defined as follows:
none
or undefined: calls tolog
will not write to the console or call the RVHostlog
API.error
: calls tolog
will write to the console.verbose
: calls tolog
will write to the console and also call the RVHostlog
API.
User Defined Property config (added in minor 1.2.0)
Refresh intervals may be defined by channel and feed number using Channel-1.Interval
/ Feed-1.Interval
/ Feed-1.Channel
as the naming convention for the user-defined properties. These can be mapped to specific channel or feedContainers in the app. This is to configure apps that have multiple sources, but we also support an updateInterval
property for single source apps. Note that this property can only be used if there is a single source; the app will log a warning if used with multiple sources.
HelloWorld Example
App.vue
<template>
<hello-world :msg="helloMessage" />
</template>
<script setup>
/** Utils */
import { useEventBus } from "@vueuse/core";
/** Components */
import HelloWorld from "@/components/HelloWorld.vue";
import { inject } from "vue";
const helloMessage = "Welcome to the rvHost boilerplate";
const rvData = inject("rvData");
const rvHost = inject("rvHost");
const logger = inject("logger");
const eventBusKey = Symbol("eventBusSymbol");
console.log(logger);
console.log(rvData);
console.log(rvHost);
/** Plugin event Bus DO NOT REMOVE */
const pluginBus = useEventBus(eventBusKey); // This is the event bus for notifications about container updates based on your configuration
pluginBus.on((event) => {
switch (event.type) {
case "containerUpdated":
console.log(event.info);
// this bus notifies the app that there is new container data to be consumed.
// Call the hydrateContainer Method for the container in rvData that matches the guid when desired by your application.
break;
default:
break;
}
});
</script>
HelloWorld.vue
<script setup>
import { ref } from 'vue'
defineProps({
msg: String,
})
const count = ref(0)
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<button type="button" @click="count++">count is {{ count }}</button>
<p>
Edit
<code>components/HelloWorld.vue</code> to test HMR
</p>
</div>
<p>
Check out
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
>create-vue</a
>, the official Vue + Vite starter
</p>
<p>
Install
<a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
in your IDE for a better DX
</p>
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
Unit Testing
Run pnpm test:unit
to run unit tests.
Build
Run pnpm build
to build a publishable app. Files will be written to the lib
subdirectory (exposed by package.json
).
package.json
exposes the lib
folder and uses microbundle without source maps:
"version": "1.2.0",
"description": "Vue plugin for CRI Vue3",
"type": "module",
"source": "./src/index.ts",
"exports": {
"types": "./lib/index.d.ts",
"require": "./lib/index.cjs",
"default": "./lib/index.modern.js"
},
"main": "./lib/index.cjs",
"types": "./lib/index.d.ts",
"module": "./lib/index.module.js",
"unpkg": "./lib/index.umd.js",
"files": [
"lib"
],