<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[prince-curie]]></title><description><![CDATA[prince-curie]]></description><link>https://princecurie.tech</link><generator>RSS for Node</generator><lastBuildDate>Thu, 16 Apr 2026 05:15:57 GMT</lastBuildDate><atom:link href="https://princecurie.tech/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Software Design Document]]></title><description><![CDATA[Several times, I have been involved in starting a project/feature and realising that there exist issues that are yet to be discussed, either with external teams, other departments, or the relations team of a third-party provider. This has made me spe...]]></description><link>https://princecurie.tech/the-software-design-document</link><guid isPermaLink="true">https://princecurie.tech/the-software-design-document</guid><category><![CDATA[software design]]></category><category><![CDATA[software design document]]></category><category><![CDATA[design document]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Tue, 25 Jul 2023 20:29:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/GnvurwJsKaY/upload/5945a5f1693869f4fe520944342bc754.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Several times, I have been involved in starting a project/feature and realising that there exist issues that are yet to be discussed, either with external teams, other departments, or the relations team of a third-party provider. This has made me spend more time than necessary building. In search of a solution to ensure such tragedies do not befall me again or the occurrence is reduced, I came in contact with Software Design Document (SDD). This is a document that ensures that you ask all the necessary questions needed, clear all doubts you have, and get reasonable feedback before you proceed to write a single line of production code.</p>
<p>This article discusses what an SDD is, why some engineers do not want it and while other engineers embrace it, tips on writing an SDD, some necessary components of a design doc, and how to measure if the documentation process was a waste of time.</p>
<h3 id="heading-what-is-a-software-design-document">What is a Software Design Document?</h3>
<p>An SDD provides a detailed description of your software design. It functions as a reference for software engineers to build. It contains assumptions, dependencies relating to the software and its uses, general constraints, goals, guidelines, and all development methods involved in developing the software.</p>
<h3 id="heading-arguments-against-sdd">Arguments against SDD</h3>
<ul>
<li>Humans not wanting to write: Writing documents can be tiresome. Some engineers have formed the habit of documenting after building since building is where the fun is. Sometimes you are staring at the screen not knowing where to start or how to continue. </li>
<li>Pace of software growth: This is similar to the argument that people have against writing comments, it is argued that the code is likely to move and change so fast that the comment becomes obsolete since the engineer might not remember to update it. Now compare this to a doc separate from your code. The likelihood of keeping up might be lower. Assuming this becomes true, then the developers who built a whole multi-page document might feel like they had wasted time putting it all together and the developers who are new to the system might not be able to trust what the SDD says again. </li>
<li>Management pressure: Others complain that the pressure from management reduces the chances of dedicating time to putting together a whole document.</li>
</ul>
<h3 id="heading-arguments-for-sdd">Arguments for SDD</h3>
<ul>
<li>Timeline Calculation: Knowing exactly what to do and how you plan to do it, makes it easier to calculate how long it will take for it to be done with ease and better accuracy. </li>
<li>Meet Stakeholders Criteria: It becomes easier to know exactly what the stakeholders are looking out for since you think about the task thoroughly before building, asking questions for clarity, sharing the documents with all stakeholders, and getting feedback. This makes it easier to build systems that meet the stakeholder's criteria. </li>
<li>Point of Reference: The document serves as a point of reference whenever you are unsure how to proceed or have others mentioning new issues with claims that it was discussed before you started building the project. </li>
<li>Easier to onboard new Engineers to the Project: The document ensures that any engineer joining the team can easily pick up the project since the SDD is easy to read and comprehend and covers all aspects of the project. </li>
<li>Decision making: It ensures that all design decisions are made and the ones not made are noted.</li>
</ul>
<h3 id="heading-tips-for-writing-an-sdd">Tips for Writing an SDD</h3>
<ul>
<li>Keep it simple: Make it so simple that even a five-year-old reading the doc will have no other option than to understand what you have written. Okay, that may be over the top, but you get the point. </li>
<li>Use of Images: Where necessary, throw in something pictorial to drive home the point. It might be a chart, diagram, or graph. Also, provide a link to the editable copy. </li>
<li>Jokes: Just like salt to a meal, ensures that the meal does not taste bland. Adding safe-for-work jokes to your doc will spice it up a little and make it not a boring read. But like salt to a meal, adding too much might distract from the purpose. </li>
<li>Preempt: Preempting possible scenarios, and questions your reviewers may throw at you will help you go through it and get fully prepared before presenting it to your reviewer.</li>
</ul>
<h3 id="heading-deciding-if-the-sdd-is-a-success">Deciding if the SDD is a Success</h3>
<p>It is either you finish the task on time, with it meeting stakeholders' requirements and running properly, or you find an issue that needs solving before you complete the project. You then look to ensure it is not a dead end and if it is a dead end, you may decide to leave the project or find a better solution.</p>
<h3 id="heading-components-of-a-design-doc">Components of a Design Doc</h3>
<ul>
<li>Title and People: This section contains the document’s title, authors, reviewers, the date the document was last updated, and everyone who will work on the project alongside you. </li>
<li>Summary: This section contains an easy-to-grasp top-level summary every engineer should read to decide if they are meant to go on reading the document. </li>
<li>Background: In this section, we discuss what the problem we are trying to solve is, why a solution is necessary, how the solution can be accessed, and how the solution fits into the goals and strategy of the team. </li>
<li>Goals: This section looks at how success will be measured and the tools to measure it. It also looks at how it affects the end user, especially in scenarios where you have direct access to them. Either the direct users are humans or other systems. </li>
<li>Milestones: Your document should contain a clear high-level list of important activities when they are expected to be accomplished, and who is responsible for accomplishing them. </li>
<li>Solutions: Here, we look into the existing solutions (if any) and how the solution is being used. Then we look into the new solutions, the technical diagrams, architecture, and system designs as well as the user stories to explain them all. </li>
<li>Discussion: All unanswered questions are presented so that the reader can weigh in their opinions (if any).</li>
</ul>
<h3 id="heading-conclusion">Conclusion</h3>
<p>I believe having a doc like this will solve the problems I faced, mentioned at the beginning. I have started using one for my team and me. Though it does not include all the components mentioned since they are small tasks expected to run in a sprint or two. But having a document similar to this has been of immense blessing in helping us solve a lot of issues before building. If you are not in favour of the SDD, it is understandable. We all will not like everything ☺️.</p>
<p>If you made it this far, thanks for reading!</p>
]]></content:encoded></item><item><title><![CDATA[Understanding SOLID Principles]]></title><description><![CDATA[The SOLID principles are a set of five principles, amongst others, guiding how software is designed to be less fragile, less rigid, more testable, maintainable, and readable. It influences how we write code in such a way that future changes do not th...]]></description><link>https://princecurie.tech/understanding-solid-principles</link><guid isPermaLink="true">https://princecurie.tech/understanding-solid-principles</guid><category><![CDATA[SOLID principles]]></category><category><![CDATA[oop]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[OOP Design Principles]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Sun, 29 Jan 2023 06:17:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674973057925/75446706-5b56-4715-bc50-fdad566e1d32.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The SOLID principles are a set of five principles, amongst others, guiding how software is designed to be less fragile, less rigid, more testable, maintainable, and readable. It influences how we write code in such a way that future changes do not threaten the stability of existing software.</p>
<p>The five principles are:</p>
<ul>
<li><p>Single Responsibility Principle.</p>
</li>
<li><p>Open Closed Principle.</p>
</li>
<li><p>Liskov Substitution Principle.</p>
</li>
<li><p>Interface Segregation Principle.</p>
</li>
<li><p>Dependency Inversion Principle.</p>
</li>
</ul>
<p>This article explains each of the solid principles with examples in TypeScript. Even if you do not understand TypeScript, the article is written to be simple and easy to understand, like codebases written following these principles.</p>
<h3 id="heading-prerequisites"><strong>Prerequisites</strong></h3>
<p>This article assumes you have basic knowledge of TypeScript and object-oriented programming. As the examples are all classes written in TypeScript.</p>
<h3 id="heading-single-responsibility-principle"><strong>Single Responsibility Principle</strong></h3>
<p>The principle states that a class should have only one reason to change. In order to achieve that, a class should only do one thing alone. This makes a class smaller and less fragile. It also ensures that people can work on various parts of the codebase without having a merge conflict</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> User {
    create() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User created'</span>)
    }

    index() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Users returned'</span>)
    }

    fetch() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User returned'</span>)
    }

    sendNotification() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Notification sent'</span>)
    }

    login() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Login successful'</span>)
    }

    logout() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Logout successful'</span>)
    }
}
</code></pre>
<p>Looking at the example above, we can see that the Single Responsibility Principle is not being obeyed. This class handles other issues, such as authentication and notification. So to follow the principle, we will move the <code>sendNotification</code> method to a different class where everything pertaining to notifications is being handled and move the login and logout method to an authentication class where login and logout will be taken care of.</p>
<h3 id="heading-open-closed-principle"><strong>Open-Closed Principle</strong></h3>
<p>This principle states that a class should only be opened for extension and closed for modification. This principle ensures that:</p>
<ul>
<li><p>Existing classes do not have new bugs introduced to them.</p>
</li>
<li><p>New additions are tested in isolation.</p>
</li>
<li><p>The single responsibility principle is not broken.</p>
</li>
</ul>
<p>This means that we should only be able to add new functionality to a class and not edit existing code. Looking at the example from the Single Responsibility Principle, let's assume the business tells us we have new users all the way from the planet Mars and more coming from other planets later. Our business has decided to have them sign up. We do not need to edit the create method to have them come in, instead, we can make the user class abstract, the create method abstract, and create a new class for Martians with a create method to overwrite the existing create method on the user class. While also having access to the initial methods on the User class.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">class</span> User {
    <span class="hljs-keyword">abstract</span> create(): <span class="hljs-built_in">void</span>

    index() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Users returned'</span>)
    }

    fetch() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User returned'</span>)
    }
}

<span class="hljs-keyword">class</span> Earthlings {
    create() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User created'</span>)
    }
}

<span class="hljs-keyword">class</span> Martian <span class="hljs-keyword">extends</span> User {
    create() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User created'</span>)
    }
}
</code></pre>
<p>From the example above, we moved the existing implementation of the create function to New Classes. So while the user class contains methods solely for all users, the Martian class will also contain methods and properties for users from mars.</p>
<h3 id="heading-interface-segregation-principle"><strong>Interface Segregation Principle</strong></h3>
<p>This principle is all about having separate interfaces. If a class does not implement a property or function in an interface, then it has no dealings with that interface in the first place.</p>
<p>So going back to our Authentication class we mentioned earlier. Our interface for it will look like</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">interface</span> Auth {
    login(): <span class="hljs-built_in">void</span>;

    logout(): <span class="hljs-built_in">void</span>;
}

<span class="hljs-keyword">class</span> Authentication <span class="hljs-keyword">implements</span> Auth{
    login() {

    }

    logout() {

    }
}
</code></pre>
<h3 id="heading-liskov-substitution-principle"><strong>Liskov Substitution Principle</strong></h3>
<p>A superclass can be swapped with a subclass, and the method using the class will not notice the change. Using the principle if such a swap happens, nothing should break, and the system should perform as if no change happened. This means that if we are to override an existing method, the new implementation should exhibit similar behaviour to the existing method in the base class. For example,</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674970345722/dca66bcc-bba9-463a-a3ec-329a82d3f152.jpeg" alt class="image--center mx-auto" /></p>
<p>Looking at the image, we realise that the plastic duck cannot be substituted for a live duck.</p>
<p>Another example will be</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Animal {
    walk() {}

    speak() {}

    eat() {}
}

<span class="hljs-keyword">class</span> Lion <span class="hljs-keyword">extends</span> Animal {}

<span class="hljs-keyword">class</span> snake <span class="hljs-keyword">extends</span> Animal {}
</code></pre>
<p>From our example, we realised that this is a bad example since a snake cannot walk but crawl. So let’s have an example that adheres to this principle</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Animal {
    speak() {}

    eat() {}
}

<span class="hljs-keyword">class</span> WalkingAnimal <span class="hljs-keyword">extends</span> Animal {
    walk() {}
}

<span class="hljs-keyword">class</span> CrawlingAnimal <span class="hljs-keyword">extends</span> Animal {
    crawl() {}
}

<span class="hljs-keyword">class</span> Lion <span class="hljs-keyword">extends</span> WalkingAnimal {}

<span class="hljs-keyword">class</span> Snake <span class="hljs-keyword">extends</span> CrawlingAnimal {}
</code></pre>
<p>From this last example, we can see that, Lion can be substituted with Animal or WalkingAnimal class, and it will function well.</p>
<h3 id="heading-dependency-inversion-principle"><strong>Dependency Inversion Principle</strong></h3>
<p>Looking at our earlier examples. Let's assume the Auth class needs to send a notification whenever a user logs in. Our auth class will look like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Authentication {
    login() {
        <span class="hljs-keyword">const</span> alert = <span class="hljs-keyword">new</span> Alert();
        alert.send()

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User logged in'</span>)
    }

    logout() {

    }
}

<span class="hljs-keyword">class</span> Alert {
    send() {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Notification sent'</span>)
    }
}
</code></pre>
<p>The issue with this first is that the open and closed principle can easily be broken once we decide to switch our notification class, while already breaking the Dependency Inversion Principle.</p>
<p>So what is the Dependency Inversion Principle? The principle states that:</p>
<ul>
<li><p>A high-level class should not depend on a low-level class.</p>
</li>
<li><p>A high-level class and a low-level class should depend on an abstraction.</p>
</li>
<li><p>An abstraction should not depend on any class implementation.</p>
</li>
</ul>
<p>From the example, we can see that our high-level class is the authentication class while the low-level class is the Alert class.</p>
<p>So what is an abstraction? To illustrate, you own a car but cannot describe how the car ignition comes on in full detail. But the car manufacturers decided a long time ago that such knowledge should not be a burden to you. So they provide you with a simple interface such as a point where you insert a key and turn the key or a button. From our illustration, we can say that abstraction is simply the act of separating the content of a class from its implementation.</p>
<p>The example below shows how Dependency Inversion can be achieved.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Authentication {
    login(alert: IAlert) {
        alert.send()

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User logged in'</span>)
    }

    logout() {

    }
}

<span class="hljs-keyword">interface</span> IAlert {
    send() :<span class="hljs-built_in">void</span>
}

<span class="hljs-keyword">class</span> Alert <span class="hljs-keyword">implements</span> IAlert {
    send(): <span class="hljs-built_in">void</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Notification sent'</span>)
    }
}

