<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Suraj Sharma</title>
    <description>The latest articles on DEV Community by Suraj Sharma (@surajsharma).</description>
    <link>https://dev.to/surajsharma</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F72222%2F76602ba7-9d83-433b-9092-d9e76a1e3581.jpeg</url>
      <title>DEV Community: Suraj Sharma</title>
      <link>https://dev.to/surajsharma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/surajsharma"/>
    <language>en</language>
    <item>
      <title>Write your own git (in typescript) - part 1</title>
      <dc:creator>Suraj Sharma</dc:creator>
      <pubDate>Sun, 15 Mar 2020 01:44:41 +0000</pubDate>
      <link>https://dev.to/surajsharma/write-your-own-git-in-typescript-part-1-3g8m</link>
      <guid>https://dev.to/surajsharma/write-your-own-git-in-typescript-part-1-3g8m</guid>
      <description>&lt;p&gt;This quote about git had me inspired:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The combination of core simplicity and powerful applications often makes thing[s] really hard to grasp, because of the mental jump required to derive the variety of applications from the &lt;strong&gt;essential simplicity of the fundamental abstraction&lt;/strong&gt; (monads, anyone?)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It comes from a &lt;a href="https://wyag.thb.lt/"&gt;tutorial&lt;/a&gt; on writing your own git in Python, and I decided to port it to TypeScript.&lt;/p&gt;

&lt;p&gt;In this and coming posts, we will go through the tutorial and complete it in 8 steps. The code, which is strongly typed to the greatest possible extent can be found &lt;a href="https://github.com/inversepolarity/Sustain"&gt;here&lt;/a&gt;. The tutorial leaves the task of upgrading the resulting app "&lt;em&gt;to a full-featured git library and CLI&lt;/em&gt;" to the reader, so we will try to take it a step further, if not all the way.&lt;/p&gt;

&lt;p&gt;Shall we dance?&lt;/p&gt;

&lt;h3&gt;
  
  
  0 - Intended Audience
&lt;/h3&gt;

&lt;p&gt;Intermediate JS/TS developers familiar with NodeJS and with at least some basic understanding of File Systems. TypeScript enthusiasts learning the language.&lt;/p&gt;

&lt;h3&gt;
  
  
  1 - Getting Started
&lt;/h3&gt;

&lt;p&gt;The idea is to make a Node.js app in TypeScript that mimics wyag. For this, we will need a CLI interface in TypeScript.&lt;/p&gt;

&lt;p&gt;I followed &lt;a href="https://itnext.io/how-to-create-your-own-typescript-cli-with-node-js-1faf7095ef89"&gt;this tutorial&lt;/a&gt; on creating a CLI with Node and am summarising the process below:&lt;/p&gt;

&lt;h4&gt;
  
  
  Init
&lt;/h4&gt;

&lt;p&gt;Do an &lt;code&gt;npm init&lt;/code&gt; in your folder and then add the following dependencies to your &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/clear"&gt;clear&lt;/a&gt; - clearing the screen, &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/figlet"&gt;figlet&lt;/a&gt; - ASCII art for Schwaaag, &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/chalk"&gt;chalk&lt;/a&gt; - terminal styling &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/commander"&gt;commander&lt;/a&gt; - for args&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/path"&gt;path&lt;/a&gt; - for working with file and directory paths&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;and the following devDependencies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/@types/node"&gt;@types/node&lt;/a&gt; - Type definitions for Node.js&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/nodemon"&gt;nodemon&lt;/a&gt; - If you don't know what this is, now is the time to stop reading this tutorial and go do something else&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/ts-node"&gt;ts-node&lt;/a&gt; - execution environment and REPL (if you have to google REPL, seriously, please go do something else)&lt;/li&gt;
&lt;li&gt;
&lt;a href=""&gt;typescript&lt;/a&gt; - ❤️&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Scripts
&lt;/h4&gt;

&lt;p&gt;The Scripts section of your &lt;code&gt;package.json&lt;/code&gt; should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
  "start": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts",
  "create": "npm run build &amp;amp;&amp;amp; npm run test",
  "build": "tsc -p .",
  "test": "sudo npm i -g &amp;amp;&amp;amp; pizza",
  "refresh": "rm -rf ./node_modules ./package-lock.json &amp;amp;&amp;amp; npm install"
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  TSconfig
&lt;/h4&gt;

