Skip to content

Commit

Permalink
feat: command-specific configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
dlenroc authored Oct 29, 2023
1 parent 9490e8f commit c4524e8
Show file tree
Hide file tree
Showing 73 changed files with 628 additions and 547 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
},
"devDependencies": {
"@tsconfig/node20": "^20.1.2",
"@types/node": "^20.8.7",
"@tsconfig/strictest": "^2.0.2",
"@types/node": "^20.8.9",
"@types/sinon": "^10.0.20",
"sinon": "^17.0.0",
"ts-node": "^10.9.1",
"tsx": "^3.14.0",
"typescript": "^5.2.2"
}
}
150 changes: 28 additions & 122 deletions packages/debug-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,136 +11,42 @@ npm install @dlenroc/roku-debug-server
## Usage

```typescript
import { TelnetExecutor, getPlugins } from '@dlenroc/roku-debug-server';
import { DebugServerExecutor, getPlugins } from '@dlenroc/roku-debug-server';

const ctx = new TelnetExecutor({
const ctx = new DebugServerExecutor({
hostname: '<ip>',
port: '8080'
port: 8080,
});

// raw
const rawPlugins = await ctx.execute('plugins');
console.log(rawPlugins);

// typed
const plugins = await getPlugins(ctx);
console.log(plugins);
```

---

```typescript
clearLaunchCaches(ctx: Executor): Promise<void>
```

```typescript
clearSceneGraphPerformanceData(executor: Executor): Promise<void>
```

```typescript
clearSceneGraphPerformanceData(executor: Executor): Promise<void>
```

```typescript
createDeveloperKey(executor: Executor): Promise<DeveloperKey>
```

```typescript
disableRendezvousLogging(executor: Executor): Promise<void>
```

```typescript
enableRendezvousLogging(executor: Executor): Promise<void>
```

```typescript
getChannelPerformanceData(executor: Executor): Promise<ChannelStats>
```

```typescript
getDeveloperKey(executor: Executor): Promise<string>
```

```typescript
getLoadedTextures(executor: Executor, overlay?: string): Promise<LoadedTextures>
```

```typescript
getMaxWarningCount(executor: Executor): Promise<number>
```

```typescript
getMemoryStats(executor: Executor): Promise<MemoryStats>
```

```typescript
getPlugins(executor: Executor, idOrName?: number | string): Promise<{ plugins: Plugin[] }>
```

```typescript
getProfilingStatus(executor: Executor): Promise<ProfilingStatus>
```

```typescript
getR2D2Bitmaps(executor: Executor): Promise<R2D2Bitmap[]>
```

```typescript
getRendezvousLoggingStatus(executor: Executor): Promise<RendezvousLoggingStatus>
```

```typescript
getSceneGraphNodes(executor: Executor, node: string): Promise<string>
```

```typescript
getSceneGraphPerformanceData(executor: Executor): Promise<SceneGraphPerformance[]>
```

```typescript
hideFPS(executor: Executor): Promise<void>
```

```typescript
pauseProfiling(executor: Executor): Promise<void>
```

```typescript
press(executor: Executor, keys: string): Promise<void>
```

```typescript
removePlugin(executor: Executor, id: number | 'dev'): Promise<void>
```

```typescript
resumeProfiling(executor: Executor): Promise<void>
```

```typescript
scheduleChannelStats(executor: Executor, intervalInSeconds: number): Promise<number>
```

```typescript
setMaxWarningCount(executor: Executor, count: number): Promise<number>
```

```typescript
showFPS(executor: Executor): Promise<void>
```

```typescript
startSceneGraphPerformanceTracking(executor: Executor): Promise<void>
```

```typescript
stopSceneGraphPerformanceTracking(executor: Executor): Promise<void>
// raw
const rawResult = await ctx.execute('plugins', []);
console.log(rawResult);
```

```typescript
toggleFPS(executor: Executor): Promise<void>
```
---