<span class="hljs-keyword">const</span> auth = <span class="hljs-keyword">new</span> Authentication()
auth.login(<span class="hljs-keyword">new</span> Alert())
</code></pre>
<p>Looking at the example we can see that both the Authentication and the Alert class depend on the IAlert interface. Also, this method makes the code less rigid. Let’s assume that for some reason management decides to introduce sending alerts using SMS instead of emails. And a new class is created. All it needs to do is implement the IAlert interface and be passed as an argument in the login method and we are good to go.</p>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>If you have made it to this point, thanks so much and I hope this article was informative.</p>
<p>We have covered the five SOLID principles with practical examples of how they can be applied. I hope you get to apply it as much as possible to make your code less fragile, rigid, and more testable, understandable, and maintainable. Thanks.</p>
]]></content:encoded></item><item><title><![CDATA[How GraphQL Works]]></title><description><![CDATA[GraphQL is a query language and a runtime. As a query language, unlike SQL(Structured Query Language), it never interacts with a database. It speaks with the API directly about what it needs and a server-side program that runs your queries using the ...]]></description><link>https://princecurie.tech/how-graphql-works</link><guid isPermaLink="true">https://princecurie.tech/how-graphql-works</guid><category><![CDATA[GraphQL]]></category><category><![CDATA[graphql-schema]]></category><category><![CDATA[graphql-query]]></category><category><![CDATA[graphql-mutation]]></category><category><![CDATA[how graphql works]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Thu, 26 Jan 2023 23:01:27 GMT</pubDate><content:encoded><![CDATA[<p>GraphQL is a query language and a runtime. As a query language, unlike SQL(Structured Query Language), it never interacts with a database. It speaks with the API directly about what it needs and a server-side program that runs your queries using the type of system you create for your data. This article explains what graphQL is, the different parts that make it work, and how these components interact.</p>
<p>If you find this topic and what will be discussed interesting, I am inviting you to grab a seat or anywhere comfortable to recline while reading. That is all you will be needing.</p>
<h3 id="heading-graphql-basic-concepts">GraphQL Basic Concepts</h3>
<ul>
<li><p><strong>Object Type</strong>: It is found in a graphQL schema. It is an important part of the schema that defines the object returns from the graphQL service and the object's field.</p>
<pre><code class="lang-plaintext">  type User {
      id: ID!
      name: String!
      age: Int!
      isHomeless: Boolean
      occupation: String
  }
</code></pre>
<p>  In the example above, the User object type has fields such as name and age. The words after the colon refer to the type of data the field will return. The fields with the exclamation mark at the end of the datatype are not nullable. Being not nullable means that the fields will always return with their corresponding value, at no time will the field be returned empty. Object types are used when returning a collection of values like the user's data and not a single value. The fields in the example above are all scalar types. To explain what a scalar type is, follow <a target="_blank" href="https://graphql.org/learn/schema/#scalar-types">this link</a>.</p>
</li>
<li><p><strong>Input type</strong>:  They are similar to the object type but are used to pass in an object for creation. They use the keyword input instead of type. The fields in the input type can also be defined as an argument on the mutation method as an input type.</p>
<pre><code class="lang-plaintext">  input UserInput {
      name: String!
      age: Int!
      isHomeless: Boolean
      occupation: String
  }
</code></pre>
</li>
<li><p><strong>Query</strong>: GraphQL query is similar to the GET HTTP request. It is used by the client to read data from the graphQL server.</p>
<pre><code class="lang-plaintext">  type Query {
    getUser(id: ID): User
  }
</code></pre>
<p>  Queries may have arguments. The example above will return a single user data based on its id. It is an example of a query type found in the schema. The request from the client side will look like this:</p>
<pre><code class="lang-plaintext">  {
     getUser{
        id
        name
        age
     }
  }
</code></pre>
<p>  The getUser part of the query on the client side is known as the root field, while the rest in the bracket is the requested payload. If we need more data, we need to update the payload section with more data as specified by the schema.</p>
</li>
<li><p><strong>Mutation</strong>: GraphQL mutation enables a user to create new data or manipulate existing data.</p>
<pre><code class="lang-plaintext">  type Mutation {
    createUser(input: UserInput): User
  }
</code></pre>
<p>  On the client end, the request for mutation is similar to that of the query but comes with a mutation keyword, as seen below. Also, the arguments attached to it are necessary to either create or manipulate existing data</p>
<pre><code class="lang-plaintext">  mutation {
      createUser({name: "prince", age: 20})
  }
</code></pre>
<p>  If two or more query requests are sent in at a time. They will all return at the same time. But in case of multiple mutation requests at a time, it returns one after the order in the same they were sent in.</p>
</li>
<li><p><strong>Schema</strong>: Schemas are created using the GraphQL Schema Definition Language (SDL). This serves as a form of contract between the server and the client. It is similar to a menu at a restaurant. The menu tells you what the restaurant has available, and the customer is expected to order what is on the menu. So the schema tells the client what the server has to offer.</p>
<pre><code class="lang-plaintext">  type User {
      id: ID!
      name: String!
      age: Int!
      isHomeless: Boolean
      occupation: String
  }

  input UserInput {
      name: String!
      age: Int!
      isHomeless: Boolean
      occupation: String
  }

  type Query {
    getUser(id: ID): User
  }

  type Mutation {
    createUser(input: UserInput): User
  }
