Skip to content

Commit 31e6b91

Browse files
authored
Merge pull request #10 from capsulerun/feature/v0.1.0/custom-commands
feat: add support for custom command registration and execution
2 parents b94ea34 + 823eaec commit 31e6b91

7 files changed

Lines changed: 52 additions & 15 deletions

File tree

packages/bash-types/src/bash.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { CommandHandler, CustomCommand } from "./command";
12
import type { BaseRuntime } from "./runtime";
23

34
export interface BashOptions {
@@ -6,6 +7,11 @@ export interface BashOptions {
67
*/
78
runtime: BaseRuntime;
89

10+
/**
11+
* Array with custom commands added at runtime
12+
*/
13+
customCommands?: CustomCommand[];
14+
915
/**
1016
* The host workspace directory
1117
*/

packages/bash-types/src/command.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,26 @@ import { State } from "./state";
44
/**
55
* The context of a command execution
66
*/
7-
export type CommandContext = {
7+
export interface CommandContext {
88
opts: CommandOptions;
99
stdin: string;
1010
state: State;
1111
runtime: BaseRuntime;
1212
};
1313

14-
/**
15-
* The handler of a command execution
16-
*/
17-
export type CommandHandler = (ctx: CommandContext) => Promise<CommandResult>;
18-
1914
/**
2015
* The result of a command execution
2116
*/
22-
export type CommandResult = {
17+
export interface CommandResult {
2318
stdout: string;
2419
stderr: string;
2520
exitCode: number;
2621
};
2722

28-
2923
/**
3024
* The options of a command execution
3125
*/
32-
export type CommandOptions = {
26+
export interface CommandOptions {
3327
raw: string[];
3428
flags: Set<string>;
3529
options: Map<string, string>;
@@ -40,10 +34,32 @@ export type CommandOptions = {
4034
/**
4135
* The manual of a command
4236
*/
43-
export type CommandManual = {
37+
export interface CommandManual {
4438
name: string;
4539
description: string;
4640
usage: string;
4741
options?: Record<string, string>;
4842
};
4943

44+
/**
45+
* The custom command creation result
46+
*/
47+
export interface CustomCommand {
48+
name: string;
49+
handler: CommandHandler;
50+
manual?: CommandManual;
51+
}
52+
53+
/**
54+
* The handler of a command execution
55+
*/
56+
export type CommandHandler = (ctx: CommandContext) => Promise<CommandResult>;
57+
58+
59+
/**
60+
* The builder to create a custom command
61+
*/
62+
export type CreateCustomCommand = (name: string, handler: CommandHandler, manual?: CommandManual) => CustomCommand;
63+
64+
65+

packages/bash-types/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export { State } from "./state";
22
export { BaseRuntime, RuntimeResult } from "./runtime";
33
export { BashOptions } from "./bash";
4-
export { CommandResult, CommandHandler, CommandContext, CommandOptions, CommandManual } from "./command";
4+
export { CommandResult, CommandHandler, CommandContext, CommandOptions, CommandManual, CustomCommand, CreateCustomCommand } from "./command";

packages/bash/src/core/bash.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { BaseRuntime, BashOptions, CommandResult } from "@capsule-run/bash-types";
1+
import type { BaseRuntime, BashOptions, CommandHandler, CommandResult, CustomCommand } from "@capsule-run/bash-types";
22
import { StateManager } from "./stateManager";
33
import { Filesystem } from "./filesystem";
44
import { Parser } from "./parser";
@@ -9,16 +9,19 @@ export class Bash {
99
private filesystem: Filesystem;
1010
private parser: Parser;
1111
private executor: Executor;
12+
private customCommands: CustomCommand[];
1213

1314
public readonly stateManager: StateManager;
1415

15-
constructor({ runtime, hostWorkspace = ".capsule/session/workspace", initialCwd = "workspace" }: BashOptions) {
16+
constructor({ runtime, customCommands = [], hostWorkspace = ".capsule/session/workspace", initialCwd = "workspace" }: BashOptions) {
1617
this.runtime = runtime;
1718
this.runtime.hostWorkspace = hostWorkspace;
19+
this.customCommands = customCommands;
20+
1821
this.stateManager = new StateManager(runtime, initialCwd);
1922
this.filesystem = new Filesystem(hostWorkspace);
2023
this.parser = new Parser();
21-
this.executor = new Executor(runtime, this.stateManager.state);
24+
this.executor = new Executor(runtime, this.customCommands, this.stateManager.state);
2225

2326
this.filesystem.init();
2427
}

packages/bash/src/core/executor.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import path from 'path';
22
import { parsedCommandOptions } from '../helpers/commandOptions';
33
import { displayCommandManual } from '../helpers/commandManual';
44

5-
import type { BaseRuntime, CommandHandler, CommandManual, CommandResult, State } from '@capsule-run/bash-types';
5+
import type { BaseRuntime, CommandHandler, CommandManual, CommandResult, CustomCommand, State } from '@capsule-run/bash-types';
66
import type { ASTNode, CommandNode } from './parser';
77

88

99
export class Executor {
1010

1111
constructor(
1212
private readonly runtime: BaseRuntime,
13+
private readonly customCommands: CustomCommand[],
1314
private readonly state: State,
1415
) {}
1516

@@ -138,6 +139,11 @@ export class Executor {
138139
const commandsDir = path.resolve(__dirname, '../commands');
139140
const handlerPath = path.join(commandsDir, name, 'handler');
140141

142+
const customCommand = this.customCommands.find(cmd => cmd.name === name);
143+
if (customCommand) {
144+
return { handler: customCommand.handler, manual: customCommand.manual };
145+
}
146+
141147
try {
142148
const mod = require(handlerPath);
143149
return { handler: mod.handler as CommandHandler, manual: mod.manual as CommandManual };

packages/bash/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export { Bash } from "./core/bash";
2+
export { createCommand } from "./utilities/createCommand";
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { CreateCustomCommand } from "@capsule-run/bash-types";
2+
3+
export const createCommand: CreateCustomCommand = (name, handler, manual) => {
4+
return { name, handler, manual };
5+
}

0 commit comments

Comments
 (0)