Clients
The client implementation follows good design pattern, making the design as modular as possible.
The diagram above illustrates the main idea of how the client works. The Argparse layer is like controller or GraphQL on server side, provides an interface to interact with users. The service layer will do all the work. The Main layer (function) connects everything together.
This is just a rough overview, the real design is more complicated and involves more components (mainly in the service layer).
Sample Code
match &args.command {
XCCommands::Register { email, password } => {
ctx.cmd_name = CommandName::Register;
let register_args = RegisterParser::parse(email, password);
let register_service = RegisterService { args: register_args };
register_service.run(&ctx);
}
XCCommands::Login { email, password } => {
ctx.cmd_name = CommandName::Login;
let login_args = LoginParser::parse(email, password);
let login_service = LoginService { args: login_args };
login_service.run(&ctx);
}
}
Hooks
Hooks is another component of client. Refer to Oclif Hooks.
Lifecycle hooks are some functions that will be on some event. For example, oclif lifecycle events has init hook that runs when CLI starts, and command_not_found hook that runs when command is not found.
For example we can have a init hook for auto update, which checks for latest version CLI after each run, and verify that the current CLI version has the same API version as the server. If the API version doesn't match, it may result in unexpected errors between the client and the server.
For now, we will have the same lifecycle hooks as Oclif:
initprerunpostruncommand_not_found
Plugin Design
Most of the logic happens in the Service layer. We will be using a plugin design in services that involve data IO (e.g. Clipboard).