</code></pre>
</li>
<li><p><strong>Resolver</strong>: A resolver is a function that interacts with other backend components, e.g. database, REST API, etc., to return the necessary response for a graphQL query. Resolvers optionally accept four positional arguments, which are root, args, context value, and info.</p>
<ul>
<li><p>root: This returns the results from the previous resolver in the resolver chain.</p>
</li>
<li><p>args: This is an object containing arguments passed by the query.</p>
</li>
<li><p>context: This is an object shared by all resolvers in a particular query.</p>
</li>
<li><p>info: This contains information about the execution state of the query.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-how-does-graphql-execute-its-queries">How Does GraphQL Execute its Queries</h3>
<p>Whether it's a mutation or a query, graphQL executes its queries following three(3) processes</p>
<ul>
<li><p>Parse</p>
</li>
<li><p>Validate</p>
</li>
<li><p>Execution</p>
</li>
</ul>
<p><strong>Parse</strong>: The incoming request comes in as a string. This string is broken into meaningful substrings and parsed into an Abstract Syntax Tree (AST). The AST is based on GraphQL specifications found <a target="_blank" href="https://spec.graphql.org/October2021/#sec-Language.Lexical-Analysis-Syntactic-Parse">here</a>. If an error exists, the server stops at this point and returns the error.</p>
<p><strong>Validate</strong>: Once the parsing is done, the schema and the parsed request are sent in for validation. They are validated against some specific sets of rules. A detailed description of such rules is found <a target="_blank" href="https://spec.graphql.org/October2021/#sec-Validation">here</a>. It is important to note that if a request has been validated before, then this step might be skipped, and we move to the execution phase. If any error is found, the server stops, and the error message is returned.</p>
<p><strong>Execution:</strong> This is the last phase, where validation occurs again. Once validation is passed, the appropriate resolver function is applied to each field. This is done recursively until all fields return a value. If a resolver function returns a promise, the execution is paused until the promise is fulfilled. The value in each field is converted to the agreed data type in the schema.</p>
<p>When all this is done, the response is packaged in a structure that is similar to the original query and is sent out typically in a JSON format.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>If you have made it here, thanks. This article has tried to explain basic concepts that make graphQL work, also it has also explained how graphQL queries are executed. Finally, if you need to read in detail about how all these work, you can check out the graphQL specification document <a target="_blank" href="https://spec.graphql.org/">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Installing Bun on Windows 10]]></title><description><![CDATA[I recently installed Bun on my windows system. This article is a step-by-step guide on the process involved in doing so. It also includes the challenges I went through to ensure a successful installation.
I will assume you have wsl on your local mach...]]></description><link>https://princecurie.tech/installing-bun-on-windows-10</link><guid isPermaLink="true">https://princecurie.tech/installing-bun-on-windows-10</guid><category><![CDATA[Bun]]></category><category><![CDATA[Windows]]></category><category><![CDATA[Windows 10]]></category><category><![CDATA[WSL]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Tue, 12 Jul 2022 11:32:36 GMT</pubDate><content:encoded><![CDATA[<p>I recently installed Bun on my windows system. This article is a step-by-step guide on the process involved in doing so. It also includes the challenges I went through to ensure a successful installation.
I will assume you have wsl on your local machine and the wsl is running Ubuntu operating system.</p>
<h3 id="heading-step-one">Step one</h3>
<ul>
<li>Start up Powershell in administrative mode.</li>
</ul>
<h3 id="heading-step-two">Step two</h3>
<ul>
<li>Update wsl: This is done by running the command <code>wsl --update</code> in the Powershell terminal. It is important to note that this step is not necessary if your system automatically downloads and installs all updates.</li>
</ul>
<h3 id="heading-step-three">Step three</h3>
<ul>
<li>Shutdown wsl: This is done in the Powershell terminal by running the command <code>wsl --shutdown</code>. It is only necessary if you carried out step one.</li>
</ul>
<p>The rest of the steps will be carried out on wsl. So start wsl.</p>
<h3 id="heading-step-four">Step four</h3>
<ul>
<li>Install unzip: The unzip package is needed to decompress the incoming files and folders. If you have it already you can skip this step. Else run <code>sudo apt install unzip</code>.</li>
</ul>
<h3 id="heading-step-five">Step five</h3>
<ul>
<li>Install Bun: Now to the main task. Run <code>curl https://bun.sh/install | bash</code>.</li>
</ul>
<h3 id="heading-step-six">Step six</h3>
<ul>
<li>Set path: When Bun is done downloading. A message will appear on the console showing us the commands needed to set the path. Run these commands to set the path.</li>
</ul>
<p>If you are still here, cool. We have installed Bun. Now we can try to install packages and start a project or create and run an HTTP server or run the <code>bun --help</code> command to view the help menu.</p>
<p>Lastly, one thing I noticed was how I needed to repeat steps five and six anytime I started wsl. It always returned a <code>Command not found error message</code>.   </p>
]]></content:encoded></item><item><title><![CDATA[Web2 vs Web3]]></title><description><![CDATA[Disclaimer: This write-up is not written to tell you which is better or which will come out victorious. Instead, the writer seeks to help you understand what they are and the inherent differences between the two of them.
The internet today is at an a...]]></description><link>https://princecurie.tech/web2-vs-web3</link><guid isPermaLink="true">https://princecurie.tech/web2-vs-web3</guid><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[web]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Wed, 02 Mar 2022 20:38:10 GMT</pubDate><content:encoded><![CDATA[<p>Disclaimer: This write-up is not written to tell you which is better or which will come out victorious. Instead, the writer seeks to help you understand what they are and the inherent differences between the two of them.</p>
<p>The internet today is at an age where products are created to be free to use, this product belongs to a specific organization that has control over it. The user interface is beautiful ensuring that the users have a nice experience and are willing to return from time to time. Data are stored on central servers and the products are also placed on central servers Companies like Meta with products like <a target="_blank" href="https://www.facebook.com">Facebook</a> fall into this category. This is referred to as web2.</p>
<p>The internet is also getting a facelift with the emergence of a promising technology known as blockchain technology. The technology promises to be different from the existing technology in terms of its attributes. Companies like <a target="_blank" href="https://nestcoin.com/">Nestcoin</a> build products making use of this technology. This is referred to as web3.</p>
<p>So what is the difference between web2 and web3?</p>
<p>We will be looking at four(4) areas where there are differences.</p>
<ul>
<li>Openness</li>
<li>Identity</li>
<li>Organisation </li>
<li>User Experience</li>
</ul>
<h3 id="heading-openness">Openness</h3>
<p>One difference between web2 and web3 has to do with how open they are. web2 is not known to be as open as web3. web2 is built around the concept that the codebase and data for a product are in the hands of the organisation managing it and only those authorized have access to it. web3 is built on the concept that the user data is openly available and any organisation running a similar service can access this data. The codebase is also publicly available ensuring that anyone with technical knowledge can study it and understand what they are getting into. It also allows for the discovery of vulnerabilities on the product level from users of the product.</p>
<h3 id="heading-identity">Identity</h3>
<p>On web2 the user identity on a product is confirmed either through the use of social login or password and any other value that uniquely identifies a user on a system like an email, phone number, etc. web3 made it different by allowing users to use a system by the click of a few buttons. The user's wallet address became his identity and no other details were needed from the user to access the system.</p>
<h3 id="heading-organisation">Organisation</h3>
<p>This may not be true for all organisations building products for web3. But more and more are taking up a structure that allows for transparency and freedom that was not available for organisations building on the web2. This starts from how funding is sourced. Early-stage builders on web2 will require friends, family, venture capitalists, etc. To fund what is being built. 
web3, brought a change anyone can buy a stake in the organisation if they are interested. Due to owning a part of the firm they have the freedom to vote on decisions that affect the future of the organisation. Individuals can sell all their stake or a part of it whenever they want, thereby cashing out their profits if any.</p>
<p>On a side note, if you are thinking about learning more about web3, the team at <a target="_blank" href="https://zuri.team/">Zuri</a> in collaboration with <a target="_blank" href="https://nestcoin.com/">Nestcoin</a> are organizing <a target="_blank" href="https://blockgames.gg/">Blockgames</a> which helps to train people to become blockchain developers. You can check them out and join the next cohort if interested.</p>
<h3 id="heading-user-experience">User Experience</h3>
<p>Coming from a web2 world user experience is great each product is competing to capture your attention the longest. Starting from the user interface to the words used. In the web3 world, a lot still needs to the done to ensure that users can use a product with ease. Also, the creation of Ethereum Name Service(ENS) has reduced friction, ensuring that users do not need a long combination of characters(wallet address) to make a transaction and that it can be using the easy-to-remember username of the required address.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Finally, we have looked at four(4) areas where differences exist between web2 and web3. With time user experience on web3 is expected to get better. The rest is expected to widen as we find more use cases and continue to improve on the blockchain technology that powers web3.</p>
]]></content:encoded></item><item><title><![CDATA[How I Implemented IPFS to Save Images]]></title><description><![CDATA[I had to use IPFS to save image files on a project I worked on. It was a blockchain project with the smart contract written in solidity. The front end is in vanilla JavaScript, HTML, and CSS. This article shows how I was able to use IPFS from the fro...]]></description><link>https://princecurie.tech/how-i-implemented-ipfs-to-save-images</link><guid isPermaLink="true">https://princecurie.tech/how-i-implemented-ipfs-to-save-images</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[ipfs]]></category><category><![CDATA[HTML]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Sun, 11 Apr 2021 16:04:01 GMT</pubDate><content:encoded><![CDATA[<p>I had to use IPFS to save image files on a project I worked on. It was a blockchain project with the smart contract written in solidity. The front end is in vanilla JavaScript, HTML, and CSS. This article shows how I was able to use IPFS from the frontend to save the image and also how I was able to view the image from the browser. The codebase I will be referencing can be found <a target="_blank" href="https://gist.github.com/prince-curie/d72baad9b0cc0d2bc8d5f25f532a75a8">here</a>.  </p>
<h3 id="heading-importing-the-ipfs-class">Importing The IPFS Class</h3>
<p>In order to interact with IPFS, we need to import it. Since the front end is in vanilla JavaScript we use the <code>ipfs</code> package hosted on a Content Delivery Network(CDN). We import the <code>ipfs</code> package globally into the project as a javascript script using the link <code>&lt;script src="https://cdn.jsdelivr.net/npm/ipfs/dist/index.min.js"&gt;&lt;/script&gt;</code>. The link is placed in the HTML file.</p>
<h3 id="heading-uploading-image-with-ipfs">Uploading Image with IPFS</h3>
<p>After importing the script we need to upload the image. To do this we:</p>
<ol>
<li>Create an interface to ensure an image is picked.</li>
<li>Have event listeners listen for when a file is selected</li>
<li>Upload the image to IPFS</li>
</ol>
<h4 id="heading-create-an-interface-to-ensure-an-image-is-picked">Create an interface to ensure an image is picked</h4>
<p>To ensure a file is picked, a form is created with a input field for file, in the <code>index.html</code> file. </p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-attr">accept</span>=<span class="hljs-string">"image/*"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"image"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"file"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<h4 id="heading-create-event-listeners">Create event listeners</h4>
<p>We need to listen for when an image has been selected for upload. The event listener listens for the 'change' event on the <code>id</code> file. The listener is located in the <code>app.js</code> file. </p>
<pre><code class="lang-javascript">  <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#file'</span>).addEventListener(<span class="hljs-string">'change'</span>, upload)
</code></pre>
<p>When the event is fired, the <code>upload</code> method is called to handle it.</p>
<h4 id="heading-upload-the-image">Upload the image</h4>
<p>To upload the image, we ensure that the image is read by the javascript file and converted to an ArrayBuffer.</p>
<p>To read the image and convert it to ArrayBuffer we use the javascript <code>FileReader</code> Object. On the <code>FileReader</code> object we listen for the <code>load</code> event to ensure that the image has been successfully loaded.</p>
<p>The <code>load</code> event handler, takes the resulting ArrayBuffer which is saved on the result property of the <code>FileReader</code> object and sends it as a parameter to the add method of Ipfs.</p>
<p>To get IPFS ready for use we need to call the <code>create</code> method on <code>Ipfs</code> and assign it to a  variable. We will call the variable <code>node</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> node = <span class="hljs-keyword">await</span> Ipfs.create()
</code></pre>
<p>The <code>add</code> method of ipfs uploads the image.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">await</span> node.add(fileReader.result)
</code></pre>
<p>Finally, below is the function in full.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">upload</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> fileReader = <span class="hljs-keyword">new</span> FileReader()
    <span class="hljs-comment">// Read file as ArrayBuffer</span>
    <span class="hljs-keyword">await</span> fileReader.readAsArrayBuffer(event.target.files[<span class="hljs-number">0</span>])
    <span class="hljs-comment">//  Listen for the onload event</span>
    fileReader.onload = <span class="hljs-keyword">async</span> (event) =&gt; {            
        <span class="hljs-keyword">const</span> node = <span class="hljs-keyword">await</span> Ipfs.create()
        <span class="hljs-comment">// upload the file content</span>
        <span class="hljs-keyword">let</span> { path } = <span class="hljs-keyword">await</span> node.add(fileReader.result)

        <span class="hljs-built_in">console</span>.log(path)
    }
}
</code></pre>
<h3 id="heading-viewing-image-on-ipfs">Viewing Image on IPFS</h3>
<p>To fetch the image from IPFS, we need to attach the logged value to this URL: <a target="_blank" href="https://ipfs.io/ipfs/">https://ipfs.io/ipfs/</a>. Running it on a web browser will return the image saved. </p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>This article explains how I used IPFS to save images. I hope it passes the needed information to help you go through with such a task. </p>
]]></content:encoded></item><item><title><![CDATA[Create a File with Node.js]]></title><description><![CDATA[Node.js makes it possible to interact with your operating system filesystem, like reading from a file, deleting a file, updating a file, amongst others. Today, we look at various methods in the Node.js file system module that makes it possible to cre...]]></description><link>https://princecurie.tech/create-a-file-with-nodejs</link><guid isPermaLink="true">https://princecurie.tech/create-a-file-with-nodejs</guid><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[files]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Wed, 31 Mar 2021 16:26:23 GMT</pubDate><content:encoded><![CDATA[<p>Node.js makes it possible to interact with your operating system filesystem, like reading from a file, deleting a file, updating a file, amongst others. Today, we look at various methods in the Node.js file system module that makes it possible to create a file.</p>
<p>N.b: Most of the methods come in 3 forms, synchronous, callback and promise.
N.b: To use the file system module, we need to import it. An example is shown below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>) 
<span class="hljs-comment">// For methods which are synchronous or requires a callback</span>
<span class="hljs-comment">// or </span>
<span class="hljs-keyword">const</span> fsPromises = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>).promises 
<span class="hljs-comment">// for methods which returns a promise.</span>
</code></pre>
<p>N.b: The term <code>__dirname</code> is a variable that returns the directory name where the current Node.js file running it resides. <code>__dirname</code> does not need to be imported.</p>
<p>This article will require that you have a code editor and Node.js installed on your system.
You can create a file with a <code>.js</code> extension. To run the code, from your terminal pointing at the root folder where your file is you run <code>node &lt;YOUR-FILE-NAME&gt;.js</code>.</p>
<h2 id="the-open-method">The Open Method</h2>
<p>The open method accepts the file path as a required argument and returns a file descriptor(fd). </p>
<p>A file descriptor is a number assigned to an open file by the operating system in memory. This number is later used to identify and track this file.
The open method is needed to be called first when calling methods that require the file descriptor, like the read and write method etc.</p>
<p>To create a file using the open method, we need to pass in the path in which the file is located and the flag. The flag tells the open method why it needs to open the file.
A list of available flags and use cases can be found here <a target="_blank" href="https://nodejs.org/docs/latest-v12.x/api/fs.html#fs_file_system_flags">file system flags</a>. 
The flags are in three groups, writing, reading and appending. 
To create a file we need to use the flags for writing and appending. The append and write flag will create the file if it does not exist. By default, the open method uses the read flag. </p>
<p>The open method will not create a non-existing folder. Ensure that the file is located in the last know folder. </p>
<h3 id="fsopensync">fs.openSync()</h3>
<p>This method is synchronous</p>
<ul>
<li>An example using the write flag.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> fd = fs.openSync(__dirname + <span class="hljs-string">'/mew.txt'</span>, <span class="hljs-string">'w'</span>)

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'fd ==&gt; '</span>, fd)
</code></pre>
<h3 id="fsopen">fs.open()</h3>
<p>This method is asynchronous and requires a callback function</p>
<ul>
<li>An example using the append flag.</li>
</ul>
<pre><code class="lang-javascript">fs.open(__dirname + <span class="hljs-string">'/mewe.txt'</span>, <span class="hljs-string">'a'</span>, <span class="hljs-function">(<span class="hljs-params">err, fd</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (err) <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'err ==&gt; '</span>,err);
    <span class="hljs-keyword">if</span> (fd) <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'fd ==&gt; '</span>, fd)    
})
</code></pre>
<h3 id="fspromisesopen">fsPromises.open()</h3>
<p>This method returns a promise object, which resolves to an instance of the FileHandle object. The fileHandle is a wrapper for the integer file descriptor and contains a close method. Always close the fileHandle.</p>
<ul>
<li>An example with the async-await keyword.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createFile</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">let</span> fileHandle
    <span class="hljs-keyword">try</span> {
        fileHandle = <span class="hljs-keyword">await</span> fsPromises.open(__dirname + <span class="hljs-string">'/mow.txt'</span>, <span class="hljs-string">'a'</span>)        
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'fileHandle ==&gt; '</span>, fileHandle)
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'err ==&gt; '</span>, err)
    } <span class="hljs-keyword">finally</span> {
        <span class="hljs-keyword">await</span> fileHandle.close()
    }
}

createFile()
</code></pre>
<h2 id="the-createwritestream-method">The CreateWriteStream Method</h2>
<p>The <code>fs.createWriteStream</code> method creates an instance of <code>fs.writeStream</code> and returns the instance. It comes only in synchronous form. </p>
<p>To create a file with <code>fs.createWriteStream</code> we only need to pass the file path. The file path like <code>fs.open</code> should be in existence, as it only creates a new file. Passing the file descriptor in the options means the file is in existence. The method will ignore the file path and use the file descriptor. At its default state, a non-existing file is created and an existing file is overwritten. </p>
<p>The createWriteStream function behaviour can be slightly altered by setting the options part of the method.
<code>fs.createWriteStream(path, {options})</code></p>
<h3 id="fscreatewritestream">fs.createWriteStream()</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> result = fs.createWriteStream(__dirname + <span class="hljs-string">'/meow.txt'</span>)
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'result ==&gt; '</span>, result)
</code></pre>
<p>The result variable will contain an instance of the <code>writeStream</code> object when successful and this contains all the methods and properties that can be called to take action on the file or get details of a file.</p>
<h2 id="other-methods">Other Methods</h2>
<p>If you have gotten this far, Hurray. We considered two methods that can create a file, without needing the file content. </p>
<p>We are about to consider two methods for creating files that require passing in the file content.</p>
<p>The methods are:</p>
<ul>
<li>fs.writeFile()</li>
<li>fs.appendFile()</li>
</ul>
<p>They both have the three forms discussed earlier which are synchronous, callback and promise. </p>
<p>They also can accept a file descriptor if the file has been open for appending or writing. They both accept the file path and the data to be written to the file. If the file does not exist the file is created. <code>fs.appendFile()</code> will add to the contents of an existing file while <code>fs.writeFile()</code> overwrites the content of an existing file. </p>
<p>File system flags such as <code>wx+</code> or <code>wx</code> for writing, and <code>ax+</code> or <code>ax</code> for appending, can be added to ensure it fails if the file exists. </p>
<p>They both return undefined after executing.</p>
<p> When you pass the file content as an empty string <code>''</code> it creates an empty file.</p>
<h2 id="the-writefile-method">The WriteFile Method</h2>
<p>The writeFile method by default, comes with the write flag <code>w</code>.</p>
<h3 id="fswritefilesync">fs.writeFileSync()</h3>
<p>This is a synchronous method.</p>
<pre><code class="lang-javascript">fs.writeFileSync(__dirname + <span class="hljs-string">'/mew.txt'</span>, <span class="hljs-string">'Can you keep a secret'</span>)
</code></pre>
<p>To ensure it does not overwrite an existing file we add one of the flags specified above.</p>
<pre><code class="lang-javascript">fs.writeFileSync(__dirname + <span class="hljs-string">'/mew.txt'</span>, <span class="hljs-string">'Can you keep a secret90'</span>, {<span class="hljs-attr">flag</span>: <span class="hljs-string">'wx+'</span>})
</code></pre>
<h3 id="fswritefile">fs.writeFile()</h3>
<p>This method accepts a callback function as its last argument.</p>
<pre><code class="lang-javascript">fs.writeFile(__dirname + <span class="hljs-string">'/mew.txt'</span>, <span class="hljs-string">'Can you keep a secret'</span>, {<span class="hljs-attr">flag</span>: <span class="hljs-string">'wx'</span>}, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'err ==&gt; '</span>, err)
})
</code></pre>
<p>To ensure it does overwrite an existing file</p>
<pre><code class="lang-javascript">fs.writeFile(__dirname + <span class="hljs-string">'/mew.txt'</span>, <span class="hljs-string">'Can you keep a secret'</span>, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'err ==&gt; '</span>, err)
})
</code></pre>
<h3 id="fspromisewritefile">fsPromise.writeFile()</h3>
<p>This method returns a promise. In this example, we chain it with a then method and a catch method.</p>
<pre><code class="lang-javascript">fsPromises.writeFile(__dirname + <span class="hljs-string">'/mew.txt'</span>, <span class="hljs-string">'If walls could talk'</span>)
    .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res)
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err))
</code></pre>
<p>A flag can be added as a third argument as shown in the previous example.</p>
<h2 id="the-appendfile-method">The AppendFile Method</h2>
<p>This method by default comes with an <code>a</code> flag. This makes it possible to add content to an existing file. That is not the goal since we want to create a new file. Therefore all examples will contain flags that ensure that an exception is thrown if the file exists.</p>
<h3 id="fsappendfilesync">fs.appendFileSync()</h3>
<p>This method is a synchronous method</p>
<pre><code class="lang-javascript">fs.appendFileSync(__dirname + <span class="hljs-string">'/mew.txt'</span>, <span class="hljs-string">'Truly Madly Deeply'</span>, {<span class="hljs-attr">flag</span>: <span class="hljs-string">'ax'</span>})
</code></pre>
<h3 id="fsappendfile">fs.appendFile()</h3>
<p>This method accepts a callback function as its last argument.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> data = <span class="hljs-string">'Do they know the places where we go when we are grey and old'</span>
fs.appendFile(__dirname + <span class="hljs-string">'/mew.txt'</span>, data, {<span class="hljs-attr">flag</span>: <span class="hljs-string">'ax+'</span>}, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err))
</code></pre>
<h3 id="fspromisesappendfile">fsPromises.appendFile()</h3>
<p>This method returns a promise</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> data = <span class="hljs-string">'I hope this finds a way to your heart.'</span>

fsPromises.appendFile(__dirname + <span class="hljs-string">'/mew.txt'</span>, data, {<span class="hljs-attr">flag</span>: <span class="hljs-string">'ax+'</span>})
    .then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> res)
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(err))
</code></pre>
<h2 id="conclusion">Conclusion</h2>
<p>This article looks at four methods that can create a file in Node.js and the various forms each method has. It discusses some side effects it has if an already existing file is been called to be created by the last two methods. The data written into the file in the last two methods were lines gotten from songs I was listening to while writing.  I hope you enjoyed reading this. </p>
]]></content:encoded></item><item><title><![CDATA[Accessing Inputs with Node.js Standard Input]]></title><description><![CDATA[One question to ask on seeing the topic is, what is standard input? Using the human body to answer we can say that the human body needs a place to take in food which is through the mouth.
Like the human body, every computer program running on Linux/U...]]></description><link>https://princecurie.tech/accessing-inputs-with-nodejs-standard-input</link><guid isPermaLink="true">https://princecurie.tech/accessing-inputs-with-nodejs-standard-input</guid><category><![CDATA[Node.js]]></category><category><![CDATA[process]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Mon, 15 Mar 2021 11:24:40 GMT</pubDate><content:encoded><![CDATA[<p>One question to ask on seeing the topic is, what is standard input? Using the human body to answer we can say that the human body needs a place to take in food which is through the mouth.
Like the human body, every computer program running on Linux/UNIX based terminal needs a way to accept user input. That is usually through the keyboard. This is the standard input.
Node.js has a method that accepts user input. This method is the stdin found in the global process module </p>
<h2 id="the-stdin-method">The <code>stdin</code> Method</h2>
<p>To access a one-line user input from the keyboard in the program, the process.stdin method which is an instance of Node.js readable stream is called, with the once event listener function attached to it. The once event listener accepts an event name and then a listener function. An example is below.</p>
<pre><code class="lang-javascript">process.stdin.once(<span class="hljs-string">'data'</span>, <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-comment">// Code to perform an action</span>
})
</code></pre>
<p>The event name is data. The data event name is emitted once the user completes typing in the input and clicks on the enter button to send it. The once event listener listens for the data event from the process.stdin. Once the event is emitted from the process.stdin. The listener function which is a callback function collects the incoming data from the terminal as an argument.
Below is a function where the incoming input is displayed in the terminal.</p>
<pre><code class="lang-javascript">process.stdin.once(<span class="hljs-string">'data'</span>, <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data)
})
</code></pre>
<p>So copy and save the code in a javascript file. Run the code by opening the terminal and typing <code>node &lt;name_of_the_file&gt;.js</code>. Please ensure the path of your terminal is in the same location as your file.</p>
<p>I guess you ran the code and realised you are stuck in the program. Ooops, sorry. You can use the combination of <code>ctrl</code> and <code>c</code> keys to end the program.  This is done by pressing the <code>Ctrl</code> key and then the <code>c</code> key while still pressing the <code>Ctrl</code> button.</p>
<p>To end the program after it is done with accepting user input and running the listener function. The exit method of the process global module is called. This terminates the running program as soon as possible. The exit method is at the bottom of the callback function, to ensure every part of the program runs before we leave.</p>
<p>So our program looks like this:</p>
<pre><code class="lang-javascript">process.stdin.once(<span class="hljs-string">'data'</span>, <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data)

    process.exit()
})
</code></pre>
<h2 id="conclusion">Conclusion</h2>
<p>This article looks at the Node.js implementation of standard input using the <code>process.stdin</code> method to accept keyboard inputs for programs that run on the terminal. 
Thanks for reading, I hope you love it. Will like to read your comments about the article.</p>
]]></content:encoded></item><item><title><![CDATA[Basics of Test Doubles]]></title><description><![CDATA[Test doubles also known as imposter has long been likened to the stunt doubles found in movies. They act in place of the movie actor/actress to perform stunts. 
In the world of software testing test doubles is a term that refers to objects used to re...]]></description><link>https://princecurie.tech/basics-of-test-doubles</link><guid isPermaLink="true">https://princecurie.tech/basics-of-test-doubles</guid><category><![CDATA[TDD (Test-driven development)]]></category><category><![CDATA[Testing]]></category><category><![CDATA[unit testing]]></category><category><![CDATA[test]]></category><category><![CDATA[test driven development]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Thu, 31 Dec 2020 19:57:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1609444548106/4JgsGm_RT.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Test doubles also known as imposter has long been likened to the stunt doubles found in movies. They act in place of the movie actor/actress to perform stunts. 
In the world of software testing test doubles is a term that refers to objects used to replace objects in production.
This article answers questions such as:</p>
<ul>
<li>Why we need a test double?</li>
<li>The different types of test doubles.</li>
<li>What look out for when using a test double.</li>
</ul>
<h2 id="why-use-a-test-double">Why use a test double</h2>
<p>We use test doubles in any of these situations</p>
<ul>
<li>The object it depends on is not available.</li>
<li>There is an uncertainty in the result the object will return.</li>
<li>Running the object will lead to undesirable side effects.</li>
</ul>
<h2 id="types-of-test-doubles">Types of test doubles</h2>
<p>We look at five(5) types of test doubles.</p>
<ul>
<li><p>Dummy Object: As the name implies are dummies, nothing special about them. They are in use when you need to fill a position, as a necessary parameter to call a method or create an instance of a class. Dummy objects are empty, no methods, no properties, so it cannot take any action and does not need to.</p>
</li>
<li><p>Fake Object: Like an imitation of an original look like the original but is lacking in some ways. The fake object unlike the dummy object contains some implementation of the object in production. Unlike the object in production, fake objects have a lot of short cuts and are more simplified. The shortcut and simplification allow for the avoidance of undesirable side effects. An in-memory database used in testing is an example of a fake object. </p>
</li>
<li><p>Test Spy: Test spy like a spy sits back to gather information about the interaction of the logic under test and the object it is replacing. The details in this information are verified after the logic under test is done with the test. Spies verifies actions felt outside the code under test.</p>
</li>
<li><p>Mock: A Mock is like a spy, but an impatient one if I may say. A mock verifies the action triggered by the logic under test, but felt by other systems takes place by defining the expectations for it before the logic under test is run.  </p>
</li>
<li><p>Test stub: A test stub is an object that has no logic but only a predefined response. </p>
</li>
</ul>
<h2 id="what-to-avoid-when-using-test-doubles">What to avoid when using test doubles</h2>
<p>These are a few tips to have in mind when using test doubles.</p>
<ul>
<li>Do not use too many test doubles in a test.</li>
<li>Your test doubles should not be complex.</li>
<li>Do not replace data structures with test doubles.</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>In conclusion, I hope this explains to beginners what test doubles are and the various types. If you have made it here kindly like the article and drop a comment. Thanks.</p>
]]></content:encoded></item><item><title><![CDATA[Setting up Twilio Function for Sending Text and Whatsapp Messages]]></title><description><![CDATA[The joy of having a scalable, secure messaging service, while not bothering about infrastructure. Allowing you to move fast from writing business logic to production is what Twilio function offers.
Today, we will look at the step by step process of s...]]></description><link>https://princecurie.tech/setting-up-twilio-function-for-sending-text-and-whatsapp-messages</link><guid isPermaLink="true">https://princecurie.tech/setting-up-twilio-function-for-sending-text-and-whatsapp-messages</guid><category><![CDATA[twilio]]></category><category><![CDATA[messaging]]></category><category><![CDATA[whatsapp]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Sat, 26 Dec 2020 13:58:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1608987104017/iW-bnMJ5k.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The joy of having a scalable, secure messaging service, while not bothering about infrastructure. Allowing you to move fast from writing business logic to production is what Twilio function offers.
Today, we will look at the step by step process of setting up Twilio functions for sending Text and Whatsapp messaging. We will be creating two functions. The first one will send Whatsapp messages and the second one will send text messages.</p>
<h2 id="requirements">Requirements</h2>
<ul>
<li>A free or paid Twilio account. If you are new to Twilio you can sign up by  <a target="_blank" href="https://www.twilio.com/try-twilio">clicking here</a>.</li>
<li>Knowledge of javascript or a desire to learn.</li>
<li>Web browser.</li>
<li>A device with Whatsapp installed on it and working.</li>
</ul>
<h2 id="setting-up-a-twilio-function">Setting up a Twilio function</h2>
<ol>
<li>After logging in to your Twilio account.</li>
<li>Click on the icon with the three dots at the left top corner below the home icon to open the menu.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608877462813/g9JranwBq.jpeg" alt="twilio1.JPG" /></li>
<li>Clicking on the icon opens the sidebar, on the sidebar scroll down to the RUNTIME section and click on Functions.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608877800504/pwbokXui3.jpeg" alt="twilio2.JPG" /></p>
<ol>
<li>We need to create a service. A service is like an application container to store your functions for a project. To create a service, we click on the create service button</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608878189060/Oc2qfZVNz.jpeg" alt="twilio3.JPG" /></p>
<ol>
<li>Clicking on the button, a modal popup asking you to name the service. The name will be the first part of your serverless domain.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608890578870/B7zPTqc5x.jpeg" alt="twilio4.JPG" /></p>
<ol>
<li><p>After inputting the name and clicking on the Next button. It creates a service.</p>
</li>
<li><p>We next add a function to the service by clicking on the add button at the top left side of the screen.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608891961030/4TT7el6va.jpeg" alt="twilio5.JPG" /></p>
<ol>
<li>Click on the add function option. Input the name of the function and press the enter button. The function forms and a code sample in the code editor appear to get you started.</li>
</ol>
<h2 id="sending-whatsapp-messages">Sending Whatsapp messages</h2>
<p>After setting up a function we need to configure it to send Whatsapp messages. The following steps below explain how to do it.</p>
<ol>
<li>Click on the three horizontal dots beside the function name. Select the <code>Copy URL</code> option.</li>
<li>Click on the icon with three dots on the top left corner of the screen to open the side menu.</li>
<li>Select Programmable messaging.</li>
<li>Select Settings at the bottom of the sidebar menu.</li>
<li>Select Whatsapp Sandbox Settings</li>
<li>Input the URL generated when you created the function into <code>WHEN A MESSAGE COMES IN</code> field.</li>
<li>Scroll to the bottom and click on save.
Let us move back to the code editor of the existing function. Follow steps two(2) to three(3) steps mentioned when discussing how to set up a Twilio function, above.</li>
<li>Click on services or manage services.</li>
<li>From the list of existing services, click on the service we are working with.</li>
<li>Click on the function you are working with to ensure it appears on the code editor if it is not open.</li>
<li>Delete the entire content of the function block except for the return statement.</li>
<li>Paste the following code to send a hello world response back when we send a message.<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> twiml = <span class="hljs-keyword">new</span> Twilio.twiml.MessagingResponse();
twiml.message(<span class="hljs-string">'Hello World'</span>);
</code></pre>
</li>
<li>Click on Save and after saving click on Deploy All.
Below is a GIF showing the entire process.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608909119350/xVzYJWOmW.gif" alt="twilio1.gif" /></p>
<h2 id="test">Test</h2>
<p>To test what has been done so far, we need to go to step five(5) of sending Whatsapp message above to get the Whatsapp number and sandbox name.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608911058297/-4KW3t9iF.jpeg" alt="twilio6.JPG" />
On your device open your Whatsapp application and send join  to the number to get it connected.
Send any message to the Whatsapp number and get the hello world message specified in <code>twiml.message('Hello World');</code>.</p>
<h2 id="sending-a-text-message">Sending a Text message</h2>
<p>To send text messages we need to set up a new function. On creating the new function, we set the necessary environment variable and visibility of the function.</p>
<h3 id="setting-environment-variable">Setting Environment Variable</h3>
<p>To set environment variables we need to follow this few steps:</p>
<ol>
<li>Go down to the Settings section at the bottom towards the left and click on Environment Variables.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608961838759/_Sb3NXYQ8.jpeg" alt="twilio7.JPG" /></p>
<ol>
<li>Click on the check box that says "Add my Twilio Credentials (ACCOUNT_SID) and (AUTH_TOKEN) to ENV". If it is not checked already.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608962034034/gt8O0TkWX.jpeg" alt="twilio8.JPG" /></p>
<h3 id="set-function-visibility">Set Function Visibility</h3>
<p>Every function by default has their visibility set to "Protected" which means we need to have a valid Twilio signature to our request headers to invoke the function. For this tutorial, we will be using the "Public" option that allows us to invoke the function from the browser. 
To set the visibility of a function we:</p>
<ol>
<li>Click on the drop-down menu to the right of the function name</li>
<li>Select the visibility we want, which for now is public.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1608963051315/yqAvMZeAL.gif" alt="twilio2.gif" /></p>
<p>We go back to the function block, delete every code in it, make the function asynchronous and add a try-catch block.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">context, event, callback</span>) </span>{
  <span class="hljs-keyword">try</span> {

 <span class="hljs-keyword">catch</span>(error) {

  }
}
</code></pre>
<p>Next we:</p>
<ol>
<li>Make a call to getTwilioClient method. It is in the context parameter. The context parameter is where we can interact with the environment variable and also the pre-initialised Twilio REST Client. So it returns an initialised twilioClient.<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> twilioClient = context.getTwilioClient();
</code></pre>
</li>
<li><p>Set the variables to, from and body using the event parameter or a pre-defined value.</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">let</span> <span class="hljs-keyword">from</span> = event.From;
 <span class="hljs-keyword">let</span> to = event.To;
 <span class="hljs-keyword">let</span> body = event.Body;
</code></pre>
<ol>
<li>Make a call to the Twilio REST Client API by passing by chaining the create method to messages method and the message method to the twilioClient. We pass the body, to and from variables in an object to the create method.<pre><code class="lang-javascript"><span class="hljs-keyword">await</span> twilioClient.messages
.create({
  body,
  to,
  <span class="hljs-keyword">from</span>,
});
</code></pre>
</li>
</ol>
</li>
<li><p>Add the return statement both in the try block and also the catch block. 
<code>return callback(null, 'success');</code> to the try block and <code>return callback(error);</code> to the catch block.</p>
</li>
<li>Click on save and then on Deploy All after saving.</li>
</ol>
<p>The code will finally look like.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">context, event, callback</span>) </span>{
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> twilioClient = context.getTwilioClient();

    <span class="hljs-keyword">let</span> <span class="hljs-keyword">from</span> = event.From;
    <span class="hljs-keyword">let</span> to = event.To;
    <span class="hljs-keyword">let</span> body = event.Body;

    <span class="hljs-keyword">await</span> twilioClient.messages
      .create({
        body,
        to,
        <span class="hljs-keyword">from</span>,
      });

    <span class="hljs-keyword">return</span> callback(<span class="hljs-literal">null</span>, <span class="hljs-string">'success'</span>);  
  } <span class="hljs-keyword">catch</span>(error) {
    <span class="hljs-keyword">return</span> callback(error);
  }
}
</code></pre>
<h2 id="testing">Testing</h2>
<p>To test the SMS sending we </p>
<ol>
<li>Click on the three horizontal dots beside the function name. Select the <code>Copy URL</code> option.</li>
<li>Open a browser and paste the URL there</li>
<li>Add the query parameters From, To and Body in this manner.
<code>?From=+15095550100&amp;To=+15105550100&amp;Body=Hello%20World</code>
It is important to note that if you are using a trial account. From will be your trial phone number found on your dashboard. To will be the number used in creating the Twilio account or any other phone number you add to it. </li>
<li>Attach it to the URL in the browser and get a success response.</li>
</ol>
<h2 id="conclusion">Conclusion</h2>
<p>If you have made it this far, thanks. We looked at how to set up Twilio functions to send SMS and Whatsapp messages. How it does not need installing Twilio in your codebase and allows your messaging service to run outside your application.
Drop your comments and feedback in the comment section and click on the like button.
Thanks.</p>
]]></content:encoded></item><item><title><![CDATA[Developer's Guide to Flow Charts]]></title><description><![CDATA[A flow chart is a pictorial representation of the steps needed to perform a task, in its exact order. A flow chart can also be called flowchart, process flowchart, functional flowchart, process map, process chart, functional process chart, business p...]]></description><link>https://princecurie.tech/developers-guide-to-flow-charts</link><guid isPermaLink="true">https://princecurie.tech/developers-guide-to-flow-charts</guid><category><![CDATA[flow]]></category><category><![CDATA[charts]]></category><category><![CDATA[process]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Fri, 11 Dec 2020 03:07:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1607654607248/QFeQ8jabY.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A flow chart is a pictorial representation of the steps needed to perform a task, in its exact order. A flow chart can also be called flowchart, process flowchart, functional flowchart, process map, process chart, functional process chart, business process model, process model, process flow diagram, workflow diagram, business flow diagram. The terms "flowchart" and "flow chart" can be interchanged.</p>
<h2 id="importance-of-flow-chart">Importance of flow chart</h2>
<ul>
<li>breaking down complex algorithms</li>
<li>helps team members understand the order in which a process follows</li>
<li>creates a visual representation of the steps involved in a project</li>
<li>helps document a process</li>
</ul>
<h2 id="flow-chart-symbols">Flow chart symbols</h2>
<p>We will look at the five most used flow chart symbols</p>
<ul>
<li>Terminators: This symbol is oval-shaped and sometimes appear as a circle. It signifies the beginning or end of a process depending on where it appears.  </li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607466685625/PolAbkKjD.jpeg" alt="terminators.JPG" /></p>
<ul>
<li>Data: This symbol takes the shape of a parallelogram. It signifies the input or output of data.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607466828410/rjc9TtGdE.jpeg" alt="data.JPG" /></p>
<ul>
<li>Decision: This symbol has the shape of a rhombus or diamond. It shows that a decision needs to be taken, it branches out based on the outcome of the decision.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607466918791/cplSqAkvp.jpeg" alt="decision.JPG" /></p>
<ul>
<li>Processes: This symbol can be a rectangle or square but mostly a rectangle. It shows the next step to be taken.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607467196678/gA9pxnbvp.jpeg" alt="processes.JPG" /></p>
<ul>
<li>Arrow: This symbol shows the direction of flow from one step to the other.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607653556040/hwQOAwtni.jpeg" alt="arrow.JPG" /></p>
<h2 id="sample-flow-chart">Sample flow chart</h2>
<p>The sample flow chart shows the steps involve when a user tries to log in on a webpage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1607632332269/YT5NGhhuo.png" alt="flow chart.png" /></p>
<h2 id="tools-for-creating-a-flow-chart">Tools for creating a flow chart</h2>
<p>These tools consist of a pen and paper to software tools that are free and some that are paid. Below are examples of some:</p>
<ul>
<li>Pen and Paper</li>
<li><a target="_blank" href="https://app.diagrams.net/">diagrams.net</a></li>
<li><a target="_blank" href="http://pencil.evolus.vn/">Pencil Project</a> </li>
<li><a target="_blank" href="https://creately.com/">Creately</a></li>
<li><a target="_blank" href="https://www.lucidchart.com/pages/">Lucidchart</a>  </li>
</ul>
<h2 id="flow-chart-best-practices">Flow chart best practices</h2>
<p>To create a flow chart we should always keep it in mind to have it very simple and to be consistent. Some steps we can follow to achieve that includes</p>
<ul>
<li>Use standard symbols </li>
<li>Make the text readable even if it means spanning your flow chart across many pages. </li>
<li>Spacing between symbols, Colour schemes and symbol size should be consistent</li>
<li>Flow direction should be top to bottom or left to right and never interchangeable</li>
<li>While drawing a decision symbol, flow direction should be to the right for negative answers and downwards for positive answers.</li>
<li>Never assume everyone knows what each symbol in your flow chart represent, use a key to describe each symbol and its meaning.</li>
<li>Double-check the processes to ensure they are fully represented in the flow chart.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Build a Command-Line Application with Typescript and AdonisJS Ace]]></title><description><![CDATA[This article shows you how to build a command-line application using typescript and @adonisjs/ace. The command-line application accepts user input and makes a request to the numbers API. The request returns an interesting fact about the number.
To be...]]></description><link>https://princecurie.tech/how-to-build-a-command-line-application-with-typescript-and-adonisjs-ace</link><guid isPermaLink="true">https://princecurie.tech/how-to-build-a-command-line-application-with-typescript-and-adonisjs-ace</guid><category><![CDATA[Node.js]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[npm]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Thu, 19 Nov 2020 07:11:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1605764610304/9fchFqzL1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article shows you how to build a command-line application using <code>typescript</code> and <code>@adonisjs/ace</code>. The command-line application accepts user input and makes a request to the numbers API. The request returns an interesting fact about the number.
To begin you need Node.js and npm installed on your machine, npm comes together with Node.js. Basic knowledge of typescript is also advised although not necessary.
The code in use can be found in this  <a target="_blank" href="https://github.com/prince-curie/numb-cli">repo</a>.  </p>
<h2 id="installation">Installation</h2>
<ol>
<li>We run <code>npm init -y</code>. It sets up a new Node.js project in the current folder with the default details without asking any questions.</li>
<li>We install typescript globally using <code>npm install -g typescript</code>.
Next, we set up a new typescript project by running the command <code>tsc --init</code>.
The <code>tsc --init</code> command creates a <code>tsconfig.json</code> file.<br />Open the generated <code>tsconfig.json</code> file and update the following details<pre><code class="lang-json"> <span class="hljs-string">"target"</span>: <span class="hljs-string">"es2015"</span>,
 <span class="hljs-string">"outDir"</span>: <span class="hljs-string">"./dist"</span>,     
 <span class="hljs-string">"rootDir"</span>: <span class="hljs-string">"./src"</span>,
</code></pre>
The key <code>rootDir</code> describes the root directory that typescript will compile from. The key <code>outDir</code> describes the directory to save the compiled file. The key <code>target</code> describes the lowest level to compile the code to.</li>
<li>We install AdonisJs Ace which is a tool for creating command-line applications in Node.js<pre><code class="lang-bash">npm i --save @adonisjs/ace
</code></pre>
</li>
<li>We install type definition for Node.js, that allows you to use global values like process, require etc. in typescript.<pre><code class="lang-bash">npm i --save @types/node
</code></pre>
</li>
</ol>
<h2 id="creating-the-shebang">Creating the Shebang</h2>
<p>According to  <a target="_blank" href="https://en.wikipedia.org/wiki/Shebang_(Unix)">Wikipedia</a></p>
<blockquote>
<p>In computing, a shebang is the character sequence consisting of the characters number sign and exclamation mark at the beginning of a script. It is also called sha-bang, hashbang, pound-bang, or hash-pling.</p>
</blockquote>
<p>The Shebang tells the operating system what interpreter to use in running the script.
To create the shebang:</p>
<ol>
<li>We create the <code>src</code> folder, in the project root folder.</li>
<li>We create a folder called <code>bin</code> in the <code>src</code> folder.</li>
<li>We create a file we will call <code>numb-cli.ts</code>.</li>
<li>We paste the shebang by pasting the line below.</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-meta">#!/usr/bin/env node</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Welcome'</span>)
</code></pre>
<ol>
<li>We update the package.json file by adding the key-value pair.<pre><code class="lang-json"><span class="hljs-string">"bin"</span>: {
 <span class="hljs-attr">"numb-cli"</span>: <span class="hljs-string">"dist/bin/numb-cli.js"</span>
},
</code></pre>
<h2 id="testing-the-shebang">Testing the Shebang</h2>
To test if the shebang is working,</li>
<li>We compile the typescript file into javascript by running the command <code>tsc</code> on the terminal.</li>
<li>We install the package globally by running the command <code>npm link</code></li>
<li>We run the package by running the command <code>numb-cli</code>.</li>
<li>It should return the response Welcome.
N.b: To uninstall the package, use the command <code>npm unlink</code>.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1605162162783/p39Xpk6LC.gif" alt="testing cli 1.gif" /></p>
<h2 id="create-indexts-file">Create index.ts file</h2>
<p>After testing the shebang, we add the line <code>import "..";</code> in place of <code>console.log('Welcome')</code>. The new line will import the <code>index.ts</code> file, which we will create in the <code>src</code> folder. 
In the <code>package.json</code> file we update, the value for the key <code>"main"</code> with <code>"dist/index.js",</code>. 
So the <code>package.json</code> file becomes:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"numb-cli"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"dist/index.js"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"test"</span>: <span class="hljs-string">"echo \"Error: no test specified\" &amp;&amp; exit 1"</span>
  },
  <span class="hljs-attr">"bin"</span>: {
    <span class="hljs-attr">"numb-cli"</span>: <span class="hljs-string">"dist/bin/numb-cli.js"</span>
  },
  <span class="hljs-attr">"keywords"</span>: [],
  <span class="hljs-attr">"author"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"license"</span>: <span class="hljs-string">"ISC"</span>,
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"@adonisjs/ace"</span>: <span class="hljs-string">"^5.0.8"</span>,
    <span class="hljs-attr">"@types/node"</span>: <span class="hljs-string">"^14.14.7"</span>
  }
}
</code></pre>
<p>And the <code>src/bin/numb-cli.ts</code> becomes:</p>
<pre><code class="lang-typescript"><span class="hljs-meta">#!/usr/bin/env node</span>

<span class="hljs-keyword">import</span> <span class="hljs-string">".."</span>;
</code></pre>
<p>In the <code>index.ts</code> file, we import <code>ace</code>, and set it up to execute commands</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> ace <span class="hljs-keyword">from</span> <span class="hljs-string">'@adonisjs/ace'</span>;

ace.wireUpWithCommander()
ace.invoke()
</code></pre>
<p>This should work when tested, but the <code>@adonisjs/ace</code> package has no type definition so it will not compile the typescript to javascript.
Let us create a declaration file for <code>@adonisjs/ace</code>.</p>
<h3 id="creating-declaration-file">Creating declaration file</h3>
<p>At the root of the <code>src</code> folder:</p>
<ol>
<li>Create a folder called <code>@adonisjs</code></li>
<li>Create a file called ace.d.ts</li>
<li>Paste in the line <code>declare module '@adonisjs/ace';</code>
On testing, a response like the one below will appear.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1605462031377/WHLOJGtHU.gif" alt="testing cli 2.gif" /></p>
<h2 id="creating-commands">Creating commands</h2>
<p>To create commands, we extend the ace command class. The new class enables us to overrides the signature, description and the handle method. </p>
<ul>
<li>Signature method: The signature method is a getter that returns the name of the command</li>
<li>Description method: The description method is a getter that returns a description of the command.</li>
<li>Handle method: This is a method that is called when we call the command. It is an asynchronous method. It accepts two (2) parameters which are not compulsory, </li>
<li>args</li>
<li>options
We register the new command by passing it as a parameter to the <code>ace.addCommand</code> method, which we call in the <code>src/index.ts</code> file.</li>
</ul>
<p>The <code>src/index.ts</code> file becomes </p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> ace <span class="hljs-keyword">from</span> <span class="hljs-string">'@adonisjs/ace'</span>;
<span class="hljs-keyword">import</span> Random <span class="hljs-keyword">from</span> <span class="hljs-string">'./commands/Random'</span>;

ace.addCommand(Random);

ace.wireUpWithCommander();
ace.invoke();
</code></pre>
<p>We will call the command subclass <code>Random</code> and keep it in a <code>Random.ts</code> file in the <code>commands</code> folder. The <code>Random.ts</code> file will contain:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {Command} <span class="hljs-keyword">from</span> <span class="hljs-string">'@adonisjs/ace'</span>;

<span class="hljs-keyword">class</span> Random <span class="hljs-keyword">extends</span> Command {
    <span class="hljs-keyword">static</span> get signature ():<span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">'random'</span>;
    }

    <span class="hljs-keyword">static</span> get description ():<span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Returns a random fact about a number"</span>;
    }

    <span class="hljs-keyword">async</span> handle () {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Welcome'</span>);
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Random;
</code></pre>
<p>On testing the created command we get 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1605472448043/sCVv9xFH_.gif" alt="testing cli 3.gif" /></p>
<h2 id="asking-questions">Asking questions</h2>
<p><code>@adonisjs/ace</code> provides methods to ensure that interaction with users occurs. To interact with users, we will use the <code>ask</code> and the <code>choice</code> method amongst others. The ask method accepts the question and a default answer which is optional as parameters. It allows a user to input a response to the question asked. The choice method accepts 3 parameters, a question, an array of options to choose from and an optional default option. Using the two methods mentioned above, we ask the users what number he/she wants a random fact about and what category the random fact will be about.
The code in the <code>Random.ts</code> file will look like this:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> {Command} <span class="hljs-keyword">from</span> <span class="hljs-string">'@adonisjs/ace'</span>;

<span class="hljs-keyword">class</span> Random <span class="hljs-keyword">extends</span> Command {
    <span class="hljs-keyword">static</span> get signature ():<span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">'random'</span>;
    }

    <span class="hljs-keyword">static</span> get description ():<span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Returns a random fact about a number"</span>;
    }

    <span class="hljs-keyword">async</span> handle () {
        <span class="hljs-keyword">const</span> <span class="hljs-built_in">number</span>:<span class="hljs-built_in">number</span> = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>
            .ask(<span class="hljs-string">'Input a number'</span>)

        <span class="hljs-keyword">const</span> category:<span class="hljs-built_in">string</span> = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>
            .choice(<span class="hljs-string">'Select a category'</span>, [
                <span class="hljs-string">'trivia'</span>,
                <span class="hljs-string">'math'</span>,
                <span class="hljs-string">'date'</span>,
                <span class="hljs-string">'year'</span>
            ]);
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Random;
</code></pre>
<p>Testing the CLI should return:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1605652623773/kHpn_oMqt.gif" alt="testing cli 4.gif" /></p>
<h2 id="making-an-http-request">Making an HTTP request</h2>
<p>There is a need to use the details gotten earlier from the user in other get the random fact. <code>@adonisjs/ace</code> does not have the capability to make an HTTP request. To make an HTTP request we install the <code>got</code> NPM package. </p>
<pre><code class="lang-bash">npm i got
</code></pre>
<p>The command above installs <code>got</code> as a dependency.
Next, we import <code>got</code> into the <code>Random.ts</code> file.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> got <span class="hljs-keyword">from</span> <span class="hljs-string">'got'</span>;
</code></pre>
<p> In the handle method of the <code>Random</code> class, we make an HTTP <code>get</code> request to the URL that returns the fact.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> url:<span class="hljs-built_in">string</span> = <span class="hljs-string">`http://numbersapi.com/<span class="hljs-subst">${<span class="hljs-built_in">number</span>}</span>/<span class="hljs-subst">${category}</span>`</span>

<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> got(url);
</code></pre>
<h2 id="displaying-response">Displaying response</h2>
<p>At this point, the user needs to see the random fact. This is possible with either the methods provided by <code>@adonisjs/ace</code> Command class or with the use of methods of the Console class. The <code>@adonisjs/ace</code> methods each give the displayed text to a unique colour. With the console methods, the text becomes beautiful using the <code>this.chalk</code> method of the <code>Command</code> class. <code>this.chalk</code> accesses an instance of  <a target="_blank" href="https://www.npmjs.com/package/kleur">kleur</a> offering flexibility to the user.
We add Icons to the displayed response by using the <code>this.icon</code>
method of the <code>Command</code> class and passing one of the acceptable parameters which are:</p>
<ul>
<li>success</li>
<li>error</li>
<li>info</li>
<li>warn
Each of this parameter represents a particular colour and an icon. 
For the CLI we add the snippet below to display other response as well our icon<pre><code class="lang-typescript"><span class="hljs-built_in">this</span>.success(<span class="hljs-string">`<span class="hljs-subst">${response.body}</span> -  <span class="hljs-subst">${<span class="hljs-built_in">this</span>.icon(<span class="hljs-string">'success'</span>)}</span>`</span>);
</code></pre>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1605663085874/2fHXdY2sw.gif" alt="testing cli 5.gif" /></p>
<h2 id="handling-exceptions">Handling exceptions</h2>
<p>We have built the CLI this far:</p>
<ul>
<li>Creating a command;</li>
<li>Asking questions;</li>
<li>Accepting responses;</li>
<li>Making an external HTTP request;</li>
<li>Getting back results;</li>
<li>Displaying the results to the user.</li>
</ul>
<p>But what if there is an exception since we did not confirm user input and other errors that may occur from making an external network call.
To handle this <code>@adonisjs/ace</code> provides an event listener <code>onError</code>. The <code>onError</code> listens for exceptions, notes the command that throws it, and passes the exception and the command to a closure function. The closure function is where we display the error message from and stop the running process.
The onError listener is a method of the ace class and is placed in the <code>index.ts</code> file.
Since the use of icons and colourful text displays works as methods on the command class. We create an instance of the <code>Command</code> class so we can use its methods.
To throw an exception we check the user input ensuring it is a whole number. So in the handle method of the <code>Random</code> class, we add these checks:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// check if number is of datatype number</span>
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">isNaN</span>(<span class="hljs-built_in">number</span>)) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">number</span>}</span> is not a number.`</span>)
}

<span class="hljs-comment">// ensures that number is not a float</span>
<span class="hljs-keyword">if</span>(<span class="hljs-built_in">number</span> % <span class="hljs-number">1</span> != <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">number</span>}</span> should not be a decimal number`</span>)
}
</code></pre>
<p>The <code>index.ts</code> file becomes:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> ace, {Command} <span class="hljs-keyword">from</span> <span class="hljs-string">'@adonisjs/ace'</span>;

<span class="hljs-keyword">interface</span> ErrorMessage {
    message: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">const</span> command = <span class="hljs-keyword">new</span> Command()

ace.onError(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error:ErrorMessage, commandName:<span class="hljs-built_in">string</span></span>) </span>{
    command.error(<span class="hljs-string">`<span class="hljs-subst">${commandName}</span> reported <span class="hljs-subst">${error.message}</span> - <span class="hljs-subst">${command.icon(<span class="hljs-string">'error'</span>)}</span>`</span>)

    process.exit(<span class="hljs-number">1</span>)
  })
</code></pre>
<p>The <code>interface ErrorMessage</code> used above ensures the datatype of keys within the error object. So it becomes the datatype for the object.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1605769708099/W3A_1EUkn.gif" alt="testing cli 6.gif" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>This article explains how to build a Nodejs CLI using typescript and @adonisjs/ace. Always remember to compile to javascript before running and to always unlink before linking back when testing a new update. 
Finally, the code in the index.ts file will be:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> ace, {Command} <span class="hljs-keyword">from</span> <span class="hljs-string">'@adonisjs/ace'</span>;
<span class="hljs-keyword">import</span> Random <span class="hljs-keyword">from</span> <span class="hljs-string">'./commands/Random'</span>;

ace.addCommand(Random);

<span class="hljs-keyword">interface</span> ErrorMessage {
    message: <span class="hljs-built_in">string</span>;
}

<span class="hljs-keyword">const</span> command = <span class="hljs-keyword">new</span> Command()

ace.onError(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error:ErrorMessage, commandName:<span class="hljs-built_in">string</span></span>) </span>{
    command.error(<span class="hljs-string">`<span class="hljs-subst">${commandName}</span> reported <span class="hljs-subst">${error.message}</span> - <span class="hljs-subst">${command.icon(<span class="hljs-string">'error'</span>)}</span>`</span>)

    process.exit(<span class="hljs-number">1</span>)
  })

ace.wireUpWithCommander();
ace.invoke();
</code></pre>
<p>and the class in the Random.ts file will be:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Command } <span class="hljs-keyword">from</span> <span class="hljs-string">'@adonisjs/ace'</span>;
<span class="hljs-keyword">import</span> got <span class="hljs-keyword">from</span> <span class="hljs-string">'got'</span>;

<span class="hljs-keyword">class</span> Random <span class="hljs-keyword">extends</span> Command {
    <span class="hljs-keyword">static</span> get signature ():<span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">'random'</span>;
    }

    <span class="hljs-keyword">static</span> get description ():<span class="hljs-built_in">string</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Returns a random fact about a number"</span>;
    }

    <span class="hljs-keyword">async</span> handle () {
        <span class="hljs-keyword">const</span> <span class="hljs-built_in">number</span>:<span class="hljs-built_in">number</span> = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>
            .ask(<span class="hljs-string">'Input a number'</span>)
        <span class="hljs-keyword">if</span>(<span class="hljs-built_in">isNaN</span>(<span class="hljs-built_in">number</span>)) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">number</span>}</span> is not a number.`</span>)
        }

        <span class="hljs-keyword">if</span>(<span class="hljs-built_in">number</span> % <span class="hljs-number">1</span> != <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`<span class="hljs-subst">${<span class="hljs-built_in">number</span>}</span> should not be a decimal number`</span>)
        }

        <span class="hljs-keyword">const</span> category:<span class="hljs-built_in">string</span> = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>
            .choice(<span class="hljs-string">'Select a category'</span>, [
                <span class="hljs-string">'trivia'</span>,
                <span class="hljs-string">'math'</span>,
                <span class="hljs-string">'date'</span>,
                <span class="hljs-string">'year'</span>
            ]);

        <span class="hljs-keyword">const</span> url:<span class="hljs-built_in">string</span> = <span class="hljs-string">`http://numbersapi.com/<span class="hljs-subst">${<span class="hljs-built_in">number</span>}</span>/<span class="hljs-subst">${category}</span>`</span>

        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> got(url);

        <span class="hljs-built_in">this</span>.success(<span class="hljs-string">`<span class="hljs-subst">${response.body}</span> - <span class="hljs-subst">${<span class="hljs-built_in">this</span>.icon(<span class="hljs-string">'success'</span>)}</span>`</span>);
        process.exit(<span class="hljs-number">0</span>)
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Random;
</code></pre>
<p>To learn more about @adonisjs/ace you can check the official documentation  <a target="_blank" href="https://adonisjs.com/docs/4.1/ace#_questions">here</a>.
@adonisjs/ace also has the ability to work with the filesystem and the database. I hope this helps as a starting point in showing how to use the <code>@adonisjs/ace</code> and also how to use it with typescript.
If you have come this far thanks for reading. Kindly drop your comments in the comment section. </p>
]]></content:encoded></item><item><title><![CDATA[In Search of Node Modules]]></title><description><![CDATA[I know this seems funny, I am looking for my node modules. Are you looking for your node modules? Maybe not. For once, let us assume that you need to know where your node modules are. This article is about npm commands that help find where your node ...]]></description><link>https://princecurie.tech/in-search-of-node-modules</link><guid isPermaLink="true">https://princecurie.tech/in-search-of-node-modules</guid><category><![CDATA[Node.js]]></category><category><![CDATA[npm]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Mon, 09 Nov 2020 05:53:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1604867971043/Q4H4yHsdB.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I know this seems funny, I am looking for my node modules. Are you looking for your node modules? Maybe not. For once, let us assume that you need to know where your node modules are. This article is about npm commands that help find where your node module is located and what node modules are installed.
For this article, I will like to assume that you have Node.js and npm installed on your machine.</p>
<h2 id="finding-locally-installed-node-modules">Finding locally installed node modules</h2>
<p>To locate where the locally installed modules will be located or are placed. We use the command <code>npm root</code>. If you are in a folder without any node modules installed and which has not being initialised using <code>npm init</code> for a node package. The command returns the location where your node modules will exist. If you are in a folder with a node module installed or which has been initialised for a node package. The command returns the node modules location.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604817939931/YQ2lFuXg5.gif" alt="npm root locally.gif" />
Here it returns the would-be location of the node_modules folder. if it existed. 
Let us check for the installed modules in the node_modules folder returned in the image above using the <code>npm list</code> command.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604821548809/TuPjPoJDp.gif" alt="npm list locally empty.gif" />
From the GIF above we can see that there are no node packages located in the <code>node_modules</code> folder.</p>
<p>From the motion graphics below, we see that the <code>npm _commands</code> folder is empty. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604819832637/9oCMXe9IH.gif" alt="files in the folder.gif" /></p>
<p>We install some packages into the folder using the <code>npm install &lt;package name&gt;</code> command. Check for the <code>node_modules</code> folder and the installed modules.
To check for the installed modules, we use the <code>npm list</code> command used earlier.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604898668990/OFfmUwP-O.gif" alt="npm list locally.gif" /></p>
<h2 id="finding-globally-installed-node-modules">Finding globally installed node modules</h2>
<p>We know that locally installed node modules are located at the root of the package in the node_modules folder. So, where are our globally installed node modules?
To find the location we add the suffix <code>-g</code> to the command we used earlier. So the command becomes <code>npm root -g</code>. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604822995444/eM4uwaRzx.gif" alt="npm root globally.gif" />
The GIF above shows the location of where all globally installed modules are installed. 
To list the modules installed globally, we add the suffix <code>-g</code> to the command used earlier. The command becomes <code>npm list -g</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604899688844/dCKrgTqIc.gif" alt="npm list globally.gif" /></p>
<p>The command <code>npm list</code> or <code>npm list -g</code> also returns the dependency in each installed module. To avoid displaying the dependency use suffix <code>--depth=0</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1604902164505/l3iYks_Hz.gif" alt="npm list no dep.gif" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>This article has shown how to find the location of node modules installed locally and globally and how to list out each module. All from the comfort of your command line application.</p>
]]></content:encoded></item><item><title><![CDATA[How to Debug with VS Code Debugger]]></title><description><![CDATA[Debugging is a part of the act of creating beauty with programming languages. It turns one into an investigator seeking out why the work of art did not turn out as expected. One way we all learned at the beginning was to output different values while...]]></description><link>https://princecurie.tech/how-to-debug-with-vs-code-debugger</link><guid isPermaLink="true">https://princecurie.tech/how-to-debug-with-vs-code-debugger</guid><category><![CDATA[Visual Studio Code]]></category><category><![CDATA[debugging]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Mon, 26 Oct 2020 07:54:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1603584266262/KKJjHZaLE.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Debugging is a part of the act of creating beauty with programming languages. It turns one into an investigator seeking out why the work of art did not turn out as expected. One way we all learned at the beginning was to output different values while seeking out the culprit. 
This article looks at how it is done using the VS code's debugger, javascript as the programming language, and Node.js as the runtime environment.</p>
<h2 id="prerequisite">Prerequisite</h2>
<p>I will assume you have Node.Js and VS code editor installed on your system and you can create a REST API.
The code used is found in <a target="_blank" href="https://github.com/prince-curie/use_debugger">this repo</a>. </p>
<h2 id="debugger-features">Debugger Features</h2>
<h3 id="breakpoints">Breakpoints</h3>
<p>Breakpoints specify where the running code will break into the debugger. You can create a breakpoint to be absolute or conditional.</p>
<ul>
<li><p>Absolute Breakpoints: The debugger stops running the code when it gets to where a breakpoint is specified. It turns on or off by clicking on the editor margin.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603061796489/KtozIJTsb.gif" alt="absolute breakpoint.gif" /></p>
</li>
<li><p>Conditional Breakpoints: Conditional breakpoint signifies that a criterion becomes true before the breakpoint breaks the code execution. To create a conditional breakpoint, you right-click on the editor margin and select the one you want. Two types of conditional breakpoint exist:</p>
<ul>
<li><p>Expression: The breakpoint breaks the code when the expression becomes true. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603063892480/EtMWVbQOf.gif" alt="expression conditional breakpoint.gif" /></p>
</li>
<li><p>Hit Count: It determines how many times a line of code needs to be hit before the code breaks execution at that line. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603065162673/7hiC6Ox9N.gif" alt="hit count conditional breakpoint.gif" /></p>
</li>
</ul>
</li>
<li><p>Logpoint: Logpoint is a breakpoint which does not break the running code but prints a message. The value in a variable can be displayed by putting the braces in curly braces. A logpoint can be created by right-clicking on the editor margin and selecting logpoint. 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603233361960/mAHjiW8mi.gif" alt="log point.gif" /></p>
</li>
</ul>
<p>After creating each breakpoint it appears in the BREAKPOINTS section at the bottom of the sidebar.</p>
<h3 id="variables">Variables</h3>
<p>This section appears at the top sidebar when a debug section is paused by a breakpoint or with the use of the pause icon on the debug toolbar. The variable section allows you to:</p>
<ul>
<li>View the value of variables in the code at the point in which the code was paused.</li>
<li>Change the value of a variable by double-clicking on it, inputting your desired value, and pressing the enter key. </li>
<li>Add a variable to a watch list.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603378635513/Pfwfa7HKP.png" alt="variable.PNG" /></p>
<h3 id="watch">Watch</h3>
<p>This section allows you to focus on the specific variable(s). You choose which variable to focus on by right-clicking on the variable and selecting the "Add to Watch" option.<br /><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603394200821/gUEW7sZJ2.gif" alt="watch.gif" /></p>
<h3 id="debug-toolbar">Debug toolbar</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603396410907/r0l6vQFAk.png" alt="debug actions.PNG" />
The debug toolbar appears at the top of the editor when a debug section starts.
From left to right each of the icons represents:</p>
<ul>
<li>Continue / Pause </li>
<li>Step Over </li>
<li>Step Into </li>
<li>Step Out </li>
<li>Restart </li>
<li>Stop </li>
</ul>
<h3 id="debug-console">Debug console</h3>
<p>It displays logged output while debugging a program. This output is logged either with the Node.js console module or VS code's debugger logpoint. To open the debug console, click on view and select Debug Console or use the shortcut <code>Ctrl + Shift + Y</code>.</p>
<h2 id="debugging-a-function">Debugging a Function</h2>
<p>We have a function in a file called <code>app.js</code> which finds the sum of all the numbers in an array. </p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span> (<span class="hljs-params">data</span>) </span>{
  <span class="hljs-keyword">let</span> sum = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">let</span> counter = <span class="hljs-number">0</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> element <span class="hljs-keyword">of</span> data) {
    counter++
    sum = element + sum
  } 
  <span class="hljs-keyword">return</span> sum
}

<span class="hljs-keyword">const</span> result = add([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])
</code></pre>
<p>In other to run the debugger, we have to: </p>
<ul>
<li><p>Click on the run icon in the activity bar.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603057671634/jfYYxfnkN.gif" alt="click on the run icon.gif" />
Since no <code>launch.json</code> file has been created yet, the run start view is shown as seen above</p>
</li>
<li><p>Click on the <code>Run and Debug</code> button. A prompt appears asking you to select the environment.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603059716109/OhQjO231C.gif" alt="run and debug.gif" /></p>
</li>
<li><p>This selection will be made based on where your code is meant to run. Since the function will be running on the <code>Node.js</code> environment. Node.js will be selected.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603059355142/AdzW0Fx6j.gif" alt="select environment.gif" /></p>
</li>
</ul>
<p>From the image above <code>app.js</code> was run with VS code's debugger. So it begs the question, is that all? No!</p>
<p>The features above show there is more to debugging with VS code's debugger.</p>
<h2 id="debugging-a-web-api">Debugging a web API</h2>
<ul>
<li>Create a configuration file: The file allows you to save and configure debugging setup details. The setup is saved in a <code>launch.json</code> file in a <code>.vscode</code> folder</li>
<li>Start the debugging process</li>
<li>Make a request to an endpoint.
It is that simple.</li>
</ul>
<h3 id="create-a-configuration-file">Create a configuration file</h3>
<ul>
<li>Click on the run icon </li>
<li>Click on "create a launch.json file"</li>
<li><p>Select "Node.js" as environment: This creates a <code>launch.json</code> file in a <code>.vscode</code> folder. The content of the file is: </p>
<pre><code class="lang-javascript">{
  <span class="hljs-comment">// Use IntelliSense to learn about possible attributes.</span>
  <span class="hljs-comment">// Hover to view descriptions of existing attributes.</span>
  <span class="hljs-comment">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387</span>
  <span class="hljs-string">"version"</span>: <span class="hljs-string">"0.2.0"</span>,
  <span class="hljs-string">"configurations"</span>: [
      {
          <span class="hljs-string">"type"</span>: <span class="hljs-string">"node"</span>,
          <span class="hljs-string">"request"</span>: <span class="hljs-string">"launch"</span>,
          <span class="hljs-string">"name"</span>: <span class="hljs-string">"Launch Program"</span>,
          <span class="hljs-string">"skipFiles"</span>: [
              <span class="hljs-string">"&lt;node_internals&gt;/**"</span>
          ],
          <span class="hljs-string">"program"</span>: <span class="hljs-string">"${file}"</span>
      }
  ]
}
</code></pre>
</li>
<li><p>The program value is generated based on what file is open. The value can be edited to point to the file that starts the API server. </p>
<pre><code class="lang-javascript">{
  <span class="hljs-comment">// Use IntelliSense to learn about possible attributes.</span>
  <span class="hljs-comment">// Hover to view descriptions of existing attributes.</span>
  <span class="hljs-comment">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387</span>
  <span class="hljs-string">"version"</span>: <span class="hljs-string">"0.2.0"</span>,
  <span class="hljs-string">"configurations"</span>: [
      {
          <span class="hljs-string">"type"</span>: <span class="hljs-string">"node"</span>,
          <span class="hljs-string">"request"</span>: <span class="hljs-string">"launch"</span>,
          <span class="hljs-string">"name"</span>: <span class="hljs-string">"Launch Program"</span>,
          <span class="hljs-string">"skipFiles"</span>: [
              <span class="hljs-string">"&lt;node_internals&gt;/**"</span>
          ],
          <span class="hljs-string">"program"</span>: <span class="hljs-string">"api/index.js"</span>
      }
  ]
}
</code></pre>
<h3 id="start-the-debugging-process">Start the debugging process</h3>
<p>Click on the Start Debugging icon. It starts up the server and displays whatever message you wrote to ensure the server is running.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1603498575676/x0llpxT84.gif" alt="start debug.gif" /></p>
<h3 id="make-a-request-to-an-endpoint">Make a request to an endpoint.</h3>
<p>You can make a request with any HTTP method using tools like postman etc.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This article has explained the features of VS code debugger. How to set it up for use in debugging a function and also a web API. VS code also has debuggers for other languages and they are found under extensions by searching for debuggers. Will like to hear from you about other ways you have used the VS code's debugger in the comment section below. Thanks. </p>
]]></content:encoded></item><item><title><![CDATA[What are Microframeworks?]]></title><description><![CDATA[Over the last weekend, I built something simple with Lumen, APIs for onboarding users which included login, and a logged user profile. Coming from an AdonisJs Framework to Laravel and going straight to lumen gave me an experience I never expected, an...]]></description><link>https://princecurie.tech/what-are-microframeworks</link><guid isPermaLink="true">https://princecurie.tech/what-are-microframeworks</guid><category><![CDATA[framework]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Sat, 26 Sep 2020 09:19:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1601111893287/bBRD6YPe5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the last weekend, I built something simple with Lumen, APIs for onboarding users which included login, and a logged user profile. Coming from an AdonisJs Framework to Laravel and going straight to lumen gave me an experience I never expected, and then I saw the term microframeworks on the Lumen web page for the first time. 
This article answers some questions, what are microframeworks? When can it be used? And what examples of microframeworks exist?  </p>
<h3 id="what-are-microframeworks">What are microframeworks?</h3>
<p>Judging from the term "micro" we might say an extremely small framework, and this shows that it is smaller than a framework in scope or capacity. So this means that a microframework can be a framework without its own template engine, database abstraction layer, a logger, a body-parser, a validator, an authentication module, etc. </p>
<h3 id="when-to-use-a-microframework">When to use a microframework</h3>
<p>The answer to this question is never a straightforward answer but some things can be put into consideration to help in making the decision to use a microframework.</p>
<ul>
<li><p><strong>Control</strong>: One question to ask is how much control are you willing to have and how much are you willing to surrender, this ranges from you having the choice to pick the different libraries you prefer for the project as you build instead of being stuck with the one that comes packaged with the framework to selecting the folder structure you desire for your project.</p>
</li>
<li><p><strong>Size</strong>: How big is the project? The answer to this question helps you realise if installing all the packages a framework comes with is necessary, so if I am building APIs that have no interaction with the database, requires no authentication for users, and accepts no user input. Do I need to install a framework that comes bundled with a template engine, a database abstraction layer, a validator, and an authentication library or just one that has a routing library and enables me to make a request and simply returns a response?</p>
</li>
</ul>
<h3 id="examples-of-microframework">Examples of microframework</h3>
<p>Below are a few examples:</p>
<ul>
<li><p>Express: This is a fast Nodejs framework that is used to build web applications. It is very minimalist and a backbone for many frameworks. It gives the users the freedom to fully structure there project the way they want and to select, whatever library the desire and need to accomplish the task before them. To learn more  <a target="_blank" href="http://expressjs.com">follow this link</a> </p>
</li>
<li><p>Lumen: This is a PHP framework that is based on Laravel but made for building APIs and microservices. It gives one the power to use the needed Laravel features with little configuration while been fast. To learn more  <a target="_blank" href="https://lumen.laravel.com">follow this link</a> </p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Wrapping NPM Packages as a Service Provider in AdonisJs]]></title><description><![CDATA[AdonisJs makes creating APIs fun, it makes dependency importing into a file easy with the use global method. It gives the developer a central point to configure their dependencies and bind it to the IOC container. To read about the IOC container  cli...]]></description><link>https://princecurie.tech/wrapping-npm-packages-as-a-service-provider-in-adonisjs</link><guid isPermaLink="true">https://princecurie.tech/wrapping-npm-packages-as-a-service-provider-in-adonisjs</guid><category><![CDATA[Node.js]]></category><category><![CDATA[AdonisJS]]></category><category><![CDATA[twilio]]></category><category><![CDATA[npm]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Sun, 06 Sep 2020 18:44:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1599410111228/CqpYJJ4H3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AdonisJs makes creating APIs fun, it makes dependency importing into a file easy with the <code>use</code> global method. It gives the developer a central point to configure their dependencies and bind it to the IOC container. To read about the IOC container  <a target="_blank" href="https://adonisjs.com/docs/4.1/ioc-container#_binding_dependencies">click here</a>. 
This article will show you how to use AdonisJs service providers to achieve all the benefits mentioned earlier, including configuring different dependencies serving a similar purpose to have a single interface and a central point to switch from one dependency to the other without altering the code.
I will be demonstrating using the Twilio Node.js helper library, I will assume you are already working with AdonisJs but if you need to learn about adonisJs you can follow <a target="_blank" href="https://adonisjs.com/docs/4.1/installation">this link</a> and have a basic understanding of object-oriented programming. </p>
<h2 id="getting-started">Getting Started</h2>
<p>First, we install the Twilio helper library using <code>npm</code>, if you prefer you can use <code>yarn</code>. <code>npm install twilio</code> into the project.</p>
<h2 id="setting-up-configuration">Setting up Configuration</h2>
<p>So we open up the <code>config</code> folder and create a file in it called <code>sms.js</code>. The configuration object will be created in such a way that it can contain various SMS service providers configuration details. The details will be fed from the environment file.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Env = use(<span class="hljs-string">'Env'</span>)

<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-comment">/*
  |--------------------------------------------------------------------------
  | Connection
  |--------------------------------------------------------------------------
  |
  | Connection to be used for sending SMS. 
  | A connection needs to have a corresponding object below.
  |
  */</span>
  connection: Env.get(<span class="hljs-string">'SMS_CONNECTION'</span>),
  sms_sender: Env.get(<span class="hljs-string">'SMS_SENDER'</span>),
  <span class="hljs-comment">/*
  |--------------------------------------------------------------------------
  | TWILIO
  |--------------------------------------------------------------------------
  |
  | Here we define the configuration for sending SMS via TWILIO.
  |
  */</span>
  twilio: {
    driver: <span class="hljs-string">'twilio'</span>,
    accountSid: Env.get(<span class="hljs-string">'TWILIO_SMS_ACCOUNTS_ID'</span>),
    auth_token: Env.get(<span class="hljs-string">'TWILIO_SMS_AUTH_TOKEN'</span>)
  },
}
</code></pre>
<p>The <code>connection</code> determines which SMS service provider the system is using, <code>sms_sender</code> defines the number sending the SMS, <code>twilio</code> is the object containing the configuration details for the Twilio SMS service provider, any other service provider needed can be configured by adding the configuration object like the <code>twilio</code> object.</p>
<h2 id="setting-up-the-providers-folder">Setting up the Providers Folder</h2>
<p>The <code>providers</code> folder will contain all providers and will live in the root of your app. In the <code>providers</code> folder we create a folder called Sms, here is where all the magic will happen.</p>
<pre><code>|<span class="hljs-comment">-- app</span>
| |<span class="hljs-comment">--config</span>
| |<span class="hljs-comment">-- providers</span>
|   |<span class="hljs-comment">-- sms</span>
| |<span class="hljs-comment">-- start</span>
</code></pre><h2 id="setting-the-source-folder">Setting the Source folder</h2>
<p>In the newly created <code>providers/sms</code> folder, we need to have a folder where the code interacts with the npm package. the folder will be named <code>src</code>, which will contain an <code>index.js</code> file and other files for the different SMS service providers. In this demo, we will call it a <code>Twilio.js</code> file which will contain the class that interacts with the Twilio node.js helper function.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Twilio = <span class="hljs-built_in">require</span>(<span class="hljs-string">'twilio'</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TwilioDriver</span> </span>{
  <span class="hljs-keyword">constructor</span> (config, sender) {
    <span class="hljs-keyword">this</span>.config = config
    <span class="hljs-keyword">this</span>.messageBody = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">this</span>.sendTo = <span class="hljs-literal">null</span>
    <span class="hljs-keyword">this</span>.sender = sender
  }

  to (to) {
    <span class="hljs-keyword">this</span>.sendTo = to
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>
  }

  body (body) {
    <span class="hljs-keyword">this</span>.messageBody = body
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>
  }

  <span class="hljs-keyword">async</span> sendSms () {
    <span class="hljs-keyword">const</span> client = Twilio (<span class="hljs-keyword">this</span>.config.accountSid, <span class="hljs-keyword">this</span>.config.auth_token)

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> client.messages.create ({
      body: <span class="hljs-keyword">this</span>.messageBody,
      <span class="hljs-keyword">from</span>: <span class="hljs-keyword">this</span>.sender,
      to: <span class="hljs-keyword">this</span>.sendTo
    })
  }
}

<span class="hljs-built_in">module</span>.exports = TwilioDriver
</code></pre>
<p>Next, we create an <code>index.js</code> file in the <code>src</code> folder, the file will <code>require</code> other files in the <code>src</code> folder, pass it into an object and export the object. The <code>index.js</code> file will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {
  twilio: <span class="hljs-built_in">require</span>(<span class="hljs-string">'./Twilio'</span>)
}
</code></pre>
<h2 id="creating-the-service-provider-index-file">Creating the Service Provider index file</h2>
<p>This file takes in the <code>config</code> file and the <code>index.js</code> file from the <code>src</code> folder, it will reside in the <code>Sms</code> folder. It takes in the connection property of the <code>config</code> file and decides which SMS service provider to instantiate.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Driver = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./src'</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sms</span> </span>{
  <span class="hljs-keyword">constructor</span> (Config) {
    <span class="hljs-keyword">this</span>.Config = Config
  }

  prepare () {
    <span class="hljs-comment">/**
     * Read connection name using Config
     * provider
     */</span>

    <span class="hljs-keyword">const</span> SmsConfig = <span class="hljs-keyword">this</span>.Config.get(<span class="hljs-string">'sms'</span>)
    <span class="hljs-keyword">const</span> name = SmsConfig.connection
    <span class="hljs-keyword">const</span> sender = SmsConfig.sms_sender
    <span class="hljs-keyword">const</span> config = SmsConfig[name]

    <span class="hljs-keyword">const</span> SmsDriver = Driver[name]


    <span class="hljs-comment">/**
     * Return the instance back
     */</span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SmsDriver (config, sender)
  }
}

