Package Exports
- roku-deploy
- roku-deploy/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (roku-deploy) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
roku-deploy
This is the V4 branch, it's a work in progress.
Publish Roku projects to a Roku device by using Node.js.
Table of Contents
- Installation
- Requirements
- Upgrading to V4
- CLI Usage
- JavaScript Usage
- Options Priority Order
- Files Array
- Available roku-deploy Options
- Troubleshooting
- Changelog
Installation
npm install roku-deployRequirements
Your project must be structured the way that Roku expects. The source files can be in a subdirectory (using the
rootDirconfig option), but whever your roku files exist, they must align with the following folder structure:components/ images/ source/ manifest locale/ fonts/
You should create a rokudeploy.json file at the root of your project that contains all of the overrides to the default options. roku-deploy will auto-detect this file and use it when possible. (note:
rokudeploy.jsonis jsonc, which means it supports comments).
sample rokudeploy.json
{
"host": "192.168.1.101",
"password": "securePassword"
}Upgrading to v4
The new release has a few breaking changes that is worth going over in order to prepare developers for what they will need to change when they choose to upgrade.
JavaScript functions don't load config files from disk
In v3, files like roku-deploy.json and bsconfig.json would be loaded anytime a rokuDeploy function was called through the NodeJS api. This functionality has been removed in v4 so that developers have more control over when the config files are loaded. If your script needs to load the config file values, you can simply call util.getOptionsFromJson before calling the desired rokuDeploy function. Here's an example:
const config = {
//get the default options
...rokuDeploy.getOptions(),
//override with any values found in the `rokudeploy.json` file
...util.getOptionsFromJson({ cwd: process.cwd() })
};
await rokuDeploy.sideload(options);Removed support for bsconfig.json
We've removed support for loading bsconfig.json files. This was introduced in v3, but sometimes causes confusion between various systems (like brighterscript, vscode extension, etc). If you need to load values from a bsconfig.json, you can explicitly specify the config path. Like this:
const config = {
//get the default options
...rokuDeploy.getOptions(),
//override with any values found in
...util.getOptionsFromJson({ configPath: './bsconfig.json' })
};
//call some rokuDeploy function
await rokuDeploy.sideload(options);Changed, added, or moved some functions in the main Node API
Another set of changes are the names and features available in the Node API. Some have been renamed and others have been change to be used only as CLI commands in order to organize and simplify what is offered. Renamed functions:
zipPackage()->zip()pressHomeButton()->closeChannel()publish()->sideload()signExistingPackage()->createSignedPackage()deleteInstalledChannel()->deleteDevChannel()takeScreenshot()->captureScreenshot()
Some functions were added to help with certain developer usecases. These mostly allow for any remote-to-Roku interaction:
keyPress()keyUp()keyDown()sendText()
Previously, some functions were available in the Node API, but have been moved to CLI commands. These are:
deploy()createPackage()deployAndSignPackage()
Default file array changed
Lastly, the default files array has changed. node modules and static analysis files have been excluded to speed up load times. Also, fonts/ and locale/ was added as they are in some Roku documentation. The new default array can be seen in the section titled Files Array
CLI Usage
Deploy a zip package
Deploy a .zip package of your project to a roku device
npx roku-deploy deploy --host 'ip.of.roku' --password 'password of device' --rootDir '.' --outDir './out'Create a signed package of your project
npx roku-deploy deploy package --host 'ip.of.roku' --password 'password' --signingPassword 'signing password'Stage the root directory
npx roku-deploy stage --stagingDir './path/to/staging/dir' --rootDir './path/to/root/dir'Zip the contents of a given directory
npx roku-deploy zip --stagingDir './path/to/root/dir' --outDir './path/to/out/dir'Press the Home key
npx roku-deploy keyPress --key 'Home' --host 'ip.of.roku' --remotePort 1234 --timeout 5000Sideload a build
npx roku-deploy sideload --host 'ip.of.roku' --password 'password' --outDir './path/to/out/dir'Convert to SquashFS
npx roku-deploy squash --host 'ip.of.roku' --password 'password'Create a signed package
npx roku-deploy sign --host 'ip.of.roku' --password 'password'You can view the full list of commands by running:
npx roku-deploy --helpJavaScript Usage
Copying the files to staging
If you'd like to use roku-deploy to copy files to a staging folder, you can do the following:
import { rokuDeploy } from 'roku-deploy';
rokuDeploy.stage({
rootDir: "folder/with/your/source/code",
stagingDir: 'path/to/staging/folder',
files: [
"source/**/*",
"components/**/*",
"images/**/*",
"manifest",
"locale/**/*",
"fonts/**/*"
],
//...other options if necessary
}).then(function(){
//the files have been copied to staging
}, function(error) {
//it failed
console.error(error);
});Creating a zip from an already-populated staging folder
Use this logic if you'd like to create a zip from your application folder.
//create a signed package of your project
rokuDeploy.zip({
outDir: 'folder/to/put/zip',
stagingDir: 'path/to/files/to/zip',
outFile: 'filename-of-your-app.zip'
//...other options if necessary
}).then(function(){
//the zip has been created
}, function(error) {
//it failed
console.error(error);
});Pressing the Home key
rokuDeploy.keyPress({
key: 'Home'
//...other options if necessary
})Sideloading a project
If you've already created a zip using some other tool, you can use roku-deploy to sideload the zip.
//sideload a package onto a specified Roku
rokuDeploy.sideload({
host: 'ip-of-roku',
password: 'password for roku dev admin portal',
outDir: 'folder/where/your/zip/resides/',
outFile: 'filename-of-your-app.zip'
//...other options if necessary
}).then(function(){
//the app has been sideloaded
}, function(error) {
//it failed
console.error(error);
});Convert to SquashFS
rokuDeploy.convertToSquashfs({
host: '1.2.3.4',
password: 'password'
//...other options if necessary
})Create a signed package
rokuDeploy.createSignedPackage({
host: '1.2.3.4',
password: 'password',
signingPassword: 'signing password',
stagingDir: './path/to/staging/directory'
//...other options if necessary
})Can't find what you need? We offer a variety of functions available in the RokuDeploy.ts file. Here are all of the public functions:
stage()zip()sideload()getFilePaths()keyPress()keyUp()keyDown()sendText()closeChannel()rekeyDevice()createSignedPackage()deleteDevChannel()captureScreenshot()getOptions()checkRequiredOptions()getDeviceInfo()getDevId()
Running roku-deploy as an npm script
From an npm script in package.json. (Requires rokudeploy.json to exist at the root level where this is being run)
{
"scripts": {
"deploy": "roku-deploy"
}
}Options Priority Order
RokuDeploy can be configured in various ways (cli args, roku-deploy.json, parameters, and defaults). Here's the order these options will be loaded:
When run from the CLI:
- start with the default set of options from
rokuDeploy.getOptions() - override with any values found in
roku-deploy.jsonor specified config file - override with any values from CLI args
When run from javascript:
- start with the default set of options from
rokuDeploy.getOptions() - override with any values passed in as function arguments
Files Array
The files array is how you specify what files are included in your project. Any strings found in the files array must be relative to rootDir, and are used as include filters, meaning that if a file matches the pattern, it is included.
For most standard projects, the default files array should work just fine:
{
"files": [
"source/**/*.*",
"components/**/*.*",
"images/**/*.*",
"locale/**/*",
"fonts/**/*",
"manifest",
"!node_modules",
"!**/*.{md,DS_Store,db}"
]
}This will copy all files from the standard roku folders directly into the package while maintaining each file's relative file path within rootDir.
If you want to include additonal files, you will need to provide the entire array. For example, if you have a folder with other assets, you could do the following:
{
"files": [
"source/**/*.*",
"components/**/*.*",
"images/**/*.*",
"locale/**/*",
"fonts/**/*",
"manifest",
"!node_modules",
"!**/*.{md,DS_Store,db}",
//your folder with other assets
"assets/**/*"
]
}Excluding Files
You can also prefix your file patterns with "!" which will exclude files from the output. This is useful in cases where you want everything in a folder EXCEPT certain files. The files array is processed top to bottom. Here's an example:
{
"files": [
"source/**/*",
"!source/some/unwanted/file.brs"
]
}Top-level String Rules
All patterns will be resolved relative to
rootDir, with their relative positions withinrootDirmaintained.No pattern may reference a file outside of
rootDir. (You can use{src;dest}objects to accomplish) For example:{ "rootDir": "C:/projects/CatVideoPlayer", "files": [ "source/main.brs", //NOT allowed because it navigates outside the rootDir "../common/promise.brs" ] }Any valid glob pattern is supported. See glob on npm for more information.
Empty folders are not copied
Paths to folders will be ignored. If you want to copy a folder and its contents, use the glob syntax (i.e.
some_folder/**/*)
Advanced Usage
For more advanced use cases, you may provide an object which contains the source pattern and output path. This allows you to get very specific about what files to copy, and where they are placed in the output folder. This option also supports copying files from outside the project.
The object structure is as follows:
{
/**
* a glob pattern string or file path, or an array of glob pattern strings and/or file paths.
* These can be relative paths or absolute paths.
* All non-absolute paths are resolved relative to the rootDir
*/
src: Array<string|string[]>;
/**
* The relative path to the location in the output folder where the files should be placed, relative to the root of the output folder
*/
dest: string|undefined
}{ src; dest } Object Rules
if
srcis a non-glob path to a single file, thendestshould include the filename and extension. For example:{ src: "lib/Promise/promise.brs", dest: "source/promise.brs"}if
srcis a glob pattern, thendestshould be a path to the folder in the output directory. For example:{ src: "lib/*.brs", dest: "source/lib"}if
srcis a glob pattern that includes**, then all files found insrcafter the**will retain their relative paths insrcwhen copied todest. For example:{ src: "lib/**.brs", dest: "source/lib"}if
srcis a path to a folder, it will be ignored. If you want to copy a folder and its contents, use the glob syntax. The following example will copy all files from thelib/vendorfolder recursively:{ src: "lib/vendor/**/*", dest: "vendor" }if
destis not specified, the root of the output folder is assumed
Collision Handling
roku-deploy processes file entries in order, so if you want to override a file, just make sure the one you want to keep is later in the files array
For example, if you have a base project, and then a child project that wants to override specific files, you could do the following:
{
"files": [
{
//copy all files from the base project
"src": "../BaseProject/**/*"
},
//override "../BaseProject/themes/theme.brs" with "${rootDir}/themes/theme.brs"
"themes/theme.brs"
]
}Available roku-deploy Options
Here are the available options for customizing to your developer-specific workflows. The defaults are shown to the right of the option name, but all can be overridden:
host: string (required) The IP address or hostname of the target Roku device. Example:
"192.168.1.21".password: string (required) The password for logging in to the developer portal on the target Roku device.
signingPassword: string (required for signing) The password used for creating signed packages.
rekeySignedPackage: string (required for rekeying) Path to a copy of the signed package you want to use for rekeying.
devId: string Dev ID we are expecting the device to have. If supplied we check that the dev ID returned after keying matches what we expected.
outDir?: string =
"./out"A full path to the folder where the zip/pkg package should be placed.outFile?: string =
"roku-deploy"The base filename the zip/pkg file should be given (excluding the extension).rootDir?: string =
'./'The root path to the folder holding your project. The manifest file should be directly underneath this folder. Use this option when your roku project is in a subdirectory of where roku-deploy is installed.files?: ( string | { src: string; dest: string; } ) [] =
[ "source/**/*.*", "components/**/*.*", "images/**/*.*", "locale/**/*", "fonts/**/*", "manifest", "!node_modules", "!**/*.{md,DS_Store,db}" ]An array of file paths, globs, or
{ src: string; dest: string }objects that will be copied into the deployment package. Make sure to exclusively use forward slashes (/) for path separators (even on Windows), as backslashes are reserved for character escaping. You can learn more about this requirement here.Using the {src;dest} objects will allow you to move files into different destination paths in the deployment package. This would be useful for copying environment-specific configs into a common config location (i.e. copy from
"ProjectRoot\configs\dev.config.json"to"roku-deploy.zip\config.json"). Here's a sample://deploy configs/dev.config.json as config.json { "src": "configs/dev.config.json", "dest": "config.json" }//you can omit the filename in dest if you want the file to keep its name. Just end dest with a trailing slash. { "src": "languages/english/language.xml", "dest": "languages/" }This will result in the
[sourceFolder]/configs/dev.config.jsonfile being copied to the zip file and named"config.json".You can also provide negated globs (thanks to glob-all). So something like this would include all component files EXCEPT for specs.
files: [ 'components/**/*.*', '!components/**/*.spec.*' ]NOTE: If you override this "files" property, you need to provide all config values, as your array will completely overwrite the default.
stagingDir?: string =
`${options.outDir}/.roku-deploy-staging`The path to the staging folder (where roku-deploy places all of the files right before zipping them up).convertToSquashfs?: boolean =
falseIf true we convert to squashfs before creating the pkg file.username?: string =
"rokudev"The username for the roku box. This will always be 'rokudev', but allow to be passed in just in case roku adds support for custom usernames in the future.packagePort?: number =
80The port used for package-related requests. This is mainly used for things like emulators, or when your roku is behind a firewall with a port-forward.remotePort?: number =
8060The port used for sending remote control commands (like home press or back press). This is mainly used for things like emulators, or when your roku is behind a firewall with a port-forward.screenshotDir?: string =
"./tmp/roku-deploy/screenshots/"The directory where screenshots should be saved. Will use the OS temp directory by default.timeout?: number =
150000The number of milliseconds at which point this request should timeout and return a rejected promise.remoteDebug?: boolean =
falseWhen publishing a side loaded channel this flag can be used to enable the socket based BrightScript debug protocol. This should always befalseunless you're creating a plugin for an editor such as VSCode, Atom, Sublime, etc. More information on the BrightScript debug protocol can be found here: https://developer.roku.com/en-ca/docs/developer-program/debugging/socket-based-debugger.mdcwd?: string =
process.cwd()The current working directory, which all other paths will be set relative to. If left to default, it will be set as the process.cwd() method, which returns the current working directory of the Node.js process.deleteDevChannel?: boolean =
trueIf true the previously installed dev channel will be deleted before installing the new one.packageUploadOverrides?: Overrides for values used during the zip upload process. You probably don't need to change these...
logLevel?: string =
"error"The level lof logging information printed in the console. You can read more information here
Click here to see the typescript interface for these options
Troubleshooting
- if you see a
ESOCKETTIMEDOUTerror during deployment, this can be caused by an antivirus blocking network traffic, so consider adding a special exclusion for your Roku device.
Changelog
Click here to view the changelog