BrightScript encoder/decoder generator for Protocol Buffers. Feed it .proto files and it will:
- Parse the schema bundle.
- Emit BrightScript runtime helpers plus message-specific encode/decode modules.
- Optionally generate JSON baseline vectors (via
protobufjs) for parity testing. - Mirror the output into a Roku harness so it can be exercised on-device.
Install globally (or run via npx):
npm install -g protoc-gen-brsGenerate BrightScript modules:
protoc-gen-brs generate \
--proto path/to/schema.proto \
--proto path/to/another.proto \
--outDir ./brs-outputCreate baseline fixtures:
protoc-gen-brs baseline \
--proto path/to/schema.proto \
--fixtureDir ./fixtures/parityBoth commands accept multiple --proto values (files or directories).
Decoder field casing defaults to snake_case. Pass --decodeCase camel to generate decoders that hydrate camelCase keys (useful for BrightScript code that prefers Roku script conventions), or --decodeCase both to emit both snake_case and camelCase keys simultaneously.
- Node.js 18+ (the toolchain relies on ESM compatible features and async/await).
- Roku SDK tooling if you intend to side-load and run the bundled Roku app.
Install dependencies after cloning:
npm installnpm run build– Compile the TypeScript CLI intodist/.npm run build:roku– Invoke BrighterScript (bsc) to compile the Roku app sources (Node ≤ 22 recommended untilroku-deployupdates its dependencies).npm run package:roku– Createout/channel.zipusingroku-deploy(zipsout/without contacting a device).npm run generate:brs -- --proto <paths>– Load.protoinputs and emit BrightScript encoders/decoders plus registry files intoroku-app/source/generated/.npm run generate:baseline -- --proto <paths>– Render JSON baseline vectors intofixtures/baseline/and mirror them intoroku-app/source/generated/__baselineData.brsfor the Roku harness.npm run clean– Remove build artifacts and generated fixtures.
Tip: use directories like
proto/or individual.protofiles with--proto. Multiple values are allowed.
# Generate the BrightScript encoder/decoder from the sample schema
npm run generate:brs -- --proto proto/simple.proto
# Produce baseline JSON + BrightScript fixture data
npm run generate:baseline -- --proto proto/simple.proto
# Compile Roku sources (requires Node 22 or earlier today)
npm run build:roku
# Side-load ./out/ to a developer Roku device and run the channelThe Roku app prints per-case comparisons plus a summary tally. The scaffold currently handles a message with a single string field; expanding the generator logic will broaden coverage.
The npm run roku:test script regenerates the runtime + baseline fixtures, side-loads the channel, and collects the telnet log from a developer device (requires ROKU_HOST / ROKU_PASSWORD).
During generation we normally pass --pruneDefaults so proto2 default values are stripped in both the encoded payloads and JSON baselines. This mirrors the behaviour the Roku runtime now implements and keeps the parity checks focused on user-set fields.
-
Default run (pruned):
ROKU_HOST=... ROKU_PASSWORD=... npm run roku:test
This matches
--pruneDefaultson bothgenerate:brsandgenerate:baseline. -
Skip pruning:
ROKU_HOST=... ROKU_PASSWORD=... npm run roku:test -- --no-prune
Useful when you need to inspect raw proto defaults or compare behaviour with legacy fixtures. This omits
--pruneDefaultsfor both generators. -
Explicitly re-enable pruning (e.g. after using
--no-prune):ROKU_HOST=... ROKU_PASSWORD=... npm run roku:test -- --prune
You can also control the default via environment variable:
export ROKU_PRUNE_DEFAULTS=false # or true
ROKU_HOST=... ROKU_PASSWORD=... npm run roku:testCLI flags (--prune, --no-prune) take precedence over ROKU_PRUNE_DEFAULTS. The full capture is written to out/roku-log.txt either way.
src/– TypeScript CLI and generation logic.proto/– Source.protofiles (recursive discovery).generated/source/– BrightScript output staging area (consumed by BrighterScript).fixtures/baseline/– JavaScript baseline data for cross-platform validation.roku-app/– Roku application skeleton that will load generated code and fixtures.
- Broaden generator coverage (additional numeric types, bytes, repeated fields, nested messages, enums).
- Allow configurable fixtures (custom values, multiple cases per message, failure scenarios).
- Automate Roku deployment/execution (roku-deploy integration, on-device reporting).
- Add automated testing (TypeScript unit coverage + BrightScript simulation tests).