<span class="hljs-built_in">module</span>.exports = Sms
</code></pre>
<h2 id="binding-to-the-ioc-container">BInding to the IOC container</h2>
<p>Here we use service provider to bind all our previous work to the IOC container. The service provider is a class we extend, it comes with a register and a boot method but we only need to use the register method. In the register method, the configuration from the <code>config</code> file is passed into the <code>Sms</code> class located in the <code>sms/index.js</code> file. The first parameter of this.app.bind defines the name used to address the provider when importing it later for use.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { ServiceProvider } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@adonisjs/fold'</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SmsProvider</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ServiceProvider</span> </span>{
  register () {
    <span class="hljs-keyword">this</span>.app.bind(<span class="hljs-string">'Sms'</span>, () =&gt; {
      <span class="hljs-keyword">const</span> Config = <span class="hljs-keyword">this</span>.app.use(<span class="hljs-string">'Adonis/Src/Config'</span>)
      <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> (<span class="hljs-built_in">require</span>(<span class="hljs-string">'.'</span>))(Config).prepare()
    })
  }
}

<span class="hljs-built_in">module</span>.exports = SmsProvider
</code></pre>
<p><code>this.app</code> references the <code>ioc</code> object, so we can use <code>this.app.bind</code> or <code>this.app.singleton</code> and it will be the same with <code>ioc.bind</code> or <code>ioc.singleton</code> </p>
<h2 id="registering-the-provider">Registering the Provider</h2>
<p>To register the newly created provider, open the <code>app.js</code> file in the <code>start</code> folder in the root of the app.</p>
<ul>
<li>require the path module<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>)
</code></pre>
</li>
<li>Add the path to the new provider in the <code>providers array</code> <pre><code class="lang-javascript"><span class="hljs-keyword">const</span> providers = [
path.join(__dirname, <span class="hljs-string">'..'</span>, <span class="hljs-string">'providers'</span>, <span class="hljs-string">'sms/Provider'</span>),
]
</code></pre>
<h2 id="using-the-provider">Using the Provider</h2>
At this point, we can import the provider into any part of the project using<pre><code class="lang-javascipt">const Sms = use('Sms')
</code></pre>
<h2 id="moving-further">Moving Further</h2>
So if there is a need to use another SMS service provider nodeJs helper library, we add the configuration to the <code>config/Sms.js</code> file, we add the class to interact with the helper library in the <code>providers/sms/src</code> folder to handle it. The class will contain the <code>to</code> method, the <code>body</code> method and the <code>sendSms</code> method. So as not to break existing code. Finally, remember to define the new name of the service provider in the <code>.env</code> file and let it be the name of one of the properties in the  <code>config/Sms.js</code> file holding a configuration object.</li>
</ul>
<p>In conclusion, we have seen have to configure an NPM package as a service provider for AdonisJs, the principles remain the same and a <code>Provider.js</code> file is always necessary, the rest are  defined based on the needs of the developer.</p>
]]></content:encoded></item><item><title><![CDATA[Handling Exceptions in AdonisJS]]></title><description><![CDATA[One question I think about is "how to best handle exceptions?", I work with AdonisJs version 4.1 and in this article, I will show how AdonisJs makes handling exceptions easy.
What are exceptions?
Exceptions are events that occur and cause the running...]]></description><link>https://princecurie.tech/handling-exceptions-in-adonisjs</link><guid isPermaLink="true">https://princecurie.tech/handling-exceptions-in-adonisjs</guid><category><![CDATA[AdonisJS]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Fri, 28 Aug 2020 01:07:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1598573521485/wJY54Lid2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One question I think about is "how to best handle exceptions?", I work with AdonisJs version 4.1 and in this article, I will show how AdonisJs makes handling exceptions easy.</p>
<h2 id="what-are-exceptions">What are exceptions?</h2>
<p>Exceptions are events that occur and cause the running of a program to be disrupted.
When they occur they bubble to the top of the call stack looking for a handler at each level when one is found, the program continues running from there.
I have always handled exceptions with the <code>try-catch-finally</code> block, so when a program is disrupted in the <code>try</code> block, it gets handled in the <code>catch</code> block, and no matter what happens in the try or catch block the finally block runs. The <code>finally</code> block is optional, leave it out if you have nothing to run after the <code>try-catch</code> block.</p>
<pre><code class="lang-javascript">  <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-comment">// Block of code to be executed</span>
    } <span class="hljs-keyword">catch</span>(error) {
      <span class="hljs-comment">// Handles exceptions</span>
     } <span class="hljs-keyword">finally</span> {
       <span class="hljs-comment">// Runs after no matter the outcome of the code.</span>
    }
  }