&lt;p&gt;You will also need a &lt;code&gt;tsconfig.json&lt;/code&gt; file in the same folder as your &lt;code&gt;package.json&lt;/code&gt; with the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "lib": ["es6", "es2015", "dom"],
    "declaration": true,
    "outDir": "lib",
    "rootDir": "src",
    "strict": true,
    "types": ["node"],
    "esModuleInterop": true,
    "resolveJsonModule": true
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Creating the CLI
&lt;/h4&gt;

&lt;p&gt;Create a &lt;code&gt;src&lt;/code&gt; folder in the directory and a file named &lt;code&gt;index.ts&lt;/code&gt; within it. Then, start editing:&lt;/p&gt;

&lt;p&gt;We start with a normal shebang&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env node
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Clear the screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clear()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Import the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const chalk = require('chalk');
const clear = require('clear');
const figlet = require('figlet');
const path = require('path');
const program = require('commander');
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Display a banner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log(
  chalk.green(
    figlet.textSync('sustain', { font: 'slant', horizontalLayout: 'full' })
  ));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Add the commands/arguments to the CLI app that we will process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program
  .version('0.0.1')
  .description('A distributed version control system')
  .option('-i, --init', 'Init a repo')
  .option('-a, --add', 'Add file')
  .option('-c, --cat', 'Cat file')
  .option('-t, --checkout', 'Checkout')
  .option('-m, -commit', 'Commit')
  .option('-h, -hash', 'Hash Object')
  .option('-l, -log', 'Log')
  .option('-t, -ls-tree', 'Hash Object')
  .option('-h, -hash', 'Hash Object')
  .option('-g, -merge', 'Merge')
  .option('-r, -rebase', 'Rebase')
  .option('-v, -rev', 'Rev parse')
  .option('-r, -rm', 'Remove')
  .option('-s, -show', 'Show ref')
  .option('-t, -tag', 'Tag')
  .parse(process.argv);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we want to have some placeholder actions for the arguments sent by the user, we will come back here and write functions for each one of these:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (program.init) console.log(' - Initialize a repo');
if (program.add) console.log('  - Add file');
if (program.cat) console.log('  - Cat file');
if (program.checkout) console.log('  - Checkout');
if (program.commit) console.log('  - Commit');
if (program.hash) console.log('  - Hash object');
if (program.log) console.log('  - Log');
if (program.lstree) console.log(' - Show dir tree');
if (program.merge) console.log('  - Merge');
if (program.rebase) console.log('  - Rebase');
if (program.rparse) console.log('  - Rev parse');
if (program.rm) console.log(' - Remove');
if (program.show) console.log('  - Show ref');
if (program.tag) console.log('  - Tag');
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, add the following to implement the obligatory &lt;code&gt;-h&lt;/code&gt; and &lt;code&gt;--help&lt;/code&gt; argument for when the user needs help.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!process.argv.slice(2).length) {
  program.outputHelp();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now do &lt;code&gt;npm run build&lt;/code&gt; and call the program, you should see something like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uek9JMLx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://puu.sh/FkHhY/2e27e7bbe4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uek9JMLx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://puu.sh/FkHhY/2e27e7bbe4.png" alt="firstscreen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next part we will add the &lt;code&gt;SusRepository&lt;/code&gt; Class to the program, which is our basic building block. We will also add some utility functions to the code. Then we will implement the &lt;code&gt;init&lt;/code&gt; command and write a &lt;code&gt;RepoFind&lt;/code&gt; function which will recursively look for a git directory for our &lt;code&gt;init&lt;/code&gt; functionality.&lt;/p&gt;

&lt;p&gt;Original article written for my blog can be read &lt;a href="https://surajsharma.github.io/2020/03/Write-your-own-git-(in-TypeScript)-Part-1"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>git</category>
      <category>node</category>
      <category>vcs</category>
    </item>
  </channel>
</rss>
