A first try of typescript and deno 2

taijidude - Nov 2 - - Dev Community

After joining a new company I get to work with angular and typescript. To get more familiar with typescript I'm trying to use it as much as possible. I recently started with a small cli app for my git workflow. (I'm fully aware that this can be done in bash... 😉).

The problem...

When working with git I tend to use the git bash on windows. I switch branches often and would like to quickly go back to the branch I have been previously working on.

Example:
The first thing I want my solution to do is to show me the branch I previously worked on. This information should be updated, if I switch branches.

my_computer MINGW64 /c/Dev/temp/blogarticle (test1)
$ gst #Shows the previous branch name along with the output of git status  
previous branch: main ❗
On branch test1
nothing to commit, working tree clean

my_computer MINGW64 /c/Dev/temp/blogarticle (test1)
$ gch main # checks out the branch with the name main
Switched to branch 'main'

my_computer MINGW64 /c/Dev/temp/blogarticle (main)
$ gst
previous branch: test1 ❗
On branch main
nothing to commit, working tree clean
Enter fullscreen mode Exit fullscreen mode

Additionally, I want to be able to switch back to the previous branch. Like this...

my_computer MINGW64 /c/Dev/temp/blogarticle (main)
$ gst
previous branch: test1
On branch main
nothing to commit, working tree clean

my_computer MINGW64 /c/Dev/temp/blogarticle (main)
$ gchl ❗
Switched to branch 'test1'

my_computer MINGW64 /c/Dev/temp/blogarticle (test1)
$ gst
previous branch: main
On branch test1
nothing to commit, working tree clean
Enter fullscreen mode Exit fullscreen mode

The solution...

Deno intrigued me for a long time, so I picked it for this first try. Why?

  • It can compile your code into native executables.
  • It comes with a key-value store functionality.
  • with version 2 you are now able to use npm libraries. I've used commander js to implement the command line functionality. Installing a npm library into your project looks like this:
deno install npm:commander
Enter fullscreen mode Exit fullscreen mode

The code...

import {program} from "commander";

const dbPath:string = "C:\\Dev\\projects\\rememberGitBranch\\db.sqlite3";
const branchKey:string = "previousBranch"

export async function save(branch: string) {
  const kv = await Deno.openKv(dbPath);
  kv.set([branchKey], branch);
  kv.close();
}

export async function load(): Promise<string> {
  const kv = await Deno.openKv(dbPath);
  const lastBranch = (await kv.get([branchKey])).value
  kv.close();
  return lastBranch as string;
}

program
  .command('save')
  .description('save the name of the branch you worked with last')
  .requiredOption('-b, --branch <branch>', 'The branch to work with')
  .action(options => {
    save(options.branch);
  });

program
  .command('load')
  .description('loads the last branch name saved with the save command')  
  .action(() =>  {
    load().then(value => console.log(value));
  });

program.parse();
Enter fullscreen mode Exit fullscreen mode

Lets have a look at the output of the help function.

my_computer MINGW64 /c/Dev/projects/rememberGitBranch
$ ./rememberGitBranch.exe --help
Usage: main [options] [command]

Options:
  -h, --help    display help for command

Commands:
  save [options]  save the name of the branch you worked with last   
  load          loads the last branch name saved with the save command
  help [command]  display help for command
Enter fullscreen mode Exit fullscreen mode

As we can see, the app can be run with three commands, with one beeing the help function.

save: the save command takes a string parameter and runs the save function in the main.ts file. This function calls key-value Store stores it with a key named lastBranch. When opening the connection to the kv store i give it the path of the database file. Normally i would not have to do this, but because the deno runtime has a default storage file. But when you compile your code into an executable it doesn't know about the default file. So you have to explicitly give it a path.
If the file doesn't exists it will get created.

The output for the help call about the save command:

$ ./rememberGitBranch.exe save --help
Usage: main save [options]

save the name of the branch you worked with last

Options:
  -b, --branch <branch>  The branch to work with
  -h, --help            display help for command
Enter fullscreen mode Exit fullscreen mode

load: this commands executes the load function in the main.ts file. This function opens a connection to the kv store and queries it with the key "previousBranch". The function return the result of the query as string. This string gets printed.

The output for the help call about the load command:

$ ./rememberGitBranch.exe load --help
Usage: main load [options]

loads the last branch name saved with the save command

Options:
  -h, --help  display help for command

Enter fullscreen mode Exit fullscreen mode

Compiling the executable

deno compile --allow-write --allow-read --unstable-kv main.ts
Enter fullscreen mode Exit fullscreen mode

The result is a shiny new exe file in my project directory:

my_computer MINGW64 /c/Dev/projects_patrick/rememberGitBranch
$ ls
db.sqlite3  deno.json  deno.lock  main.ts  main_test.ts  rememberGitBranch.exe*
Enter fullscreen mode Exit fullscreen mode

Putting everything together...

Here you see some parts of my .bashrc file which uses the new cli app. This allows me to do the things i have shown in the problem section.

alias gst='echo "previous branch:" $(rememberGitBranch.exe load) && git status'
alias gch='rememberGitBranch.exe save -b "$(git branch --show-current)"&&git checkout'
function gchl {
    currentBranch=$(git branch --show-current) &&
    git checkout "$(rememberGitBranch.exe load)"
    rememberGitBranch.exe save -b "$currentBranch"
}
Enter fullscreen mode Exit fullscreen mode

Take Aways

I had fun trying this out and after a short amount of time had something in my hand that i will use in my day to day workflow. I think it's a nice way to learn about the language and most of the frameworks on a frequent basis. I have some more ideas for some cli apps and for some webapps but i need to get a little further in the udemy angular course i'm doing to work on those.

Thank you for reading! Would you have done anything different? Is there something to make the code more idiomatic?

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player