</code></pre>
<h2 id="handling-exceptions-in-adonisjs-41">Handling exceptions in AdonisJs 4.1</h2>
<p>AdonisJs following its principle of putting the developer's joy first, have gone ahead to ensure that you worry less about configuration by ensuring that some features come prebuilt so you just have to plug and code. To learn more about AdonisJs, follow this <a target="_blank" href="https://adonisjs.com/">link</a>. 
How does one handle exceptions during an HTTP life cycle in AdonisJs? </p>
<ul>
<li>Firstly, one could use the <code>try-catch</code> block and return an error message in the <code>catch</code> block if an exception is thrown, in any method handling an HTTP request or any other running process.</li>
<li><p>Secondly, AdonisJs comes prebuilt with a global exception handler, which can be configured to match the developer's need, by default it handles all exceptions and displays them in a <a target="_blank" href="https://res.cloudinary.com/adonisjs/image/upload/v1485520687/Screen_Shot_2017-01-27_at_6.07.28_PM_blcaau.png">nice format</a>.
To use the AdonisJs exception handler, run the command, <code>adonis make:handler</code>, once successful a <code>Handler.js</code> file is created in the exceptions folder. It contains an <code>ExceptionHandler</code> class which inherits from the <code>BaseExceptionHandler</code> class. The class contains two methods, the <code>handle</code> method which returns the error message, and the report method which is meant for reporting errors either to the <code>stderr</code> or via an application management tool.
What if I need to create exceptions to handle an error, for example, I need to return a not found error message, then we have to run <code>adonis make:exception notFound</code>, which creates a <code>NotFoundException</code> class in the exceptions folder located in the app folder. The exception class contains only a handle method, though you can add a report method to it and it inherits from the <code>LogicalException</code> class. Then I import the exception into the file where it is needed, <code>const NotFoundException = use('App/Exceptions/NotFoundException')</code>. When there is a need to call the exception, it is called by using <code>throw new NotFoundException()</code> and if you need to pass an error message then it will be <code>throw new NotFoundException('X not found')</code>.
To further handle it you can look at the block of code below.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> handle (error, { request, response }) {
  <span class="hljs-keyword">if</span>(error.name == <span class="hljs-string">'NotFoundException'</span>) {
    <span class="hljs-keyword">return</span> response.status(<span class="hljs-number">404</span>).send({
      status: <span class="hljs-string">'Not Found'</span>, 
      error: error.message <span class="hljs-comment">// or your error message</span>
    })  
  }

<span class="hljs-comment">// To handle other forms of exception/error</span>

  <span class="hljs-keyword">return</span> response.status(<span class="hljs-number">500</span>).send({
    status: <span class="hljs-string">'System Error'</span>, 
    error: <span class="hljs-string">'System encountered an error'</span> <span class="hljs-comment">// or your error message</span>
  })
}
</code></pre>
<p>Or</p>
</li>
</ul>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> NotFoundException = use(<span class="hljs-string">'App/Exceptions/NotFoundException'</span>)

  <span class="hljs-keyword">async</span> handle (error, { request, response }) {
    <span class="hljs-keyword">if</span>(error.name == <span class="hljs-string">'NotFoundException'</span>) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> NotFoundException().handle(error, response)  
    }

  <span class="hljs-comment">// To handle other forms of exception/error</span>

    <span class="hljs-keyword">return</span> response.status(<span class="hljs-number">500</span>).send({
      status: <span class="hljs-string">'System Error'</span>, 
      error: <span class="hljs-string">'System encountered an error'</span> <span class="hljs-comment">// or your error message</span>
    })
  }
