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

@dazn/kopytko-packager

v1.2.5

Published

Modern Roku apps packager

Downloads

24

Readme

Kopytko Packager

A package builder for the Roku platform.

The packager consists of the following features:

  • generate environment-specific manifest
  • copy files of external modules ("Kopytko Modules") installed via NPM
  • import internal and external brightscript dependencies
  • pack & zip the files
  • deploy a package to the Roku device
  • rekey the Roku device with given signed package
  • generate a package ready to upload to the Roku channel
  • prepare and build an app for the Visual Studio Code extension
  • take a screenshot of the dev app

Listing

Prerequisites

  • node version 16+
  • npm version 8+

Quick start

  1. Install the Packager
npm install @dazn/kopytko-packager --save-dev
  1. Create .kopytkorc in the root folder with minimal configuration
{
  "baseManifest": "manifest/base.js"
}
  • If your app code is not located under default /app, configure it in a sourceDir attribute
  • Path to base manifest is only example
  1. Create a base manifest file
const { baseManifest } = require('@dazn/kopytko-packager');

module.exports = {
  ...baseManifest,
  title: 'Your app title',
  mm_icon_focus_hd: 'pkg:/images/icon.png', // it is only an example path
  mm_icon_focus_sd: 'pkg:/images/icon.png',
  splash_screen_hd: 'pkg:/images/splash.png',
  splash_screen_sd: 'pkg:/images/splash.png',
}
  1. Configure start script in your package.json
"scripts": {
  "start": "node node_modules/@dazn/kopytko-packager/scripts/start.js"
}
  1. Start the app
npm start

Kopytko cli package

It is recommended to use kopytko-cli package and add it to package.json scripts:

npm install @dazn/kopytko-packager --save-dev
"scripts": {
  "start": "kopytko start",
  "build": "kopytko build",
  "test": "kopytko test"
}

Configuration

The main configuration file .kopytkorc should be placed in the root folder of the project. The example file looks like this:

{
  "archivePath": "/dist/kopytko_archive.zip",
  "generatedPackagePath": "/dist/kopytko_package.pkg",
  "signedPackagePath": "/previous/signed.pkg",
  "baseManifest": "/manifest/base.js",
  "localManifestOverride": "/manifest/local.${args.env}.js",
  "screenshotDir": "/dist",
  "pluginDefinitions": {},
  "plugins": [],
  "sourceDir": "/app",
  "environments": {
    "production": {
      "manifest": "/env/production.js",
      "plugins": []
    },
    "staging": {
      "manifest": "/env/staging.js"
    },
    "test": {
      "manifest": "/env/test.js"
    }
  }
}

Available fields:

  • archivePath [@type string @optional] - path to the app archive to generate; default value as in the example file above
  • generatedPackagePath [@type string @optional] - path to the app package to generate; default value as in the example file above
  • baseManifest [@type string @required] - base manifest file path. Having the file is sufficient to run the Roku app
  • localManifestOverride [@type string @optional] - path to the configuration file that overrides all other settings. Usually the file is on the git ignore list
  • screenshotDir [@type string @optional] - the directory where screenshots will be saved; default value as in the example file above
  • pluginDefinitions [@type [name: string]:object @optional] - plugin definitions (see plugins)
  • plugins @optional - global plugins list (see plugins)
  • environments [@type [name: string]:object @optional] - list of environments. The name should correspond to the ENV value. Each environment entry consists of:
    • manifest [@type string @required] - path to configuration file
    • plugins environment's plugins list (see plugins)
  • sourceDir [@type string @optional] - directory of app's source code; default value as in the example file above
  • tempDir [@type string @optional] - absolute path of a temporary folder used during a building process as a project directory. After build, it is removed; default value is operating system directory for temporary files

archivePath and generatedPackagePath also could be defined as string templates to dynamically generate name of the created files. Example of generatedPackagePath: 'MyApp-v${manifest.major_version}.${manifest.minor_version}.${manifest.build_version}-${args.env}.pkg'. Resolves into: 'MyApp-v1.0.0-production.pkg'. Above example will take values from given manifest file and arguments passed to the build or generate-package script.

The configuration files work in waterfall scheme meaning that baseManifest is loaded as the first file. Each environment entry overrides base configuration. The localManifestOverride is loaded as the last one overriding all others.

Scripts

The packager contains the following scripts:

  • scripts/build.js - builds the app
  • scripts/start.js - builds and deploys the app to the device
  • scripts/generate-package.js - rekey device if needed, builds, deploys the app to the device and finally signs and download the package
  • scripts/prepare-for-vsc.js - helpful when using debugging protocol in the VSC extension
  • scripts/screenshot.js - takes a screenshot of the current dev application (works only with dev channel), screenshot file name - Screenshot_<Date as ISOString>.jpg

Example usage:

"scripts": {
  "build-prod": "node node_modules/@dazn/kopytko-packager/scripts/build.js --env=production",
  "start": "node node_modules/@dazn/kopytko-packager/scripts/start.js"
}

Available parameters:

  • env - your environment value that matches entry in the .kopytkorc file. Default value (if not passed) is "dev"
  • rokuDevPassword - dev password
  • rokuDevUser - dev user
  • rokuDevId - dev id, needed to rekey the device
  • rokuDevSigningPassword - dev signing password needed to rekey the device and sign packages
  • rokuIP - IP of your roku device
  • signedPackagePath - path to the package of the existing app (signed package), needed to rekey the device
  • telnet - true/false, when true the packager will open the telnet session after deploying app to the device
  • forceHttp - true/false, when true all the urls in the manifest file that start with https will be overwritten to http

