Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,12 @@ sample rokudeploy.json
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. This will default to load from `rokudeploy.json`. Here's an example:
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 `RokuDeploy.loadOptionsFromJson` before calling the desired rokuDeploy function. This will default to load from `rokudeploy.json`. Here's an example:

```javascript
const config = {
//get the default options
...rokuDeploy.getOptions(),
//override with any values found in the `rokudeploy.json` file. You can specify current working directory here.
...util.getOptionsFromJson({ cwd: process.cwd() })
//load options from the `rokudeploy.json` file. You can specify current working directory here.
...RokuDeploy.loadOptionsFromJson({ cwd: process.cwd() })
};
await rokuDeploy.sideload(config);
```
Expand All @@ -70,10 +68,8 @@ We've removed support for loading `bsconfig.json` files. This was introduced in

```javascript
const config = {
//get the default options
...rokuDeploy.getOptions(),
//override with any values found in config file
...util.getOptionsFromJson({ configPath: './bsconfig.json' })
//load options from a custom config file
...RokuDeploy.loadOptionsFromJson({ configPath: './bsconfig.json' })
};
//call some rokuDeploy function
await rokuDeploy.sideload(config);
Expand Down
72 changes: 72 additions & 0 deletions src/RokuDeploy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4473,6 +4473,78 @@ describe('RokuDeploy', () => {
});
});

describe('loadOptionsFromJson', () => {
it('should fill in options from rokudeploy.json', () => {
fsExtra.outputJsonSync(s`${rootDir}/rokudeploy.json`, { password: 'password' });
expect(
RokuDeploy.loadOptionsFromJson({ cwd: rootDir })
).to.eql({
password: 'password'
});
});

it('loads cwd from process', () => {
try {
fsExtra.outputJsonSync(s`${process.cwd()}/rokudeploy.json`, { host: '1.2.3.4' });
expect(
RokuDeploy.loadOptionsFromJson()
).to.eql({
host: '1.2.3.4'
});
} finally {
fsExtra.removeSync(s`${process.cwd()}/rokudeploy.json`);
}
});

it('catches invalid json with jsonc parser', () => {
fsExtra.writeJsonSync(s`${process.cwd()}/rokudeploy.json`, { host: '1.2.3.4' });
sinon.stub(fsExtra, 'readFileSync').returns(`
{
"rootDir": "src"
`);
let ex;
try {
RokuDeploy.loadOptionsFromJson();
} catch (e) {
ex = e;
}
expect(ex).to.exist;
expect(ex.message.startsWith('Error parsing')).to.be.true;
fsExtra.removeSync(s`${process.cwd()}/rokudeploy.json`);
});

it('works when loading stagingDir from rokudeploy.json', () => {
sinon.stub(fsExtra, 'existsSync').callsFake((filePath) => {
return true;
});
sinon.stub(fsExtra, 'readFileSync').returns(`
{
"stagingDir": "./staging-dir"
}
`);
let loadedOptions = RokuDeploy.loadOptionsFromJson();
expect(loadedOptions.stagingDir.endsWith('staging-dir')).to.be.true;
});

it('supports jsonc for rokudeploy.json', () => {
fsExtra.writeFileSync(s`${tempDir}/rokudeploy.json`, `
//leading comment
{
//inner comment
"rootDir": "src" //trailing comment
}
//trailing comment
`);
let loadedOptions = RokuDeploy.loadOptionsFromJson({ cwd: tempDir });
expect(loadedOptions.rootDir).to.equal('src');
});

it('returns empty object when config file does not exist', () => {
const result = RokuDeploy.loadOptionsFromJson({ cwd: '/nonexistent/path' });
expect(result).to.eql({});
});
});

describe('generateBaseRequestOptions', () => {
it('uses default timeout', () => {
const result = rokuDeploy['generateBaseRequestOptions']('test', { host: 'localhost', password: 'test' });
Expand Down
37 changes: 35 additions & 2 deletions src/RokuDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ const request = r;
import * as JSZip from 'jszip';
import * as errors from './Errors';
import * as xml2js from 'xml2js';
import { parse as parseJsonc } from 'jsonc-parser';
import { parse as parseJsonc, printParseErrorCode, type ParseError } from 'jsonc-parser';
import { util } from './util';
import type { FileEntry, RokuDeployConstructorOptions } from './RokuDeployOptions';
import type { FileEntry, RokuDeployConstructorOptions, RokuDeployOptions } from './RokuDeployOptions';
import { logger } from '@rokucommunity/logger';
import * as dayjs from 'dayjs';
import * as lodash from 'lodash';
Expand All @@ -29,6 +29,39 @@ export class RokuDeploy {
outFile: 'roku-deploy.zip'
};

/**
* Load options from a rokudeploy.json file. Used by CLI commands to load configuration.
* @param options - Optional cwd and configPath settings
* @returns The parsed options from the config file, or an empty object if not found
*/
public static loadOptionsFromJson(options?: { cwd?: string; configPath?: string }): RokuDeployOptions {
const cwd = options?.cwd ?? process.cwd();
const configPath = options?.configPath ?? path.join(cwd, 'rokudeploy.json');

if (fsExtra.existsSync(configPath)) {
const configFileText = fsExtra.readFileSync(configPath).toString();
const parseErrors: ParseError[] = [];
const fileOptions = parseJsonc(configFileText, parseErrors, {
allowEmptyContent: true,
allowTrailingComma: true,
disallowComments: false
});
if (parseErrors.length > 0) {
throw new Error(`Error parsing "${path.resolve(configPath)}": ` + JSON.stringify(
parseErrors.map(x => {
return {
message: printParseErrorCode(x.error),
offset: x.offset,
length: x.length
};
})
));
}
return fileOptions;
}
return {};
}

/**
* Instance-level default options that are merged into every method call
*/
Expand Down
4 changes: 2 additions & 2 deletions src/commands/CaptureScreenshotCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class CaptureScreenshotCommand {
async run(args) {
args.cwd ??= process.cwd();

let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.captureScreenshot(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/ConvertToSquashfsCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class ConvertToSquashfsCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.convertToSquashfs(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/CreateSignedPackageCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class CreateSignedPackageCommand {
async run(args) {
args.cwd ??= process.cwd();

let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.createSignedPackage(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/DeleteDevChannelCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class DeleteDevChannelCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.deleteDevChannel(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/GetDevIdCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class GetDevIdCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
const devId = await rokuDeploy.getDevId(options);
Expand Down
5 changes: 2 additions & 3 deletions src/commands/GetDeviceInfoCommand.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { rokuDeploy } from '../index';
import { util } from '../util';
import { rokuDeploy, RokuDeploy, util } from '../index';

export class GetDeviceInfoCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
const outputPath = await rokuDeploy.getDeviceInfo(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/KeyDownCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class KeyDownCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.keyDown(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/KeyPressCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class KeyPressCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.keyPress(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/KeyUpCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class KeyUpCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.keyUp(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/RekeyDeviceCommand.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy, util } from '../index';
import * as path from 'path';

export class RekeyDeviceCommand {
async run(args) {
args.cwd ??= process.cwd();

let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
if (args.pkg) {
Expand Down
4 changes: 2 additions & 2 deletions src/commands/RemoteControlCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import * as readline from 'readline';
import type { RokuKey } from '../index';
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class RemoteControlCommand {
run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};

Expand Down
4 changes: 2 additions & 2 deletions src/commands/SendTextCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class SendTextCommand {
async run(args) {
let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.sendText(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/SideloadCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class SideloadCommand {
async run(args) {
args.cwd ??= process.cwd();

let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};

Expand Down
4 changes: 2 additions & 2 deletions src/commands/StageCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class StageCommand {
async run(args) {
args.cwd ??= process.cwd();

let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.stage(options);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/ZipCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { rokuDeploy, util } from '../index';
import { rokuDeploy, RokuDeploy } from '../index';

export class ZipCommand {
async run(args) {
args.cwd ??= process.cwd();

let options = {
...util.getOptionsFromJson(args),
...RokuDeploy.loadOptionsFromJson(args),
...args
};
await rokuDeploy.zip(options);
Expand Down
Loading
Loading