</code></pre>
<p>And in the NotFoundException.js file, the handle method will contain</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">async</span> handle (error, response}) {
      <span class="hljs-keyword">return</span> response.status(<span class="hljs-number">404</span>).send({
        status: <span class="hljs-string">'Not Found'</span>, 
        error: error.message <span class="hljs-comment">// or your error message</span>
      })  

  }
</code></pre>
<p>Finally, I hope you enjoy using the adonis exception module on your next projects.</p>
]]></content:encoded></item><item><title><![CDATA[Console.log Alternatives in Production]]></title><description><![CDATA[https://twitter.com/ichtrojan/status/1294026600426635266?s=20
So I saw the tweet above the other day and it caught my attention, what are the alternatives? Why should I use them? Why is it better than console.log?
As developers at the early stage of ...]]></description><link>https://princecurie.tech/consolelog-alternatives-in-production</link><guid isPermaLink="true">https://princecurie.tech/consolelog-alternatives-in-production</guid><category><![CDATA[production]]></category><category><![CDATA[logging]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Onwubiko Chibuike]]></dc:creator><pubDate>Wed, 19 Aug 2020 11:48:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1597813930631/2zvhDNI7x.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/ichtrojan/status/1294026600426635266?s=20">https://twitter.com/ichtrojan/status/1294026600426635266?s=20</a></div>
<p>So I saw the tweet above the other day and it caught my attention, what are the alternatives? Why should I use them? Why is it better than console.log?</p>
<p>As developers at the early stage of learning javascript, console.log was one of the first set of things we learned. While using NodeJs REPL console.log was a quick way to debug. It required no dependencies since it is based on the NodeJs console module and is easy to use</p>
<p>Today, logging can be done for various reasons, like for debugging, error tracking, performance tracking, system usage analyses, and many more.</p>
<p>So it begs the question of why does console.log need alternatives.</p>
<h2 id="why-console-log-alternatives-">Why console.log alternatives?</h2>
<p>Well, we can say because a developer felt like creating a new NPM package but there are other tangible reasons.</p>
<ul>
<li><code>console.log()</code> could not be toggled on/off, it was always on, but also it could be done manually by overwriting the console.log method, the snippet below shows how it is done in production.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span>( process.env.NODE_ENV == <span class="hljs-string">"production"</span> ) {
  <span class="hljs-built_in">console</span>.log = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{};
}
</code></pre>
<ul>
<li>console.log out of the box has no support for direct printing to a file, though this could be done as shown by the snippet below. So calling <code>logger.log('a')</code> will log to the output file and <code>logger.error('a')</code> will log to the error file.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">"fs"</span>);
<span class="hljs-keyword">const</span> output = fs.createWriteStream(<span class="hljs-string">"./logs/output"</span>); 
<span class="hljs-keyword">const</span> error = fs.createWriteStream(<span class="hljs-string">"./logs/error"</span>);