If an unnamed parameter is passed, it is treated as env parameter:

npm start -- production
# is a shortcut for:
npm start -- --env=production

.env file

To avoid the necessity of passing parameter with every script run, a .env file could be used. Documentation can be found here.

Available fields: ENV, ROKU_DEV_ID, ROKU_DEV_PASSWORD, ROKU_DEV_SIGNING_PASSWORD, ROKU_DEV_USER, ROKU_IP, SIGNED_PACKAGE_PATH, TELNET, FORCE_HTTP

Generate package script

By running this kopytko-packager will create a signed package. This script automates Packaging Roku channels

It contains 4 steps:

Package will be saved under generatedPackagePath if it was provided in .kopytkorc file, or in /dist/kopytko_package.pkg if generatedPackagePath was not provided.

To be able to generate the package following script arguments are required (or env variables):

  • ROKU_DEV_ID
  • ROKU_DEV_PASSWORD
  • ROKU_DEV_SIGNING_PASSWORD
  • ROKU_DEV_USER
  • ROKU_IP
  • SIGNED_PACKAGE_PATH

If you already have an app on your Roku channel, you will need to provide a previously signed package, to rekey the Roku device. If this is your first version of the app and you don't have ROKU_DEV_ID and ROKU_DEV_SIGNING_PASSWORD yet:

  1. Open a telnet session
  2. Generate new signing keys.

Plugins

Plugin is a code triggered during the build process of a project. There are few built-in plugins, one of them is executed regardless .kopytkorc config (kopytko-generate-manifest), but you can use and create custom plugins. To get information how to configure or write your own plugin check /docs/PLUGINS.md.

Built-in plugins:

Generating manifest file

Kopytko packager dynamically generates the manifest file by transpiling JavaScript configuration files, so you don't have to keep it in the source code anymore. It is done by the kopytko-generate-manifest plugin, configured out-of-the-box.

The example default manifest file:

module.exports = {
  title: 'Some Title',
  bs_const: {
    debug: true,
  },
};

will be transpiled to a manifest file:

title=Some Title
bs_const=debug=true

You can override @dazn/kopytko-packager/base-manifest.js which contains all required by Roku fields and dynamically sets app version based on your package.json.

Copying external Kopytko Modules

kopytko-copy-external-dependencies plugin lets you use external Kopytko Modules. A Kopytko Module is an NPM module with the kopytko-module keyword. The plugin creates a dependency list based on your package prod dependencies (and their prod dependencies, recursively) and direct dev dependencies (without their any dependencies). If your project in overall has dependencies on the same module but in different versions, the plugin will automatically use only the highest version of every major version dependency. Once a dependency list is generated, the plugin automatically copies their /components and /source directories (taking into account kopytkoModuleDir value configured in dependencies package.json file). So far the plugin doesn't copies neither images nor fonts directories.

You can get the list of available public Kopytko Modules here. If you want to share your Roku library with the community and create your own Kopytko Module, check the Creating Kopytko Module paragraph.

The plugin creates

Dependencies importing mechanism

Import dependencies from internal files and external Kopytko Modules using the @import annotation. Each of dependency will be automatically added as a </script> entry into the scope of XML file. Nested dependencies and copying external Kopytko Modules files to the package supported.

Configuration

Add predefined, built-in kopytko-import-dependencies and, if you use external Kopytko Modules, kopytko-copy-external-dependencies plugins into your .kopytkorc config file. We recommend configuring kopytko-copy-external-dependencies to be run before environment plugins so every next plugin can manipulate dependencies code if needed:

"plugins": [
   { "name": "kopytko-copy-external-dependencies", "preEnvironmentPlugin": true },
   "kopytko-import-dependencies"
 ],
  • kopytko-copy-external-dependencies copies all (even unused in the project) files from dependency modules
  • kopytko-import-depenencies translates @import annotations and imports related dependencies in XML files

Importing internal dependencies

Import other internal .brs file via ' @import /<path> at the beginning of the file. The pkg: prefix will be automatically added into the XML file.

Example:

' @import /components/utils.brs
' @import /source/superFunction.brs
function init()
end function

Importing external dependencies

Import a .brs file from an external Kopytko Module via ' @import /<path> from <package-name>. Every external dependency entry will be automatically added into the XML file with a proper path to the copied file.

All functions and components definitions and usages will be prefixed with a standardized module name and version (normalized to Brightscript's requirements). E.g. function superFunction() from @kopytko/utils v1 will be renamed into kopytko_utils_v1_superFunction. This mechanism prevents naming collisions (e.g. when an imported external module has defined a function with the same name as one of your internal functions).

Example:

' @import /components/externalUtil.brs from @kopytko/utils

will be changed into pkg:/components/kopytko_modules/kopytko_utils_v1/externalUtils.brs XML script entry.

Kopytko-packager imports nested external dependencies out-of-the-box.

Creating Kopytko Module

  • add "kopytko-module" to "keywords" field in your module's package.json file
  • if your components and source directories are not placed in the root directory, configure it in the "kopytkoModuleDir" field in package.json, e.g. "kopytkoModuleDir": "app/"
  • be aware so far Kopytko Module supports copying only the two mentioned above directories
  • if your module is designed to be used as a direct dev dependency (e.g. a module for debugging the non-production app), and it uses some other Kopytko Modules, define them as peerDependency because Kopytko Packager doesn't install any dependencies of direct dev dependencies. Thanks to this, it will notify the end user to install your peer dependencies as dev dependencies too.