```typescript
type(executor: Executor, text: string): Promise<void>
```
| Method | Command | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | --------------------------------------------------------- |
| `clearLaunchCaches` | `clear_launch_caches` | Clear all caches that can affect channel launch time |
| `clearSceneGraphPerformanceMetrics` <br> `getSceneGraphPerformanceMetrics` <br> `startSceneGraphPerformanceTracking` <br> `stopSceneGraphPerformanceTracking` | `sgperf` | SceneGraph node operation performance metrics |
| `createDeveloperKey` | `genkey` | Generate a new developer key |
| `disableRendezvousLogging` <br> `enableRendezvousLogging` <br> `getRendezvousLoggingStatus` | `logrendezvous` | Turn Rendezvous Logging on or off |
| `getChannelPerformanceStats` <br> `scheduleChannelPerformanceLogging` | `chanperf` | Show channel CPU and memory usage |
| `getDeveloperKey` | `showkey` | Show the current developer key |
| `getLoadedTextures` | `loaded_textures` | Show loaded textures (default main RenderContext) |
| `getMaxWarningCount` <br> `setMaxWarningCount` | `brightscript_warnings` | Set the maximum number of brightscript warnings displayed |
| `getMemoryStats` | `free` | Return the output of the free(1) command |
| `getPlugins` | `plugins` | Show list of all installed plugins |
| `getProfilingStatus` | `bsprof-status` | Get BS profiling status |
| `getR2D2Bitmaps` | `r2d2_bitmaps` | Enumerate R2D2 bitmaps |
| `getSceneGraphNodes` | `sgnodes` | List Scene Graph nodes |
| `hideFPS` <br> `showFPS` <br> `toggleFPS` | `fps_display` | Display onscreen graphics statistics |
| `pauseProfiling` | `bsprof-pause` | Pause BS profiling |
| `press` | `press` | Simulate a keypress |
| `removePlugin` | `remove_plugin` | Remove a plugin from the account and device |
| `resumeProfiling` | `bsprof-resume` | Resume BS profiling |
| `type` | `type` | Send a literal text sequence |
2 changes: 1 addition & 1 deletion packages/debug-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
],
"scripts": {
"build": "tsc --build --force tsconfig.build.json",
"test": "node --no-warnings --loader ts-node/esm --test-reporter spec --test ./test/**/*.test.ts"
"test": "node --import tsx --test ./test/**/*.test.ts"
}
}
11 changes: 9 additions & 2 deletions packages/debug-server/src/DebugServerError.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
export class DebugServerError extends Error {
constructor(message: string) {
super(message);
public readonly cmd: string;
public readonly args: string[];
public readonly output: string;

constructor(options: { cmd: string; args: string[]; output: string }) {
super(`Command "${options.cmd}" failed: ${options.output}`);
this.name = 'DebugServerError';
this.cmd = options.cmd;
this.args = options.args || [];
this.output = options.output;
}
}
67 changes: 67 additions & 0 deletions packages/debug-server/src/DebugServerExecutor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { createConnection } from 'node:net';
import type { Executor } from './Executor.js';

type DebugServerExecutorOptions = {
signal?: AbortSignal;
};

export class DebugServerExecutor
implements Executor<DebugServerExecutorOptions>
{
#hostname: string;
#port: number;
#signal?: AbortSignal | undefined;

constructor(options: {
hostname: string;
port: number;
signal?: AbortSignal;
}) {
this.#hostname = options.hostname;
this.#port = options.port;
this.#signal = options.signal;
}

async execute(
command: string,
args: string[],
config?: DebugServerExecutorOptions
): Promise<string> {
const signal =
this.#signal && config?.signal
? // @ts-ignore TS2339: Property 'any' does not exist on type 'typeof AbortSignal'.
AbortSignal.any([this.#signal, config.signal])
: this.#signal || config?.signal;

return new Promise((resolve, reject) => {
const cmd = `${command} ${args.join(' ')}`.replace(/\s/g, ' ').trimEnd();

const client = createConnection(
{ host: this.#hostname, port: this.#port, signal },
() => {
client.write(`${cmd}\nq\n`);
}
);

let chunks: Buffer[] = [];

client.on('data', (chunk) => {
chunks.push(chunk);
});

client.on('end', () => {
const response = Buffer.concat(chunks)
.toString()
.replace(/\r\n?/g, '\n');

const start = response.indexOf('\n>') + 2;
const end = response.lastIndexOf('\n>');
resolve(response.slice(start, end).trim());
});

client.on('error', (error) => {
reject(error);
});
});
}
}
19 changes: 0 additions & 19 deletions packages/debug-server/src/DebugServerParsingError.ts

This file was deleted.

3 changes: 3 additions & 0 deletions packages/debug-server/src/Executor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface Executor<Config> {
execute(command: string, args: string[], config?: Config): Promise<string>;
}
11 changes: 7 additions & 4 deletions packages/debug-server/src/commands/clearLaunchCaches.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { Executor } from '../executors/Executor.ts';
import { execute } from '../internal/execute.js';
import type { Executor } from '../Executor.js';
import { execute, type Config } from '../internal/execute.js';

const pattern = /Done/;

/**
* Clear all caches that can affect channel launch time.
*/
export async function clearLaunchCaches(executor: Executor): Promise<void> {
await execute(executor, 'clear_launch_caches', [], [pattern]);
export async function clearLaunchCaches<Context extends Executor<{}>>(
ctx: Context,
config?: Config<Context>
): Promise<void> {
await execute(ctx, 'clear_launch_caches', [], [pattern], config);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Executor } from '../Executor.js';
import { execute, type Config } from '../internal/execute.js';

const pattern = /^\s*$/;

/**
* Clear SceneGraph node operation performance metrics.
*/
export async function clearSceneGraphPerformanceMetrics<
Context extends Executor<{}>
>(ctx: Context, config?: Config<Context>): Promise<void> {
await execute(ctx, 'sgperf', ['clear'], [pattern], config);
}
18 changes: 14 additions & 4 deletions packages/debug-server/src/commands/createDeveloperKey.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Executor } from '../executors/Executor.ts';
import { execute } from '../internal/execute.js';
import type { Executor } from '../Executor.js';
import { execute, type Config } from '../internal/execute.js';
import type { DeveloperKey } from '../types/DeveloperKey.ts';

const idPattern = /DevID: (.*)/;
Expand All @@ -8,7 +8,17 @@ const passwordPattern = /Password: (.*)/;
/**
* Generate a new developer key.
*/
export async function createDeveloperKey(executor: Executor): Promise<DeveloperKey> {
const result = await execute(executor, 'genkey', [], [idPattern, passwordPattern]);
export async function createDeveloperKey<Context extends Executor<{}>>(
ctx: Context,
config?: Config<Context>
): Promise<DeveloperKey> {
const result = await execute(
ctx,
'genkey',
[],
[idPattern, passwordPattern],
config
);

return { id: result[0][0][1], password: result[1][0][1] };
}
11 changes: 7 additions & 4 deletions packages/debug-server/src/commands/disableRendezvousLogging.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { Executor } from '../executors/Executor.ts';
import { execute } from '../internal/execute.js';
import type { Executor } from '../Executor.js';
import { execute, type Config } from '../internal/execute.js';

const pattern = /rendezvous logging is off/;

/**
* Disable rendezvous logging.
*/
export async function disableRendezvousLogging(executor: Executor): Promise<void> {
await execute(executor, 'logrendezvous', ['off'], [pattern]);
export async function disableRendezvousLogging<Context extends Executor<{}>>(
ctx: Context,
config?: Config<Context>
): Promise<void> {
await execute(ctx, 'logrendezvous', ['off'], [pattern], config);
}
Loading

0 comments on commit c4524e8

Please sign in to comment.