<span class="hljs-keyword">const</span> logger = <span class="hljs-keyword">new</span> Console.log({stdout: output, stderr: error})
</code></pre>
<ul>
<li><p>console.log does not give you the ability to specify what you want to log, at a specific situation, for example, developers need logs for reasons different from that of the QA team, and console.log out of the box does not help with allowing one switch on what to log at a certain scenario</p>
</li>
<li><p>Lastly, console.log is lacking when it comes to giving information pertaining to the data logged like the time of logging, how long it took for the process to run, the log level, basic HTTP information, etc. that exist in some loggers</p>
</li>
</ul>
<h2 id="node-js-logging-libraries">Node.js logging libraries</h2>
<p>What logging modules are available for nodeJs?
We will look at four in no particular order:</p>
<ul>
<li><p>debug: It is a tiny javascript utility modeled after the Node.js debugging technique, works in Node.js and web browsers.
it does not just display the data but adds colors to the output displayed as well as the time in milliseconds spent between two debug calls meaning that if it is passed before a block code and after, when we run the program it returns the amount of time it takes to run the program or the time debug was called. To read more about debug  <a href="https://www.npmjs.com/package/debug">click here</a> </p>
</li>
<li><p>morgan: A Node.js HTTP request logger middleware that can log both to file and also the stdout, it allows you to decide what information to log by using the existing format and also to define yours. To read more about morgan  <a href="https://www.npmjs.com/package/morgan">click here</a></p>
</li>
<li><p>winston: It is designed to be a simple and universal library, that can log to a database, a file, and to the stdout. It can be configured to log to all this at the same time. To read more about winston  <a href="https://www.npmjs.com/package/winston">click here</a>.</p>
</li>
<li><p>pino: A logger that is five times faster than it's alternative according to its benchmark result, it allows you to send its logs to datastores or webpages through the use of its various transport tools. To read more about pino <a href="https://www.npmjs.com/package/pino">click here</a>.</p>
</li>
</ul>
<p>PS. Cover image by <a href="https://pixabay.com/photos/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1209632">Free-Photos</a> from <a href="https://pixabay.com/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=1209632">Pixabay</a></p>
]]></content:encoded></item></channel></rss>