<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ruheni Alex</title>
    <description>The latest articles on DEV Community by Ruheni Alex (@ruheni).</description>
    <link>https://dev.to/ruheni</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F149870%2Fe7530f57-fa25-430c-9cb4-9e7cdf1cd6fe.jpg</url>
      <title>DEV Community: Ruheni Alex</title>
      <link>https://dev.to/ruheni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ruheni"/>
    <language>en</language>
    <item>
      <title>Extend your Platformatic API with Prisma Client</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Fri, 16 Dec 2022 11:22:17 +0000</pubDate>
      <link>https://dev.to/prisma/extend-your-platformatic-api-with-prisma-client-3p92</link>
      <guid>https://dev.to/prisma/extend-your-platformatic-api-with-prisma-client-3p92</guid>
      <description>&lt;p&gt;In this part, you will learn how to extend the auto-generated GraphQL and REST API by Platformatic using &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-client" rel="noopener noreferrer"&gt;Prisma Client&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You will create a GraphQL mutation and a REST API endpoint to increment the views on a post record.&lt;/p&gt;

&lt;p&gt;If you're interested in learning how to use Prisma to model your database schema and auto-generate database migrations when working with Platformatic, refer to &lt;a href="https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib"&gt;part 2&lt;/a&gt; of this series.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: It is recommended you type out the changes over copying and pasting the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Your dev toolbox
&lt;/h3&gt;

&lt;p&gt;To follow along, ensure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js v18 or later&lt;/li&gt;
&lt;li&gt;npm v7 or later&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=Prisma.prisma" rel="noopener noreferrer"&gt;Prisma VSCode Extension&lt;/a&gt; (&lt;em&gt;optional&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client" rel="noopener noreferrer"&gt;Thunder Client VSCode Extension&lt;/a&gt; (&lt;em&gt;optional&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Docker (&lt;em&gt;optional&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you don't have Docker installed, you can set up a free hosted database on &lt;a href="https://railway.app/" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; or install &lt;a href="https://www.postgresql.org/download/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Assumed knowledge
&lt;/h3&gt;

&lt;p&gt;This guide will require you have basic familiarity in the following technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;GraphQL APIs&lt;/li&gt;
&lt;li&gt;REST APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up your Platformatic API
&lt;/h2&gt;

&lt;p&gt;The starting point of this tutorial is &lt;a href="https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib"&gt;part 2&lt;/a&gt; of this series. If you're following along from the previous part, you can jump to Extend the functionality of your API with a plugin section of this guide.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll use the following starter &lt;a href="https://github.com/ruheni/prisma-platformatic/tree/automated-migrations" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. It contains the setup files for a new Platformatic project.&lt;/p&gt;

&lt;p&gt;To get started, clone the repository and checkout to the &lt;a href="https://github.com/ruheni/prisma-platformatic/tree/extend-plugin" rel="noopener noreferrer"&gt;&lt;code&gt;automated-migrations&lt;/code&gt;&lt;/a&gt; branch.&lt;/p&gt;

&lt;p&gt;Clone the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;-b&lt;/span&gt; extend-plugin https://github.com/ruheni/prisma-platformatic.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, perform the following actions to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Navigate to the cloned directory:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd prisma-platformatic
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install dependencies:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file based-off of the &lt;code&gt;.env.example&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start the PostgreSQL database with docker:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you already have an existing database server running locally, update the value of the &lt;code&gt;DATABASE_URL&lt;/code&gt; in the &lt;code&gt;.env&lt;/code&gt; file with your database's user and password values:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL="postgres://&amp;lt;USER&amp;gt;:&amp;lt;PASSWORD&amp;gt;@localhost:5432/blog"
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Connect to your database instance using &lt;code&gt;psql&lt;/code&gt; or your preferred SQL client. Copy and run the following SQL to create a database:&lt;/p&gt;


&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Generate an &lt;code&gt;up&lt;/code&gt; and &lt;code&gt;down&lt;/code&gt; migration:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx db-diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply the &lt;code&gt;up&lt;/code&gt; migration to your database:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx platformatic db migrations apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Populate the database with sample data:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx platformatic db seed seed.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you're following along from the previous part, you can skip this step.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate Prisma Client:
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```
npx prisma generate
```
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Project structure and files
&lt;/h3&gt;

&lt;p&gt;The project has the following structure:&lt;br&gt;
The important files in the directory are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt;: Contains the database connection string for your PostgreSQL database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker-compose.yml&lt;/code&gt;: Defines the Docker image and configuration for your PostgreSQL database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt;: Defines your application dependencies. &lt;a href="http://npmjs.com/package/platformatic" rel="noopener noreferrer"&gt;&lt;code&gt;platformatic&lt;/code&gt;&lt;/a&gt; is currently the only dependency in the project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;platformatic.db.json&lt;/code&gt;: Defines &lt;a href="https://oss.platformatic.dev/docs/reference/service/configuration" rel="noopener noreferrer"&gt;Platformatic's configuration&lt;/a&gt; such as the server's hostname and port, migration directory, and your database's connection string.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seed.js&lt;/code&gt;: Contains a script for populating the database with seed data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;schema.prisma&lt;/code&gt;: Defines the structure of your database schema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;schema.prisma&lt;/code&gt; file contains two models: &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Post&lt;/code&gt;, with a one-to-many relation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Extend the functionality of your API with plugins
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Define the &lt;code&gt;plugin&lt;/code&gt; property in your &lt;code&gt;platformatic.db.json&lt;/code&gt; file
&lt;/h3&gt;

&lt;p&gt;The first step is defining the plugin configuration in your &lt;code&gt;platformatic.db.json&lt;/code&gt; file. Paste the following snippet to in your configuration file right after the &lt;code&gt;migrations&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./plugin.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  Expand to view the entire file
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"server"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"logger"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"info"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3042"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"connectionString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{DATABASE_URL}"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"migrations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./migrations"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"plugin.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;p&gt;The snippet defines the path to your plugin. The plugin will be registered when your server starts, exposing the custom logic you've defined.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a plugin
&lt;/h3&gt;

&lt;p&gt;At the root of your directory, create a new file called &lt;code&gt;plugin.js&lt;/code&gt;. Paste  the following snippet to your plugin file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./plugin.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin loaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file exports an async function with an &lt;code&gt;app&lt;/code&gt; parameter that's a &lt;a href="https://www.fastify.io/docs/latest/Reference/Server/#instance" rel="noopener noreferrer"&gt;&lt;code&gt;FastifyInstance&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you you start up Platformatic with &lt;code&gt;npx platformatic db start&lt;/code&gt;, Platformatic will register the plugin. "plugin loaded" will also be logged to your console.&lt;/p&gt;

&lt;p&gt;With everything set up, let's take a look at how you can extend your API using Prisma Client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extend the GraphQL API
&lt;/h2&gt;

&lt;p&gt;You'll extend the GraphQL API by defining a mutation called &lt;code&gt;incrementPostViewCount&lt;/code&gt;. The mutation will have one argument, &lt;code&gt;id&lt;/code&gt; that is an &lt;code&gt;ID&lt;/code&gt; type. The mutation response type will be a &lt;code&gt;Post&lt;/code&gt; object type.&lt;/p&gt;

&lt;p&gt;To implement the GraphQL mutation, make the following changes to your &lt;code&gt;plugin.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./plugin.js&lt;/span&gt;

&lt;span class="c1"&gt;// 1. &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin loaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;//3.&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extendSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    extend type Mutation {
      incrementPostViewCount(id: ID): Post
    }
  `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;//4.&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineResolvers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;incrementPostViewCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 5. &lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;viewCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="c1"&gt;// 6.&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Post with id:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was not found`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;// 7.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above snippet does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Imports Prisma Client.&lt;/li&gt;
&lt;li&gt;Creates a new instance of Prisma Client.&lt;/li&gt;
&lt;li&gt;Defines the &lt;code&gt;incrementPostViewCount&lt;/code&gt; mutation type definition. It also defines the corresponding argument and the return type.&lt;/li&gt;
&lt;li&gt;Defines the resolver for your mutation.&lt;/li&gt;
&lt;li&gt;Makes a query to the database on the &lt;code&gt;Post&lt;/code&gt; model to increment a post's view count.&lt;/li&gt;
&lt;li&gt;Adds error handling in the event a record with the matching id was not found.&lt;/li&gt;
&lt;li&gt;Returns the updated post on success.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As you're defining the &lt;code&gt;incrementPostMutation&lt;/code&gt; resolver, you will notice Prisma Client provides auto-completion. On hovering on the &lt;code&gt;incrementPostViewCount&lt;/code&gt; resolver and &lt;code&gt;post&lt;/code&gt; variable, VS Code infers the types for you.&lt;/p&gt;

&lt;p&gt;You can head over to &lt;a href="http://localhost:3042/graphiql" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3042/graphiql&lt;/code&gt;&lt;/a&gt; to try out the mutation you just created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INCREMENT_POST_VIEWS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;incrementPostViewCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;viewCount&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  Expand to view the response
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"incrementPostViewCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Prisma 💚 Platformatic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"viewCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;

&lt;h2&gt;
  
  
  Extend the REST API
&lt;/h2&gt;

&lt;p&gt;Next, you'll extend the REST API by defining an endpoint that will accept &lt;code&gt;PUT&lt;/code&gt; requests to increment the views of a post.&lt;/p&gt;

&lt;p&gt;To implement the REST endpoint, update &lt;code&gt;./plugin.js&lt;/code&gt; file with the following snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ./plugin.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin loaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// ...GraphQL API&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. &lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/post/:id/views&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 2. &lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;
    &lt;span class="c1"&gt;// 3. &lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;viewCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;// 4.&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Post with id:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was not found`&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
     &lt;span class="c1"&gt;// 5.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Defines the route for incrementing a post's views.&lt;/li&gt;
&lt;li&gt;Retrieves the &lt;code&gt;id&lt;/code&gt; from the request parameters.&lt;/li&gt;
&lt;li&gt;Makes a query to the database on the &lt;code&gt;Post&lt;/code&gt; model to increment the post's view count.&lt;/li&gt;
&lt;li&gt;Adds error handling in the event a record with the matching id was not found.&lt;/li&gt;
&lt;li&gt;Returns the updated post on success.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
  Expand to see the diff
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;const { PrismaClient } = require("@prisma/client")
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;const prisma = new PrismaClient()
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;module.exports = async (app) =&amp;gt; {
&lt;/span&gt;  app.log.info('plugin loaded')
&lt;span class="err"&gt;
&lt;/span&gt;  app.graphql.extendSchema(`
    extend type Mutation {
      incrementPostViewCount(id: ID): Post
    }
  `)
&lt;span class="err"&gt;
&lt;/span&gt;  //4.
  app.graphql.defineResolvers({
    Mutation: {
      incrementPostViewCount: async (_, { id }) =&amp;gt; {
        // 5. 
        const post = await prisma.post.update({
          where: {
            id: Number(id)
          },
          data: {
            viewCount: {
              increment: 1
            }
          }
        })
&lt;span class="err"&gt;
&lt;/span&gt;        // 6.
        if (!post) throw new Error(`Post with id:${id} was not found`)
        // 7.
        return post
      }
    }
  })
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+  // 1. 
+  app.put('/post/:id/views', async (req, reply) =&amp;gt; {
+    // 2.
+    const { id } = req.params
+    // 3.
+    const post = await prisma.post.update({
+      where: {
+        id: Number(id)
+      },
+      data: {
+        viewCount: {
+          increment: 1
+        }
+      }
+    })
+    // 4. 
+    if (!post) reply.code(404).send({ error: `Post with id:${id} was not found` })
+    // 5. 
+    return reply.send(post)
+  })
&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;br&gt;
You can head over to &lt;a href="http://localhost:3042/documentation" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3042/documentation&lt;/code&gt;&lt;/a&gt; to view the Swagger docs. You should see the endpoint you just created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F204011764-c569e9a4-96f2-47dd-bdeb-9c29bd52d964.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F204011764-c569e9a4-96f2-47dd-bdeb-9c29bd52d964.png" alt="Platformatic  auto-generated Swagger documentation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To try out the endpoint you just created, you can make a request to your endpoint using &lt;code&gt;curl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X PUT \
  'localhost:3042/post/2/views' \
  --header 'Accept: */*' \
  --header 'Content-Type: application/json' 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use Thunder Client on VS Code to run the request. To make a request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open up Thunder Client on VS Code.&lt;/li&gt;
&lt;li&gt;Create a new request by clicking &lt;strong&gt;New Request&lt;/strong&gt; button on the side bar.&lt;/li&gt;
&lt;li&gt;Select the &lt;code&gt;PUT&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;Enter it to the following URL: &lt;code&gt;http://localhost:3042/post/1/views&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Send&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should see the following output on your editor:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F204013519-a088f09e-586b-4f25-b8cd-68d194133cbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F204013519-a088f09e-586b-4f25-b8cd-68d194133cbd.png" alt="Thunder Client  raw `PUT` endraw  request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap and next steps
&lt;/h2&gt;

&lt;p&gt;Congratulations! 🎉&lt;br&gt;
Using Prisma Client, you've successfully extended the GraphQL and REST APIs generated with Platformatic API.&lt;/p&gt;

&lt;p&gt;In case you missed it, check out &lt;a href="https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib"&gt;part 2&lt;/a&gt; to learn how you can use Prisma to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model your database schema&lt;/li&gt;
&lt;li&gt;Auto-generate fully customizable SQL migrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the source code for this project on &lt;a href="https://github.com/ruheni/platformatic-prisma" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you run into any challenges, feel free to create a GitHub issue or contribute to the repository. You can also reach out to me directly on &lt;a href="https://twitter.com/ruheni_alex" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>prisma</category>
      <category>platformatic</category>
    </item>
    <item>
      <title>Friendly data modeling &amp; auto-generated, editable migrations for Platformatic with Prisma</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Thu, 15 Dec 2022 09:38:54 +0000</pubDate>
      <link>https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib</link>
      <guid>https://dev.to/prisma/friendly-data-modeling-auto-generated-editable-migrations-for-platformatic-with-prisma-dib</guid>
      <description>&lt;p&gt;A wise man once said...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F194832698-08959b77-9490-48ec-91c4-15f8fd9c6dc5.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F194832698-08959b77-9490-48ec-91c4-15f8fd9c6dc5.jpeg" alt="automate-all-the-things"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;... that was me.&lt;/p&gt;

&lt;p&gt;But all jokes and memes aside, automation helps cut down the amount of time spent on tedious and repetitive tasks.&lt;/p&gt;

&lt;p&gt;This guide will teach you how to model your database schema and auto-generate customizable SQL migrations using &lt;a href="https://www.prisma.io" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; when working with Platformatic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Your dev toolbox
&lt;/h3&gt;

&lt;p&gt;To follow along, ensure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js  v16.17.0&lt;/li&gt;
&lt;li&gt;npm v7 or later&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=Prisma.prisma" rel="noopener noreferrer"&gt;Prisma VSCode Extension&lt;/a&gt; (&lt;em&gt;optional&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client" rel="noopener noreferrer"&gt;Thunder Client VSCode Extension&lt;/a&gt;  (&lt;em&gt;optional&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Docker (&lt;em&gt;optional&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you don't have Docker installed, you can set up a free hosted database on &lt;a href="https://railway.app/" rel="noopener noreferrer"&gt;Railway&lt;/a&gt; or install &lt;a href="https://www.postgresql.org/download/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Assumed knowledge
&lt;/h3&gt;

&lt;p&gt;This guide will require you to have basic familiarity with the following technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;GraphQL APIs&lt;/li&gt;
&lt;li&gt;REST APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up your Platformatic app
&lt;/h2&gt;

&lt;p&gt;In this tutorial, you'll use the following starter &lt;a href="https://github.com/ruheni/prisma-platformatic/tree/automated-migrations" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. It contains the setup files for a new Platformatic project.&lt;/p&gt;

&lt;p&gt;To get started, clone the repository and checkout to the &lt;a href="https://github.com/ruheni/prisma-platformatic/tree/automated-migrations" rel="noopener noreferrer"&gt;&lt;code&gt;automated-migrations&lt;/code&gt;&lt;/a&gt; branch.&lt;/p&gt;

&lt;p&gt;Clone the repository:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

git clone &lt;span class="nt"&gt;-b&lt;/span&gt; automated-migrations https://github.com/ruheni/prisma-platformatic.git


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, perform the following actions to get started:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Navigate to the cloned directory:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd prisma-platformatic
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
1. Install dependencies:

    ```bash


    npm install


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file based-off of the &lt;code&gt;.env.example&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cp .env.example .env
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
1. Start the PostgreSQL database with docker:

    ```


    docker-compose up -d


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you already have an existing database server running locally, update the value of the &lt;code&gt;DATABASE_URL&lt;/code&gt; in your &lt;code&gt;.env&lt;/code&gt; file with your database's user and password values:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# .env
DATABASE_URL="postgres://&amp;lt;USER&amp;gt;:&amp;lt;PASSWORD&amp;gt;@localhost:5432/blog"


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Connect to your database instance using &lt;code&gt;psql&lt;/code&gt; or your preferred SQL client. Copy and run the following SQL to create a database:&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Project structure and files
&lt;/h3&gt;

&lt;p&gt;The project has the following structure:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

prisma-platformatic
  ├── .env.example
  ├── .env
  ├── .gitignore
  ├── README.md
  ├── docker-compose.yml
  ├── package-lock.json
  ├── package.json
  └── platformatic.db.json


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The noteworthy files in the directory are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt;: Contains the database connection string for your PostgreSQL database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker-compose.yml&lt;/code&gt;: Defines the Docker image and configuration for your PostgreSQL database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt;: Defines your application dependencies. &lt;a href="http://npmjs.com/package/platformatic" rel="noopener noreferrer"&gt;&lt;code&gt;platformatic&lt;/code&gt;&lt;/a&gt; is currently the only dependency in the project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;platformatic.db.json&lt;/code&gt;: Defines &lt;a href="https://oss.platformatic.dev/docs/reference/service/configuration" rel="noopener noreferrer"&gt;Platformatic's configuration&lt;/a&gt; such as the server's hostname and port, migration directory, and your database's connection string.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data modeling and automated migrations
&lt;/h2&gt;

&lt;p&gt;Now that you've set up your application, it's time to get your hands dirty with Prisma!&lt;/p&gt;

&lt;h3&gt;
  
  
  Set Prisma in your project
&lt;/h3&gt;

&lt;p&gt;To get started, first install the &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference" rel="noopener noreferrer"&gt;Prisma CLI&lt;/a&gt; as a development dependency in your project:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install prisma --save-dev


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Prisma CLI provides the tools that allow you to evolve your database schema in your project.&lt;/p&gt;

&lt;p&gt;You can now initialize Prisma in your project with the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx prisma init


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The command creates a &lt;code&gt;prisma&lt;/code&gt; folder at the root containing a &lt;code&gt;schema.prisma&lt;/code&gt; file. The &lt;code&gt;schema.prisma&lt;/code&gt; file serves as a source of truth for your database schema.&lt;/p&gt;

&lt;p&gt;When you open up the &lt;code&gt;schema.prisma&lt;/code&gt; file, you should see the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// prisma/schema.prisma&lt;/span&gt;
&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"prisma-client-js"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"postgres"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The Prisma schema uses an intuitive and human-readable language called the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema#syntax" rel="noopener noreferrer"&gt;&lt;em&gt;Prisma Schema language&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The schema file is composed of three main components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data source&lt;/strong&gt;: Defines your database connection details such as the provider and database's connection string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generator&lt;/strong&gt;: Defines the &lt;em&gt;assets&lt;/em&gt; generated when specific Prisma commands are invoked. In this case, Prisma Client, a type-safe query builder for your database, will be generated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data model&lt;/strong&gt;: Defines the entities of your application that map to your database's tables (for relational databases) or collections (MongoDB). The schema doesn't have any yet, but models are denoted with the &lt;code&gt;model&lt;/code&gt; keyword, followed by the entity name.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Model your database schema
&lt;/h3&gt;

&lt;p&gt;For this guide, you will create a &lt;code&gt;Post&lt;/code&gt; model with the following fields in your &lt;code&gt;schema.prisma&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// ./prisma/schema.prisma&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;        &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@id&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt;     &lt;span class="n"&gt;String&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt;   &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;published&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;viewCount&lt;/span&gt; &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The snippet above defines a model called &lt;code&gt;Post&lt;/code&gt; with the following fields and properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: An auto-incrementing integer that will be the primary key for the model.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt;: A non-null &lt;code&gt;String&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;content&lt;/code&gt;: A nullable &lt;code&gt;String&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;published&lt;/code&gt;: A &lt;code&gt;Boolean&lt;/code&gt; field with a default value of &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;viewCount&lt;/code&gt;: An &lt;code&gt;Int&lt;/code&gt; field with a default value of &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createdAt&lt;/code&gt;: A &lt;code&gt;DateTime&lt;/code&gt; field with a timestamp of when the value is created as its default value.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Refer to the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/data-model" rel="noopener noreferrer"&gt;Prisma documentation&lt;/a&gt; for further details on how to model your data using Prisma.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Generate a migration with &lt;code&gt;migrate diff&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;With the schema defined, you will now auto-generate a database migration using &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference#migrate-diff" rel="noopener noreferrer"&gt;&lt;code&gt;prisma migrate diff&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;prisma migrate diff&lt;/code&gt; compares (or "diffs") two schemas, the &lt;em&gt;current&lt;/em&gt;, and the &lt;em&gt;anticipated&lt;/em&gt; version. The current version is the &lt;em&gt;from&lt;/em&gt; state, and the anticipated version is the &lt;em&gt;to&lt;/em&gt; state. The command generates a SQL script describing the changes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun fact: If you've used the &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference#migrate-dev" rel="noopener noreferrer"&gt;&lt;code&gt;prisma migrate dev&lt;/code&gt;&lt;/a&gt; command before, it runs &lt;code&gt;prisma migrate diff&lt;/code&gt; under the hood.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The command, &lt;code&gt;prisma migrate diff&lt;/code&gt; accepts the following schema sources for comparison:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A live database&lt;/li&gt;
&lt;li&gt;A migration history&lt;/li&gt;
&lt;li&gt;Schema data model (defined in the Prisma schema)&lt;/li&gt;
&lt;li&gt;An empty schema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;prisma migrate diff&lt;/code&gt; command will use the following arguments to generate a migration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--from-schema-datasource&lt;/code&gt;: Uses the URL defined in the &lt;code&gt;datasource&lt;/code&gt; block.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--to-schema-datamodel&lt;/code&gt;: Uses the data model defined in the Prisma schema for the diff.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--script&lt;/code&gt; (&lt;em&gt;optional&lt;/em&gt;): Outputs a SQL script.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;--from-schema-datasource&lt;/code&gt; and &lt;code&gt;--to-schema-datamodel&lt;/code&gt; also require a path to your Prisma schema file.&lt;/p&gt;

&lt;p&gt;Create the &lt;code&gt;migrations&lt;/code&gt; directory that you will use to store a history of migrations:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mkdir migrations


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;migrations&lt;/code&gt; directory is used by Platformatic to store and track the history of applied migrations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, open up a terminal within your project directory run the following command to auto-generate your first migration:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx prisma migrate diff &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--from-schema-datasource&lt;/span&gt; ./prisma/schema.prisma &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--to-schema-datamodel&lt;/span&gt; ./prisma/schema.prisma &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--script&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; migrations/001.do.sql &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--exit-code&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the output filename for any future migrations to prevent overwriting the contents of &lt;code&gt;001.do.sql&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You can jump to the &lt;strong&gt;Side quest&lt;/strong&gt; section to learn how you can automate versioning and generating migrations with the &lt;a href="https://github.com/ruheni/db-diff" rel="noopener noreferrer"&gt;&lt;code&gt;@ruheni/db-diff&lt;/code&gt;&lt;/a&gt; utility library&lt;/li&gt;
&lt;li&gt;If you omit the &lt;code&gt;--script&lt;/code&gt; argument, the command will generate a human-readable summary that looks something like this:
```
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;[+] Added tables&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Post&lt;/li&gt;
&lt;/ul&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;The command creates a file called &lt;code&gt;001.do.sql&lt;/code&gt; inside the &lt;code&gt;migrations&lt;/code&gt; directory with the following contents:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;

&lt;span class="c1"&gt;-- migrations/001.do.sql&lt;/span&gt;
&lt;span class="c1"&gt;-- CreateTable&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Post"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"createdAt"&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"title"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"content"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"published"&lt;/span&gt; &lt;span class="nb"&gt;BOOLEAN&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"viewCount"&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"Post_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You'll notice that the command generated the SQL that describes the changes you defined in the Prisma schema file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start your API server
&lt;/h2&gt;

&lt;p&gt;In your project directory, apply the migrations to your database using the Platformatic CLI:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx platformatic db migrations apply


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, start up your API server:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx platformatic db start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The command will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start the Platformatic API server&lt;/li&gt;
&lt;li&gt;Auto-generate a REST and GraphQL API from your SQL database&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Explore and interact with your API
&lt;/h3&gt;

&lt;p&gt;You can now explore your GraphQL API on &lt;a href="http://localhost:3042/graphiql" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3042/graphiql&lt;/code&gt;&lt;/a&gt; or your REST API on &lt;a href="http://localhost:3042/documentation" rel="noopener noreferrer"&gt;&lt;code&gt;http://localhost:3042/documentation&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run the following mutation on GraphiQL to insert a record in your database:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INSERT_POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;insertPost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Prisma 💚 Platformatic"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn how you can auto-generate your database migrations using Prisma for Platformatic"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;createdAt&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;published&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You should see the following output with a different &lt;code&gt;createdAt&lt;/code&gt; value:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"insertPost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Prisma 💚 Platformatic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn how you can auto-generate your database migrations using Prisma for Platformatic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-10-08T14:26:08.101Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"published"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Congratulations! 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Introspect your database for the &lt;code&gt;versions&lt;/code&gt; model
&lt;/h3&gt;

&lt;p&gt;Under the hood, Platformatic uses &lt;a href="https://www.npmjs.com/package/postgrator" rel="noopener noreferrer"&gt;Postgrator&lt;/a&gt; to run migrations. Postgrator creates a table in the database called &lt;code&gt;versions&lt;/code&gt; to track the applied migrations.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;versions&lt;/code&gt; table is not yet captured in the Prisma schema. When auto-generating future migrations, Prisma might prompt you to drop the &lt;code&gt;versions&lt;/code&gt; table, which is not ideal.&lt;/p&gt;

&lt;p&gt;To prevent this, you can run &lt;code&gt;prisma db pull&lt;/code&gt; to introspect the database and populate the Prisma schema with the missing model:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx prisma db pull


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your Prisma schema should now contain a &lt;code&gt;version&lt;/code&gt; model:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;// ./prisma/schema.prisma
&lt;span class="p"&gt;model Post {
&lt;/span&gt;  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  viewCount Int      @default(0)
  createdAt DateTime @default(now())
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+model versions {
+  version BigInt    @id
+  name    String?
+  md5     String?
+  run_at  DateTime? @db.Timestamptz(6)
+}
&lt;/span&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the &lt;code&gt;@@ignore&lt;/code&gt; attribute function to the model to exclude it from the Prisma Client API:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;// ./prisma/schema.prisma
&lt;span class="p"&gt;model Post {
&lt;/span&gt;  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  viewCount Int      @default(0)
  createdAt DateTime @default(now())
}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;model versions {
&lt;/span&gt;  version BigInt    @id
  name    String?
  md5     String?
  run_at  DateTime? @db.Timestamptz(6)
&lt;span class="gi"&gt;+
+  @@ignore
&lt;/span&gt;}
&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Side quest 🧙🏽: Automate versioning and generation of your database migrations
&lt;/h2&gt;

&lt;p&gt;The approach for generating migrations in the previous section generally works fine. The only caveat is that you have to manually specify the version of the migration file with every migration, i.e., &lt;code&gt;001.do.sql&lt;/code&gt;, &lt;code&gt;002.do.sql&lt;/code&gt;, and so forth.&lt;/p&gt;

&lt;p&gt;Another friction point is that the command is very long, tedious and there is a possibility of making an error.&lt;/p&gt;

&lt;p&gt;To get around these friction points, I built a utility library called &lt;a href="https://github.com/ruheni/db-diff" rel="noopener noreferrer"&gt;&lt;code&gt;@ruheni/db-diff&lt;/code&gt;&lt;/a&gt;. The tool wraps around the &lt;code&gt;prisma migrate diff&lt;/code&gt; command. It can generate an &lt;code&gt;up&lt;/code&gt; and a &lt;code&gt;down&lt;/code&gt; migration. &lt;code&gt;@ruheni/db-diff&lt;/code&gt; also versions the generated migration file and are Postgrator-compatible. On top of that, you can generate an up and down migration for every schema change.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Alternatively, you can also use &lt;a href="https://github.com/kgajera/platformatic-prisma" rel="noopener noreferrer"&gt;&lt;code&gt;platformatic-prisma&lt;/code&gt;&lt;/a&gt; by &lt;a href="https://twitter.com/kgajera24" rel="noopener noreferrer"&gt;Kishan Gajera&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Install the helper utility
&lt;/h3&gt;

&lt;p&gt;To get started, you can install &lt;code&gt;@ruheni/db-diff&lt;/code&gt; as a development dependency in your project:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install --save-dev @ruheni/db-diff


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Update your schema
&lt;/h3&gt;

&lt;p&gt;Next, update your Prisma schema by creating a &lt;code&gt;User&lt;/code&gt; model with the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: the primary key with an auto-incrementing integer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;email&lt;/code&gt;: a string value with a &lt;code&gt;@unique&lt;/code&gt; constraint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: a string value (nullable/ not-required)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;posts&lt;/code&gt;: a one-to-many relationship between the &lt;code&gt;Post&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; models, respectively&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your Prisma schema should resemble the schema in the code block below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// ./prisma/schema.prisma&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;    &lt;span class="n"&gt;Int&lt;/span&gt;     &lt;span class="nd"&gt;@id&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;  &lt;span class="nd"&gt;@unique&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;  &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;        &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@id&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt;     &lt;span class="n"&gt;String&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt;   &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;published&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;viewCount&lt;/span&gt; &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;author&lt;/span&gt;    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;    &lt;span class="nd"&gt;@relation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fields:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;authorId&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="nl"&gt;references:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
  &lt;span class="n"&gt;authorId&lt;/span&gt;  &lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;versions&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="n"&gt;BigInt&lt;/span&gt;    &lt;span class="nd"&gt;@id&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;    &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;md5&lt;/span&gt;     &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;run_at&lt;/span&gt;  &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nd"&gt;@db.Timestamptz&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;@ignore&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;
  Expand here to see the schema diff
  &lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;// ./prisma/schema.prisma
&lt;span class="gi"&gt;+model User {
+  id    Int     @id @default(autoincrement())
+  email String  @unique
+  name  String?
+  posts Post[]
+}
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;model Post {
&lt;/span&gt;  id        Int      @id @default(autoincrement())
  createdAt DateTime @default(now())
  title     String
  content   String?
  published Boolean  @default(false)
  viewCount Int      @default(0)
&lt;span class="gi"&gt;+  author    User?    @relation(fields: [authorId], references: [id])
+  authorId  Int?
&lt;/span&gt;}
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;model versions {
&lt;/span&gt;  version BigInt    @id
  name    String?
  md5     String?
  run_at  DateTime? @db.Timestamptz(6)
&lt;span class="err"&gt;
&lt;/span&gt;  @@ignore
}
&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;/p&gt;

&lt;h3&gt;
  
  
  Auto-generate an &lt;code&gt;up&lt;/code&gt; migration using &lt;code&gt;@ruheni/db-diff&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Next, use &lt;code&gt;@ruheni/db-diff&lt;/code&gt; to auto-generate an &lt;code&gt;up&lt;/code&gt; migration:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx db-diff --up


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The command should generate a new file called &lt;code&gt;002.do.sql&lt;/code&gt; with the following contents:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;

&lt;span class="c1"&gt;-- migrations/002.do.sql&lt;/span&gt;
&lt;span class="c1"&gt;-- AlterTable&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Post"&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt;     &lt;span class="nv"&gt;"authorId"&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateTable&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"email"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"name"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"User_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateIndex&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="nv"&gt;"User_email_key"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- AddForeignKey&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Post"&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"Post_authorId_fkey"&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"authorId"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can specify the type of migration you would like to generate by passing either &lt;code&gt;--up&lt;/code&gt; for only the &lt;code&gt;up&lt;/code&gt; migration or &lt;code&gt;--down&lt;/code&gt; for the down migration.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@ruheni/db-diff&lt;/code&gt; utility library will auto-generate an up and a down migration if you don't provide either the &lt;code&gt;--up&lt;/code&gt; or &lt;code&gt;--down&lt;/code&gt; flags. If you maintain down migrations, ensure the migration version name is at par with the up migration.&lt;/p&gt;

&lt;p&gt;Apply the generated migration using Platformatic CLI:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx platformatic db migrations apply


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Restart and interact with your API using Platformatic
&lt;/h3&gt;

&lt;p&gt;Restart the API server:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx platformatic db start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Platformatic will regenerate the GraphQL and REST APIs.&lt;/p&gt;

&lt;p&gt;Open up GraphiQL on &lt;code&gt;http://localhost:3042/graphiql&lt;/code&gt; and run the following mutation to create a user record in your database:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INSERT_USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;insertUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alex@prisma.io"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;
  Expand to view the response
  &lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"insertUser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alex"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;/p&gt;

&lt;p&gt;Run another query to link the user record with the existing post record you created in a previous step:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;mutation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SAVE_POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;savePost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authorId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;
  Expand to view the response
  &lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"savePost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Prisma 💚 Platformatic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Learn how you can auto-generate your database migrations using Prisma for Platformatic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alex"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;/p&gt;

&lt;p&gt;And you're all done! 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;To recap what was covered in this part, you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modeled your database schema using Prisma&lt;/li&gt;
&lt;li&gt;Used the &lt;code&gt;prisma migrate diff&lt;/code&gt; to auto-generate your SQL migrations&lt;/li&gt;
&lt;li&gt;Created a GraphQL and REST API using Platformatic&lt;/li&gt;
&lt;li&gt;Used the &lt;code&gt;@ruheni/db-diff&lt;/code&gt; utility to auto-generate and version your SQL migrations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next article will cover how you can extend the generated GraphQL and REST API using Prisma Client.&lt;/p&gt;

&lt;p&gt;Feel free to refer to &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference#migrate-diff" rel="noopener noreferrer"&gt;&lt;code&gt;prisma migrate diff&lt;/code&gt; reference docs&lt;/a&gt; to learn how you can use it to automate your database migration workflows. If you build something cool you would like to share with the rest of the world, feel free to share it in this &lt;a href="https://github.com/prisma/prisma/discussions/14101" rel="noopener noreferrer"&gt;GitHub discussion thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the event you run into any issues working with &lt;a href="https://github.com/ruheni/db-diff" rel="noopener noreferrer"&gt;&lt;code&gt;@ruheni/db-diff&lt;/code&gt;&lt;/a&gt;, feel free to &lt;a href="https://github.com/ruheni/db-diff/issues/new" rel="noopener noreferrer"&gt;create a GitHub issue&lt;/a&gt; or contribute to the library.&lt;/p&gt;

&lt;p&gt;Happy hacking! 🚀&lt;/p&gt;

</description>
      <category>node</category>
      <category>prisma</category>
      <category>database</category>
      <category>migrations</category>
    </item>
    <item>
      <title>Why Prisma and Platformatic are a great match</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Wed, 14 Dec 2022 11:27:35 +0000</pubDate>
      <link>https://dev.to/prisma/why-prisma-and-platformatic-are-a-great-match-2dkl</link>
      <guid>https://dev.to/prisma/why-prisma-and-platformatic-are-a-great-match-2dkl</guid>
      <description>&lt;p&gt;&lt;a href="https://oss.platformatic.dev/" rel="noopener noreferrer"&gt;Platformatic&lt;/a&gt; is a new tool that helps Node.js developers ship APIs faster. In this 3-part series, we’ll explore why &lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt; and Platformatic are such a great fit and how Prisma can help improve your data modeling, migrations, and querying workflows when using Platformatic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Platformatic DB
&lt;/h2&gt;

&lt;p&gt;Platformatic DB is an open-source tool that auto-generates CRUD APIs for your database. It supports both GraphQL and REST (with an OpenAPI schema) APIs. &lt;/p&gt;

&lt;p&gt;It also allows you to extend the API using &lt;a href="https://oss.platformatic.dev/docs/reference/db/plugin" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; and add authentication as well as authorization for your APIs. Platformatic DB supports SQLite, MySQL, MariaDB, and PostgreSQL databases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Prisma
&lt;/h2&gt;

&lt;p&gt;Prisma is an open-source ORM (Object Relational Mapper). It provides a declarative way to define the structure of your database using the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema" rel="noopener noreferrer"&gt;Prisma schema language&lt;/a&gt;. It also provides tools for evolving your database schema by auto-generating fully customizable SQL migrations.&lt;/p&gt;

&lt;p&gt;Prisma provides a type-safe and intuitive client for interacting with your database called &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-client" rel="noopener noreferrer"&gt;Prisma Client&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Prisma can improve your development workflow with Platformatic DB
&lt;/h2&gt;

&lt;p&gt;While Platformatic speeds up building REST and GraphQL APIs from your database, Prisma can complement your development workflow in several ways.&lt;/p&gt;

&lt;p&gt;In the following sections, we'll explore three concrete ways Prisma makes working with Platformatic DB easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intuitive data modeling language
&lt;/h3&gt;

&lt;p&gt;Prisma provides a Prisma schema — an intuitive, human-readable declarative definition of your database schema. The Prisma schema serves as the source of truth for your database schema by describing its desired end state.&lt;/p&gt;

&lt;p&gt;One of the benefits of using the Prisma schema is the auto-completion, with the help of the Prisma extension, and type-checking when modeling your database schema, allowing you to catch errors early.&lt;/p&gt;

&lt;p&gt;The following schema represents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Post&lt;/code&gt; models&lt;/li&gt;
&lt;li&gt;A one-to-many relationship between the &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Post&lt;/code&gt; models
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;        &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@id&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;      &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt;     &lt;span class="n"&gt;String&lt;/span&gt;   &lt;span class="nd"&gt;@unique&lt;/span&gt;

  &lt;span class="n"&gt;posts&lt;/span&gt;     &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;        &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@id&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt;     &lt;span class="n"&gt;String&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt;   &lt;span class="n"&gt;String&lt;/span&gt;
  &lt;span class="n"&gt;published&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;  &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;author&lt;/span&gt;    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;    &lt;span class="nd"&gt;@relation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fields:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;authorId&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="nl"&gt;references:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
  &lt;span class="n"&gt;authorId&lt;/span&gt;  &lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Refer to the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/data-model" rel="noopener noreferrer"&gt;Prisma docs&lt;/a&gt; to learn more about data modeling.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Auto-generated and customizable SQL migrations
&lt;/h3&gt;

&lt;p&gt;To generate your API with Platformatic, you must first define your database schema. The database schema is defined using SQL in a set of migrations files that are written manually. However, maintaining SQL migrations by hand can be tedious, brittle, and error-prone.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1575443725047812098-340" src="https://platform.twitter.com/embed/Tweet.html?id=1575443725047812098"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1575443725047812098-340');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1575443725047812098&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I also think writing your own migrations introduces risk for user error like forgetting to create a foreign key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/kgajera24" rel="noopener noreferrer"&gt;Kishan Gajera&lt;/a&gt; from &lt;a href="https://kgajera.com/blog/2022/11/15/platformatic-db-using-prisma-for-migrations/" rel="noopener noreferrer"&gt;Generate Up and Down Migrations for Platformatic DB using Prisma&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Editors typically don't provide auto-completion and type-checking when working with SQL. This might make it challenging to spot errors such as missing constraints like foreign keys.&lt;/p&gt;

&lt;p&gt;Prisma can help automate this process by generating a fully-customizable migration based on the defined schema using the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-cli" rel="noopener noreferrer"&gt;CLI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The following SQL migration will be generated based on the schema in the previous section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- CreateTable&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"createdAt"&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"email"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"name"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"User_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateTable&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Post"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"title"&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"content"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"published"&lt;/span&gt; &lt;span class="nb"&gt;BOOLEAN&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"createdAt"&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"authorId"&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"Post_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateIndex&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="nv"&gt;"User_email_key"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- AddForeignKey&lt;/span&gt;
&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Post"&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"Post_authorId_fkey"&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"authorId"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Type-safety and auto-completion for database queries
&lt;/h3&gt;

&lt;p&gt;Platformatic provides &lt;a href="https://oss.platformatic.dev/docs/reference/db/plugin" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; for extending your API. It also provides a &lt;a href="https://oss.platformatic.dev/docs/reference/sql-mapper/entities/introduction" rel="noopener noreferrer"&gt;SQL mapper&lt;/a&gt; for querying the database.&lt;/p&gt;

&lt;p&gt;Besides the out-of-the-box SQL mapper, you can alternatively extend your Platformatic API using Prisma Client to query your database. Prisma Client provides fully type-safe queries with rich type definitions based on your Prisma schema.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Platformatic also provides TypeScript support. You can use the CLI to &lt;a href="https://oss.platformatic.dev/docs/reference/cli#types" rel="noopener noreferrer"&gt;generate TypeScript types&lt;/a&gt; for your entities from your database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're working with the VS Code editor, VS Code's intellisense and suggestions will pop up as you define your queries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--staxrNn_--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_66%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F87cdnxf4y98g7rflagx5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--staxrNn_--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_66%252Cw_880%2Fhttps%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F87cdnxf4y98g7rflagx5.gif" alt="Prisma VS Code intellisense"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, VS Code can also run your JavaScript file, which uses Prisma Client through the TypeScript compiler and throws errors when a type is violated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--MFi7Afig--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_66%252Cw_880%2Fhttps%3A%2F%2Fi.imgur.com%2F3lYgGAI.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fpracticaldev%2Fimage%2Ffetch%2Fs--MFi7Afig--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_66%252Cw_880%2Fhttps%3A%2F%2Fi.imgur.com%2F3lYgGAI.gif" alt="Prisma VS Code type validation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more how you can write type-safe JavaScript with JsDoc in &lt;a href="https://www.prisma.io/blog/type-safe-js-with-jsdoc-typeSaf3js" rel="noopener noreferrer"&gt;this article&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Platformatic speeds up the development of REST and GraphQL APIs. Prisma pushes the development experience even further by providing intuitive data modeling, auto-generating customizable migrations, type-safety, and auto-completion.&lt;/p&gt;

&lt;p&gt;Look out for parts 2 and 3 — modeling, auto-generating database migrations, and extending your API using a plugin with Prisma Client for Platformatic. 🤙🏾&lt;/p&gt;

</description>
      <category>node</category>
      <category>prisma</category>
      <category>database</category>
      <category>migrations</category>
    </item>
    <item>
      <title>Data modeling – Table Inheritance</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Tue, 23 Nov 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/ruheni/data-modeling-table-inheritance-55f3</link>
      <guid>https://dev.to/ruheni/data-modeling-table-inheritance-55f3</guid>
      <description>&lt;p&gt;Modeling data is challenging. Well, at least I find it hard because of database normalization and the ever-changing database schemas.&lt;/p&gt;

&lt;p&gt;This article will cover table inheritance: what it is, where it likely came from, an example challenge, the different patterns with their pros and cons. Most of it will be theoretical, but I will do my best to include the relevant SQL for the examples.&lt;/p&gt;

&lt;p&gt;In this article, I will refer to database tables as an &lt;em&gt;Entity&lt;/em&gt; and a column in a table as an &lt;em&gt;Attribute&lt;/em&gt;. The SQL snippets will also be PostgreSQL specific.&lt;/p&gt;

&lt;p&gt;So, let's jump into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet the family
&lt;/h2&gt;

&lt;p&gt;Inheritance is an Object-Oriented Programming (OOP) pattern where a class (child) acquires properties of another class (parent). The inheritance between different classes creates a hierarchy/ tree from which you can draw a relationship between the classes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_C7D005F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135884-192d6e2f-cf58-4f21-ab93-a8ab47061187.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_C7D005F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135884-192d6e2f-cf58-4f21-ab93-a8ab47061187.png" alt="Family Tree" width="720" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This presents an advantage – reducing redundancy redefining a parent class' attribute in the child class.&lt;/p&gt;

&lt;p&gt;Relational databases, however, were not designed to be object-oriented – except for PostgreSQL that supports inheritance.&lt;/p&gt;

&lt;p&gt;Object Relational Mappers (ORMs) created an abstraction over databases, allowing you to model tables in your database as you would define entities/ objects/ classes instead of writing SQL by hand. The advantage this creates is that it creates a simple way to conceptualize your database. My hunch is that table inheritance was introduced by ORMs &lt;/p&gt;

&lt;h2&gt;
  
  
  A visit to the bank 💰
&lt;/h2&gt;

&lt;p&gt;A customer in a bank has an &lt;code&gt;Account&lt;/code&gt;. A customer can be a person or a company. This also means a bank would support different types of accounts: &lt;code&gt;CompanyAccount&lt;/code&gt; and a &lt;code&gt;SavingsAccount&lt;/code&gt; – to keep this analogy simple.The 2 types of accounts will have shared attributes – id, address, name – and unique properties – company name, owners etc. &lt;/p&gt;

&lt;p&gt;How would you model this sort of data?&lt;/p&gt;

&lt;p&gt;One option is table inheritance. There are 3 different forms of inheritance that you can use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Table Inheritance&lt;/li&gt;
&lt;li&gt;Concrete Table Inheritance&lt;/li&gt;
&lt;li&gt;Class Table Inheritance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Single Table Inheritance
&lt;/h2&gt;

&lt;p&gt;Ironically, Single Table Inheritance doesn't inform any form of inheritance when modeling tables using SQL. This is a conceptual model introduced by ORMs.&lt;/p&gt;

&lt;p&gt;You would create your parent entity &lt;code&gt;Account&lt;/code&gt; that would contain all the shared attributes. The child entities &lt;code&gt;CompanyAccount&lt;/code&gt; and &lt;code&gt;SavingsAccount&lt;/code&gt; would inherit the parent entity's attributes and define their own attributes.&lt;/p&gt;

&lt;p&gt;To differentiate the child entities a &lt;code&gt;type&lt;/code&gt; or &lt;code&gt;discriminator&lt;/code&gt; property is introduced in the parent entity which is a string value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// define the attributes here&lt;/span&gt;
    &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="c1"&gt;// "CompanyAccount" or "SavingsAccount"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CompanyAccount&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// define the attributes here&lt;/span&gt;
    &lt;span class="nl"&gt;signatories&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Json&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SavingsAccount&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="c1"&gt;// define the attributes here&lt;/span&gt;
    &lt;span class="nl"&gt;signatory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, at the database level, only one table – &lt;code&gt;Account&lt;/code&gt; – is created. All the attributes of the child entities would be added to the &lt;code&gt;Account&lt;/code&gt; table and marked as nullable or &lt;code&gt;NULL&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Account"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"balance"&lt;/span&gt; &lt;span class="nb"&gt;DOUBLE&lt;/span&gt; &lt;span class="nb"&gt;PRECISION&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"createdAt"&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"type"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;-- SavingsAccount specific field&lt;/span&gt;
    &lt;span class="nv"&gt;"signatory"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="c1"&gt;-- CorporateAccount specific field&lt;/span&gt;
    &lt;span class="nv"&gt;"signatories"&lt;/span&gt; &lt;span class="n"&gt;JSONB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;


    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"Account_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="nv"&gt;"account_type_index"&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="nv"&gt;"content"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach would be considered okay if there are few child entities inheriting from &lt;code&gt;Account&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_WyFjqBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135746-680b0a9f-b7cc-4fa9-8cf6-191e4cac9206.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_WyFjqBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135746-680b0a9f-b7cc-4fa9-8cf6-191e4cac9206.png" alt="Single Table Inheritance" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Single Table Inheritance wouldn't scale well because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Depending on the number of attributes from child entities, there would be many &lt;code&gt;NULL&lt;/code&gt; fields.&lt;/li&gt;
&lt;li&gt;Adding a new class would make this difficult to maintain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Concrete Table Inheritance
&lt;/h2&gt;

&lt;p&gt;The Concrete Table Inheritance pattern takes a slightly different approach when creating tables in the database. &lt;/p&gt;

&lt;p&gt;The parent entity would serve as a template from which child entities would inherit. However, in this instance, the parent entity isn't created in the database.&lt;/p&gt;

&lt;p&gt;The plus sides for this approach include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Child entities will have individual tables and won't store attributes of other child entities.&lt;/li&gt;
&lt;li&gt;Mandatory fields of the child entity would be enforced with the &lt;code&gt;NOT NULL&lt;/code&gt; constraint.&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;type&lt;/code&gt; column in the parent entity to determine the type of child entity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some downsides are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modeling using SQL would be very repetitive when defining attributes from the parent entity every time you'd create a child entity&lt;/li&gt;
&lt;li&gt;Searching through all child entities would require a &lt;code&gt;UNION&lt;/code&gt; on child tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_WyFjqBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135746-680b0a9f-b7cc-4fa9-8cf6-191e4cac9206.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_WyFjqBQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135746-680b0a9f-b7cc-4fa9-8cf6-191e4cac9206.png" alt="Untitled" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The SQL for Concrete Table Inheritance would resemble this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"SavingsAccount"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"balance"&lt;/span&gt; &lt;span class="nb"&gt;DOUBLE&lt;/span&gt; &lt;span class="nb"&gt;PRECISION&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"createdAt"&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"signatory"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"SavingsAccount_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"CorporateAccount"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"balance"&lt;/span&gt; &lt;span class="nb"&gt;DOUBLE&lt;/span&gt; &lt;span class="nb"&gt;PRECISION&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"createdAt"&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"signatories"&lt;/span&gt; &lt;span class="n"&gt;JSONB&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"CorporateAccount_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PostgreSQL supports the &lt;code&gt;INHERITS&lt;/code&gt; keyword that takes care of inheritance. The only difference is that the parent entity is also created in the database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;ACCOUNT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="c1"&gt;--- Base table properties here&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;CORPORATE_ACCOUNT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="c1"&gt;--- Specific table properties&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;INHERITS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;SAVINGS_ACCOUNT&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="c1"&gt;--- Specific table properties&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;INHERITS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ACCOUNT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Class Table Inheritance
&lt;/h2&gt;

&lt;p&gt;Class Table inheritance resembles Classes in OOP and takes the best of both worlds. &lt;/p&gt;

&lt;p&gt;The parent entity would have its own table and any child entity would have a 1-1 relationship with the parent. The ID of the child entity would serve as a foreign key in the parent entity.&lt;/p&gt;

&lt;p&gt;Example Entity Relationship Diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hjrfRhNN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135866-e84bd1e0-29d3-4bea-adc0-40d2b462f6df.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hjrfRhNN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/143135866-e84bd1e0-29d3-4bea-adc0-40d2b462f6df.png" alt="Untitled" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SQL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- CreateTable&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"Account"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"balance"&lt;/span&gt; &lt;span class="nb"&gt;DOUBLE&lt;/span&gt; &lt;span class="nb"&gt;PRECISION&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"createdAt"&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"savingsAccountId"&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"corporateAccountId"&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"Account_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateTable&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"SavingsAccount"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"signatory"&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"accountId"&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"SavingsAccount_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateTable&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="nv"&gt;"CorporateAccount"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"signatories"&lt;/span&gt; &lt;span class="n"&gt;JSONB&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;"accountId"&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="nv"&gt;"CorporateAccount_pkey"&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateIndex&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="nv"&gt;"Account_savingsAccountId_key"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"Account"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"savingsAccountId"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- CreateIndex&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="nv"&gt;"Account_corporateAccountId_key"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"Account"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"corporateAccountId"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The advantages of this approach are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is DRY&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;type&lt;/code&gt; column in the parent entity to determine the type of child entity&lt;/li&gt;
&lt;li&gt;Searching through tables is easier – no &lt;code&gt;UNION&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;There is no risk of child entities having attributes of other child entities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not all roses with this approach. Some of the disadvantages are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You wouldn't be able to determine the &lt;code&gt;type&lt;/code&gt; of a child entity without querying them. However, if you're using an ORM is a non-issue&lt;/li&gt;
&lt;li&gt;It can be hard keeping the parent and child entities in sync using triggers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The take away of this article is there's no one-size fits all approach when modeling entities in your database. Some have work well, and others... don't. What's important is doing the appropriate research in your domain and modeling data from that. Even this won't be enough as you will have to iterate on your database schema over and over again.&lt;/p&gt;

&lt;p&gt;You can read more in &lt;a href="https://www.oreilly.com/library/view/patterns-of-enterprise/0321127420/"&gt;Patterns of Enterprise Application Architecture&lt;/a&gt; by Martin Fowler.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>backend</category>
      <category>datamodeling</category>
    </item>
    <item>
      <title>Database Migrations for .NET and Entity Framework with Prisma</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Thu, 04 Nov 2021 12:51:58 +0000</pubDate>
      <link>https://dev.to/prisma/database-migrations-for-net-and-entity-framework-with-prisma-49e0</link>
      <guid>https://dev.to/prisma/database-migrations-for-net-and-entity-framework-with-prisma-49e0</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this article, you will learn how to model your data using &lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt;, run a migration with Prisma Migrate and then introspect your database with &lt;a href="https://dotnet.microsoft.com/" rel="noopener noreferrer"&gt;.NET&lt;/a&gt; to generate your &lt;a href="https://docs.microsoft.com/en-us/aspnet/entity-framework" rel="noopener noreferrer"&gt;Entity Framework&lt;/a&gt; models. This article will use Azure SQL/ SQL Server. &lt;/p&gt;

&lt;p&gt;This article only offers an alternative data modelling workflow that is succinct and offer a better development experience. Besides .NET and the Entity framework, you can also use Prisma with your tool/ frameworks of choice such as &lt;a href="https://www.djangoproject.com/" rel="noopener noreferrer"&gt;Django&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Prisma auto-generates migration files in SQL that you can modify before applying them on your database. The workflow following this approach would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Model your data&lt;/li&gt;
&lt;li&gt;Run a migration using &lt;a href="https://www.prisma.io/migrate" rel="noopener noreferrer"&gt;Prisma Migrate&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use the Entity Framework to &lt;em&gt;&lt;a href="https://docs.microsoft.com/en-us/ef/core/managing-schemas/scaffolding?tabs=dotnet-core-cli" rel="noopener noreferrer"&gt;reverse engineer&lt;/a&gt;/ scaffold/&lt;/em&gt; introspect your database and generate models and your database context.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is Prisma?
&lt;/h2&gt;

&lt;p&gt;Prisma is an object-relational mapper (ORM) that provides a declarative way to define your database models that are easy to read and comprehend. Prisma also provides &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-client" rel="noopener noreferrer"&gt;Prisma Client&lt;/a&gt; – an intuitive and  type-safe query builder based off your schema.&lt;/p&gt;

&lt;p&gt;At the core of Prisma is the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema" rel="noopener noreferrer"&gt;Prisma Schema&lt;/a&gt; – aka &lt;em&gt;schema file&lt;/em&gt;. The schema contains 3 parts: the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/data-sources/" rel="noopener noreferrer"&gt;data sources&lt;/a&gt;, &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/generators" rel="noopener noreferrer"&gt;generators&lt;/a&gt; and your &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/data-model" rel="noopener noreferrer"&gt;data model definition&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with .NET and the &lt;a href="https://docs.microsoft.com/en-us/aspnet/entity-framework" rel="noopener noreferrer"&gt;Entity framework&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Installed Node.js v 12.6.x or higher&lt;/li&gt;
&lt;li&gt;Installed .NET locally&lt;/li&gt;
&lt;li&gt;A SQL Server or Azure SQL database&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=Prisma.prisma" rel="noopener noreferrer"&gt;Prisma Extension&lt;/a&gt; for VS Code users&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you're not familiar with setting up SQL Server, check out &lt;a href="https://www.prisma.io/dataguide/mssql/setting-up-a-local-sql-server-database" rel="noopener noreferrer"&gt;Setting up a local SQL Server database&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 1: Create a new console application
&lt;/h2&gt;

&lt;p&gt;The first step is to create a new .NET console app in your working directory. This guide uses a console application to keep it simple. However, feel free to create any other type of application.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet new console &lt;span class="nt"&gt;--output&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;__app-name__&lt;span class="k"&gt;*&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the command is done, navigate to the project and confirm that your project is running.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;__app-name__&lt;span class="k"&gt;*&lt;/span&gt;
dotnet run


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If the output on the terminal is &lt;code&gt;Hello World!&lt;/code&gt;, everything seems to be running just fine!  🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Add Prisma to your project
&lt;/h2&gt;

&lt;p&gt;On a separate terminal window but still within the same project run the following commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;mkdir &lt;/span&gt;prisma-migrate
&lt;span class="nb"&gt;cd &lt;/span&gt;prisma-migrate
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The commands create a new directory, navigate to the folder and initializes it as a Node.js project. The &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-cli" rel="noopener noreferrer"&gt;Prisma CLI&lt;/a&gt; is the only dependency for this project. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; prisma


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Initialize Prisma
&lt;/h3&gt;

&lt;p&gt;Once the install is done, run the following command.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx prisma init &lt;span class="nt"&gt;--database-provider&lt;/span&gt; sqlserver


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a &lt;code&gt;.env&lt;/code&gt; file at the root of the project for storing environment variables&lt;/li&gt;
&lt;li&gt;Creates &lt;code&gt;prisma&lt;/code&gt; folder containing a &lt;code&gt;schema.prisma&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Specifies the database provider as &lt;code&gt;sqlserver&lt;/code&gt; in &lt;code&gt;schema.prisma&lt;/code&gt; file and provides a dummy &lt;code&gt;sqlserver&lt;/code&gt; connection string in &lt;code&gt;.env&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;schema.prisma&lt;/code&gt; file defines the database connection and the Prisma Client generator. This is where you will also define your database models.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="c1"&gt;/// prisma/schema.prisma&lt;/span&gt;
&lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sqlserver"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"prisma-client-js"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For this guide, you can delete &lt;code&gt;generator client&lt;/code&gt; as it is relevant in a TypeScript/ JavaScript project. The &lt;code&gt;generator client&lt;/code&gt; is used to generate the TypeScript definitions for the Prisma Client.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;.env&lt;/code&gt; with your database connection string. Refer to &lt;a href="https://www.prisma.io/docs/concepts/database-connectors/sql-server#connection-details" rel="noopener noreferrer"&gt;connection details&lt;/a&gt; for information on how to configure the connection string.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# .env&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sqlserver://HOST:PORT;database=DATABASE;user=USER;password=PASSWORD;"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;
  If you're using a remote database during development like Azure SQL, open this to learn more about how to configure the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-migrate/shadow-database" rel="noopener noreferrer"&gt;shadow database&lt;/a&gt;.
  &lt;br&gt;
Create a new database which will be the &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-migrate/shadow-database" rel="noopener noreferrer"&gt;shadow database&lt;/a&gt; on Azure. Update your &lt;code&gt;.env&lt;/code&gt; file to include the &lt;code&gt;SHADOW_DATABASE_URL&lt;/code&gt; as well. The shadow database will be used in the data modelling step 
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# .env&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sqlserver://HOST:PORT;database=DATABASE;user=USER;password=PASSWORD;"&lt;/span&gt;
&lt;span class="nv"&gt;SHADOW_DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sqlserver://HOST:PORT;database=DATABASE;user=USER;password=PASSWORD;"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Update your &lt;code&gt;schema.prisma&lt;/code&gt; file with the connection string for the shadow database. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="c1"&gt;/// prisma/schema.prisma&lt;/span&gt;
&lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;provider&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sqlserver"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt;               &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"DATABASE_URL"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;shadowDatabaseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SHADOW_DATABASE_URL"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;A shadow database is a second, &lt;em&gt;temporary&lt;/em&gt; database for use in the local development workflow. When running a migration, the secondary database is created and deleted automatically unless you're using a cloud-hosted database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's an illustration of how the shadow database works:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.prisma.io%2Fdocs%2Fstatic%2Ffa8149049da32d83d8014e3d14d644c0%2Fa6d36%2Fshadow-database.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.prisma.io%2Fdocs%2Fstatic%2Ffa8149049da32d83d8014e3d14d644c0%2Fa6d36%2Fshadow-database.png" alt="https://www.prisma.io/docs/static/fa8149049da32d83d8014e3d14d644c0/a6d36/shadow-database.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Data modelling
&lt;/h3&gt;

&lt;p&gt;This example will define 2 models: &lt;code&gt;Post&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt;.The relationship between &lt;code&gt;User&lt;/code&gt; and &lt;code&gt;Post&lt;/code&gt; is a one-to-many relationship.&lt;/p&gt;

&lt;p&gt;The models defined in &lt;code&gt;schema.prisma&lt;/code&gt; will resemble a GraphQL syntax . The models also map to a table in your database.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;

&lt;span class="c1"&gt;/// prisma/schema.prisma&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;        &lt;span class="n"&gt;Int&lt;/span&gt;      &lt;span class="nd"&gt;@id&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;content&lt;/span&gt;   &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt;     &lt;span class="n"&gt;String&lt;/span&gt;
  &lt;span class="n"&gt;createdAt&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;author&lt;/span&gt;    &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;    &lt;span class="nd"&gt;@relation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;fields:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;authorId&lt;/span&gt;&lt;span class="o"&gt;],&lt;/span&gt; &lt;span class="nl"&gt;references:&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
  &lt;span class="n"&gt;authorId&lt;/span&gt;  &lt;span class="n"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;    &lt;span class="n"&gt;Int&lt;/span&gt;     &lt;span class="nd"&gt;@id&lt;/span&gt; &lt;span class="nd"&gt;@default&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;autoincrement&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;  &lt;span class="nd"&gt;@unique&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt;  &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
  &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Refer to the &lt;a href="https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference" rel="noopener noreferrer"&gt;Prisma Schema Reference&lt;/a&gt; for further information on database field types, attributes, conventions and functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a database migration
&lt;/h3&gt;

&lt;p&gt;After modelling your data, it's time to apply the changes to your database. On your terminal window, run &lt;code&gt;npx prisma migrate dev&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx prisma migrate dev &lt;span class="nt"&gt;--name&lt;/span&gt; init


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If no database exists, a new database with the database name specified in your &lt;code&gt;.env&lt;/code&gt; file will be created. The command also creates a new database migration that is located in &lt;code&gt;./prisma/migrations&lt;/code&gt; directory. The migration is in SQL and is applied against your database. &lt;code&gt;init&lt;/code&gt; refers to the migration name which you can change to something more semantic.&lt;/p&gt;

&lt;p&gt;If you wish to only create a migration but not apply it to your database, pass the &lt;code&gt;--create-only&lt;/code&gt; option to Prisma Migrate. This will generate the SQL and allow you to customize it before applying it against your database.&lt;/p&gt;

&lt;p&gt;You can confirm that the changes have been applied, run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx prisma studio


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fde9p51dk06cbmaviv5lt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fde9p51dk06cbmaviv5lt.png" alt="Screenshot 2021-10-17 at 19.49.28.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the Model you would like to view/ edit data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm5gi64m3xeb68utpt5l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm5gi64m3xeb68utpt5l.png" alt="Screenshot 2021-10-17 at 19.51.25.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Save 1 change&lt;/strong&gt; to apply the changes.&lt;/p&gt;

&lt;p&gt;Navigate to the User model, create a new user, link the post created in the previous step and save the change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fph7m5cz8jho4m5p921zw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fph7m5cz8jho4m5p921zw.png" alt="Screenshot 2021-10-17 at 19.53.24.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Introspect your database aka Reverse Engineering
&lt;/h2&gt;

&lt;p&gt;Entity framework allows you to introspect your database schema and scaffold entity type classes and the database context based off an existing database.&lt;/p&gt;

&lt;p&gt;Navigate out of &lt;code&gt;prisma-migrate&lt;/code&gt; directory to the root of your project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; ../


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Install Entity Framework tools you will require to work with SQL Server in your project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet add package Microsoft.EntityFrameworkCore.SqlServer 
dotnet add package Microsoft.EntityFrameworkCore.Tools 
dotnet add package Microsoft.EntityFrameworkCore.Design


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Scaffold entity type classes based on your database schema to your project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet ef dbcontext scaffold &lt;span class="s2"&gt;"Server=**HOST**;Database=**DATABASE_NAME**;User Id=**USER**;Password=**PASSWORD**"&lt;/span&gt; Microsoft.EntityFrameworkCore.SqlServer &lt;span class="nt"&gt;--context-dir&lt;/span&gt; DbContext &lt;span class="nt"&gt;--context&lt;/span&gt; BlogExampleContext &lt;span class="nt"&gt;--output-dir&lt;/span&gt; Models


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Microsoft.EntityFrameworkCore.SqlServer&lt;/code&gt; refers to the package to be used to introspect the database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--context-dir&lt;/code&gt; and &lt;code&gt;--output-dir&lt;/code&gt; refer to the location of the context and the entity type classes after introspection&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--context&lt;/code&gt; refers to the name of your database context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On a successful run 2 folders with 4 files will be created in your project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="k"&gt;*&lt;/span&gt;app-name&lt;span class="k"&gt;*&lt;/span&gt;/
┣ DbContext/
┃ ┗ BlogExampleContext.cs
┣ Models/
┃ ┣ Post.cs
┃ ┗ PrismaMigration.cs
┃ ┗ User.cs
┣ ...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you will notice, &lt;code&gt;PrismaMigration.cs&lt;/code&gt; was not defined in &lt;code&gt;schema.prisma&lt;/code&gt;. This is a table created by Prisma to track the migrations that have been created and applied against your database.&lt;/p&gt;

&lt;p&gt;To exclude the &lt;code&gt;PrismaMigrations&lt;/code&gt; table, and re-run the previous command but specify the tables you would like using the &lt;code&gt;--table&lt;/code&gt; and &lt;code&gt;—force&lt;/code&gt; options to overwrite the existing models.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet ef dbcontext scaffold &lt;span class="s2"&gt;"Server=**HOST**;Database=**DATABASE_NAME**;User Id=**USER**;Password=**PASSWORD**"&lt;/span&gt; Microsoft.EntityFrameworkCore.SqlServer &lt;span class="nt"&gt;--context-dir&lt;/span&gt; DbContext &lt;span class="nt"&gt;--context&lt;/span&gt; BlogExampleContext &lt;span class="nt"&gt;--output-dir&lt;/span&gt; Models &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="nt"&gt;--table&lt;/span&gt; User &lt;span class="nt"&gt;--table&lt;/span&gt; Post


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This time, 3 files are generated and the &lt;code&gt;PrismaMigrations.cs&lt;/code&gt; file is excluded when scaffolding.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're interested in migrating to Prisma with an existing database, the Prisma CLI provides &lt;code&gt;db pull&lt;/code&gt; for introspecting the database and populating &lt;code&gt;schema.prisma&lt;/code&gt; with your database models.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations! You have successfully modelled your entities, run a migration with Prisma and scaffolded your models and context with Entity Framework. &lt;/p&gt;

&lt;p&gt;Learn how you can set up and deploy a Prisma based Node.js REST API to Azure Functions together with Azure SQL in &lt;a href="https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-azure-functions" rel="noopener noreferrer"&gt;Deploying to Azure Functions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you would like to learn more about Prisma, check out the &lt;a href="https://www.prisma.io/docs" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and feel free to create an &lt;a href="https://github.com/prisma/prisma/issues" rel="noopener noreferrer"&gt;issue&lt;/a&gt; or start a &lt;a href="https://github.com/prisma/prisma/discussions" rel="noopener noreferrer"&gt;discussion&lt;/a&gt; on GitHub.&lt;/p&gt;

</description>
      <category>prisma</category>
      <category>database</category>
      <category>backend</category>
      <category>entityframework</category>
    </item>
    <item>
      <title>SE Internship Log[5]</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Tue, 07 Sep 2021 07:14:32 +0000</pubDate>
      <link>https://dev.to/ruheni/se-internship-log-5-4869</link>
      <guid>https://dev.to/ruheni/se-internship-log-5-4869</guid>
      <description>&lt;p&gt;This week, I tackled an interesting challenge revealing knowledge gaps – executing an exported function in a TypeScript file without calling it within the file and working with the Node CLI. &lt;/p&gt;

&lt;p&gt;For most of the application code, you may write, you may never have to learn such concepts because, in software, we have &lt;strong&gt;A LOT&lt;/strong&gt; of abstractions – mainly in the form of npm packages for fellow JavaScript Developers.&lt;/p&gt;

&lt;p&gt;But if you're building systems for other systems to run on, you have to dive deeper and learn the abstractions are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context - how seeding in Prisma works
&lt;/h2&gt;

&lt;p&gt;The task involved writing a script would end up being part of a &lt;em&gt;mini-test-suite&lt;/em&gt; to ensure that the instructions a user followed wouldn't lead to an error.&lt;/p&gt;

&lt;p&gt;One of the steps was seeding a database in a &lt;a href="https://www.prisma.io"&gt;Prisma&lt;/a&gt; project. The Prisma CLI exposes a &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference#db-seed-preview"&gt;&lt;code&gt;seed&lt;/code&gt;&lt;/a&gt; command, but at the time of writing this, it's a &lt;a href="https://www.prisma.io/docs/about/prisma/releases#preview"&gt;&lt;code&gt;preview-feature&lt;/code&gt;&lt;/a&gt; and its implementation is being &lt;a href="https://github.com/prisma/prisma/issues/8732"&gt;redesigned&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The default way of executing a function in a file is by calling it. It just works. The stable implementation of seeding currently works as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="cm"&gt;/** your seeding logic */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;npx prisma db seed --preview-feature&lt;/code&gt; would successfully seed your database with the above code example&lt;/p&gt;

&lt;p&gt;But... seeding was using a different implementation of the &lt;code&gt;seed&lt;/code&gt; command that the Prisma CLI supports – executing seed function with a default exported &lt;code&gt;seed()&lt;/code&gt; or exported &lt;code&gt;seed()&lt;/code&gt; function in your &lt;code&gt;./prisma/seed.ts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="cm"&gt;/** your logic */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// OR&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="cm"&gt;/** your logic */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;npx prisma db seed --preview-feature&lt;/code&gt; would work just okay but it isn't &lt;em&gt;always&lt;/em&gt; guaranteed to work perfectly. Occasionally, &lt;code&gt;prisma db seed&lt;/code&gt; encounters an error but won't throw an error – indicating a false positive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ts-node&lt;/code&gt; 🎉&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ts-node&lt;/code&gt; is a handy tool for transpiling/ transforming TypeScript into JavaScript.&lt;/p&gt;

&lt;p&gt;Unlike the first &lt;code&gt;main()&lt;/code&gt; seeding example, the &lt;code&gt;seed()&lt;/code&gt; function isn't called. Running &lt;code&gt;npx ts-node ./prisma/seed&lt;/code&gt; would only transform the file checking for type errors.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ts-node&lt;/code&gt; exposes the &lt;code&gt;--eval&lt;/code&gt;/ &lt;code&gt;-e&lt;/code&gt; flag from the Node CLI. The &lt;a href="https://nodejs.org/api/cli.html#cli_e_eval_script"&gt;&lt;code&gt;--eval&lt;/code&gt;&lt;/a&gt; flag accepts a &lt;em&gt;script&lt;/em&gt; argument which is valid TypeScript/ JavaScript code. For It has to be valid JavaScript in the case of Node.js.&lt;/p&gt;

&lt;p&gt;You can execute the &lt;code&gt;seed()&lt;/code&gt; function with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx ts-node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"import seed from './prisma/seed'; seed()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx ts-node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"import {seed} from './prisma/seed'; seed()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the command is being executed, &lt;code&gt;--eval&lt;/code&gt; creates a "sandbox" – the Node.js &lt;a href="https://nodejs.org/api/repl.html#repl_repl"&gt;REPL (Read-Eval-Print-Loop)&lt;/a&gt; – where the code is executed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You can execute exported functions in your TypeScript project following the above command. E.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// path - ./src/starWars.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchStarWarsMovies&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/** logic here */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="cm"&gt;/** error handling */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn ts-node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"import {fetchStarWarsMovies} from './src/starWars'; fetchStarWarsMovies()"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Besides &lt;code&gt;--eval&lt;/code&gt; flag, you can also use the &lt;a href="https://nodejs.org/api/cli.html#cli_p_print_script"&gt;&lt;code&gt;--print&lt;/code&gt;/&lt;code&gt;-p&lt;/code&gt;&lt;/a&gt;. &lt;code&gt;--print&lt;/code&gt; is similar to &lt;code&gt;--eval&lt;/code&gt; but prints the output on the console.&lt;/p&gt;

&lt;p&gt;Learning about &lt;code&gt;--eval&lt;/code&gt; and &lt;code&gt;--print&lt;/code&gt; flag in &lt;code&gt;ts-node&lt;/code&gt; and Node.js showed me there's a whole mountain of tools/ software to learn out there. Abstractions are grand, but every once in a while, it's a good idea to understand how to use them instead of installing another npm package :troll_face:&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article. If you have any comments or feedback, my &lt;a href="https://twitter.com/ruheni_alex"&gt;Twitter&lt;/a&gt; DM is open.&lt;/p&gt;

&lt;p&gt;Till next week. ✌🏽&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>node</category>
    </item>
    <item>
      <title>SE Internship Log[4]</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Mon, 23 Aug 2021 10:16:49 +0000</pubDate>
      <link>https://dev.to/ruheni/se-internship-log-4-5hc5</link>
      <guid>https://dev.to/ruheni/se-internship-log-4-5hc5</guid>
      <description>&lt;p&gt;Hello there internet stranger, 👋🏽&lt;/p&gt;

&lt;p&gt;Welcome to the 5th edition of the Software Engineering(SE) Log.&lt;/p&gt;

&lt;p&gt;This week was frustrating. I spent the week trying to debug a test that failed 1-3 times a day (a cron job that runs on an hourly basis). &lt;/p&gt;

&lt;p&gt;When does it fail? Anytime.&lt;/p&gt;

&lt;p&gt;Why does it fail? The response data is 0 instead of 20(expectation).&lt;/p&gt;

&lt;p&gt;Why is it 0? No freakin' clue. 🥲&lt;/p&gt;

&lt;p&gt;Hopefully, the upcoming week will be better than the previous one.&lt;/p&gt;

&lt;p&gt;Enough with the rant. This week, I learned a bunch of stuff – re-thinking performance, &lt;a href="https://nextjs.org/docs/advanced-features/measuring-performance" rel="noopener noreferrer"&gt;Next.js measuring performance&lt;/a&gt;, &lt;a href="https://github.com/maticzav/label-sync" rel="noopener noreferrer"&gt;label-sync&lt;/a&gt;, and being proactive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Re-thinking performance
&lt;/h3&gt;

&lt;p&gt;This won't be about bloated JavaScript bundles or optimizing. I'm not an expert.&lt;/p&gt;

&lt;p&gt;This week, I got a comment on a PR for a task I was working on that I was making an expensive API call – introspecting the user's database checking for any tables.&lt;/p&gt;

&lt;p&gt;No big deal? Well, it is. This operation would happen every time a user opens a project.&lt;/p&gt;

&lt;p&gt;This changed how I think about API requests from the frontend in terms of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;li&gt;User experience.&lt;/li&gt;
&lt;li&gt;Compute required to make a task happen – on the API, and the user's resources which in this case is their database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just because you can do something doesn't mean you should. Compute resources are finite. Evaluate the impact of the requests you make and how you can cut down on what isn't necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next.js Measuring performance
&lt;/h3&gt;

&lt;p&gt;Vercel provides analytics on application performance for different stacks – Next.js included.&lt;/p&gt;

&lt;p&gt;Next.js can provide tooling that allows you to measure analytics and use your own custom analytics.&lt;/p&gt;

&lt;p&gt;The metrics that Next.js allows you to track include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://web.dev/vitals/" rel="noopener noreferrer"&gt;Web Vitals&lt;/a&gt; - these metrics measure and report the performance of your application to ensure you're delivering a great user experience. &lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://nextjs.org/docs/advanced-features/measuring-performance#custom-metrics" rel="noopener noreferrer"&gt;Custom Metrics&lt;/a&gt; - this is specific to Next.js measuring the time taken for a page to hydrate and render:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Next.js-hydration&lt;/code&gt; - time take for a page to start and finish hydrating&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Next.js-route-change-to-render&lt;/code&gt; - time taken for a page to render a page after navigating to the route&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Next.js-render&lt;/code&gt; - time taken for a page to finish rendering after a route change&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Fun learning project idea - build your own/ custom tool to measure these analytics. The aim would be to learn how to store time-series data, average the data, and visualize the data. Chrome devtools and &lt;a href="https://web.dev/measure" rel="noopener noreferrer"&gt;Web.dev&lt;/a&gt; doesn't measure custom Next.js metrics.&lt;br&gt;
You can see how well my site is performing 🤡&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F130419796-0257f6c5-a2ea-4f58-943d-0f13d32599dc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F33921841%2F130419796-0257f6c5-a2ea-4f58-943d-0f13d32599dc.png" alt="ruheni.dev analytics"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In your Next.js application, edit/ create &lt;code&gt;_app.js&lt;/code&gt; in the &lt;code&gt;/pages&lt;/code&gt; directory. Define the &lt;code&gt;reportWebVitals&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reportWebVitals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FCP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;// handle results - console.log or send to an API (same case for other metrics)&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;LCP&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CLS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TTFB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Next.js-hydration&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Next.js-route-change-to-render&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Next.js-render&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These analytics provide insights into how user experience is, parts of your application that are not doing too well, and tips on improving performance in your web application.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧰  Label-sync
&lt;/h3&gt;

&lt;p&gt;Label-sync is a handy tool that makes managing GitHub labels across multiple repositories delightful.&lt;/p&gt;

&lt;p&gt;Why do you need it? You don't.&lt;/p&gt;

&lt;p&gt;The default GitHub labels are okay. But, they could be better.&lt;/p&gt;

&lt;p&gt;GitHub labels provide meta-data for a GitHub issue. This could be the context of a given problem, for example backend, frontend, bug, test, improvement, feature, whether an issue requires discussion, time, and the list goes on on what this could be&lt;/p&gt;

&lt;p&gt;Label-sync allows you to define affected repositories, labels, themes, descriptions, group labels, etc.&lt;/p&gt;

&lt;p&gt;It requires some configuration when starting. However, managing issues in your projects will be a delight.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a personal opinion.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Being Proactive
&lt;/h3&gt;

&lt;p&gt;Being proactive involves taking responsibility in your life. It involves anticipating problems, seeking solutions, and giving it your best shot.&lt;/p&gt;

&lt;p&gt;The alternative to being proactive is reactive - responding to tasks/life as they stream. &lt;/p&gt;

&lt;p&gt;You are responsible for your growth, including your career.&lt;/p&gt;

&lt;p&gt;Go out there, ace it and have a great week!&lt;/p&gt;

&lt;p&gt;Till next week. ✌🏽&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>tools</category>
    </item>
    <item>
      <title>SE Internship Log[3]</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Mon, 16 Aug 2021 19:59:00 +0000</pubDate>
      <link>https://dev.to/ruheni/se-internship-log-3-16am</link>
      <guid>https://dev.to/ruheni/se-internship-log-3-16am</guid>
      <description>&lt;p&gt;Hello there internet stranger, 👋🏽&lt;/p&gt;

&lt;p&gt;This is the 4th installment of the Software  Engineering(SE) Log.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Toolbox 🧰
&lt;/h3&gt;

&lt;p&gt;This week, I'll share a some libraries/ tools I discovered that I found helpful:&lt;/p&gt;

&lt;h4&gt;
  
  
  ts-node &lt;code&gt;--require&lt;/code&gt; flag
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/ts-node"&gt;&lt;code&gt;ts-node&lt;/code&gt;&lt;/a&gt;transforms TypeScript into JavaScript, which is executed in Node.js.&lt;/p&gt;

&lt;p&gt;A useful flag I discovered is the &lt;code&gt;-r&lt;/code&gt;/ &lt;code&gt;--require&lt;/code&gt; that enables you to execute a file with an export (aka a module):&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// path to file on your computer: /src/hello.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello there&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can execute this file by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx ts-node &lt;span class="nt"&gt;-r&lt;/span&gt; ./src/hello.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Reading and writing files with &lt;code&gt;fs-jetpack&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/fs-jetpack"&gt;&lt;code&gt;fs-jetpack&lt;/code&gt;&lt;/a&gt; is a utility library that makes interacting with the file-system delightful.&lt;br&gt;
This can be the CRUD of files and directories - creating, reading, updating and deleting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Consistency
&lt;/h3&gt;

&lt;p&gt;Sometimes – or most times – software engineering gets tough. Tasks may be daunting, issues may be vague, or sometimes getting help/ feedback on a task may take a little longer than expected.&lt;/p&gt;

&lt;p&gt;It's frustrating. The feeling sucks!&lt;/p&gt;

&lt;p&gt;The frustration is part of the learning/ growth process.&lt;/p&gt;

&lt;p&gt;There will be days you will crush it! &lt;/p&gt;

&lt;p&gt;And sometimes, the simplest of tasks can seem impossible.&lt;/p&gt;

&lt;p&gt;What matters the most is showing up and making an attempt to fix and a bug, close an issue, or just give feedback on a project. &lt;/p&gt;

&lt;p&gt;A hack that I use to "trick" my brain to getting it done is starting with the simplest task to build up some momentum. For example, opening VS Code, starting the app server, and breaking something to try fix it.&lt;/p&gt;

&lt;p&gt;Or, take a break. It's totally fine.&lt;/p&gt;

&lt;p&gt;I've discovered that I get most of my eureka moments when I take a walk, I'm in the shower or lying on the bed &lt;em&gt;– thinking about the finality of death and how life is meaningless and we're all going to die someday and nothing we do matters.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;💡&lt;/p&gt;

&lt;p&gt;Till next week. ✌🏽&lt;/p&gt;

</description>
    </item>
    <item>
      <title>SE Internship Log[2]</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Mon, 09 Aug 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/ruheni/se-internship-log-2-5g09</link>
      <guid>https://dev.to/ruheni/se-internship-log-2-5g09</guid>
      <description>&lt;p&gt;Hello there internet stranger, 👋🏽&lt;/p&gt;

&lt;p&gt;This is the 3rd article in the Software Engineering(SE) Log.&lt;/p&gt;

&lt;p&gt;A little about me, I'm Alex, and I have no freaking idea what I'm doing. But, I'm taking one step at a time to learn and &lt;em&gt;trying&lt;/em&gt; to figure things out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testing 🎙
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;I was going for a mic check with the emoji, but uuuuhh (awkward stares)... moving on swiftly&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This week was spent improving our end-to-end testing for the smoke tests. It was pretty neat because I learnt how to create a &lt;a href="https://jestjs.io/docs/api#testeachtablename-fn-timeout"&gt;test matrix with jest&lt;/a&gt;. A test matrix reduces repetitive tests that uses the same data.&lt;/p&gt;

&lt;p&gt;Let's back up for a moment and explain some jargon.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is a test?
&lt;/h4&gt;

&lt;p&gt;A test is code that tests your code ensuring it does what it's suppose to.&lt;/p&gt;

&lt;p&gt;Testing may be manual – a user going through your application and finding bugs – or automated – a program runs assertions against your code to ensure everything works correctly.&lt;/p&gt;

&lt;p&gt;There are different types of tests such as unit, integration, and end-to-end tests that help build confidence you're not shipping any bugs – which are features sometimes. It can be painful sometimes writing tests but on the bright side, it's a great skill to have and you ship less bugs. 🙂 &lt;/p&gt;

&lt;p&gt;This Log won't cover everything that has to do with testing because there's a lot and it can't be summarized into a short article. However, you can check out the &lt;a href="https://google.github.io/googletest/"&gt;Google Test User Guide&lt;/a&gt;. It provides a good introduction to testing concepts. It's specific to &lt;code&gt;C++&lt;/code&gt; but I think it provides a good foundation in testing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I accidentally once shipped a slightly broken feature about 2 weeks ago. It wasn't a bug, but it didn't behave as expected. I still haven't fixed it but by the time this log is out, there'll be a PR fixing it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  End-to-end tests aka smoke tests
&lt;/h4&gt;

&lt;p&gt;An end-to-end (e2e) test is a test that simulates a user's interaction in an application. I.e, it opens up the application up on an emulator (browser window or mobile emulator) and interacts with the application by clicking links, filling out forms etc.&lt;/p&gt;

&lt;p&gt;There are a suite of tools that can be used to accomplish this such as &lt;a href="https://www.cypress.io/"&gt;Cypress&lt;/a&gt; and &lt;a href="https://playwright.dev/"&gt;Playwright&lt;/a&gt; for web-based applications.&lt;/p&gt;

&lt;p&gt;To give a sense of what this would be like, here's a small guide on getting started with Playwright. It'll use the &lt;a href="https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-nextjs"&gt;GraphQL-Next.js Prisma example&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  A small demo testing with Playwright
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Set up the application
&lt;/h5&gt;

&lt;p&gt;Download the example and install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | &lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xz&lt;/span&gt; &lt;span class="nt"&gt;--strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 prisma-examples-latest/typescript/graphql-nextjs
&lt;span class="nb"&gt;cd &lt;/span&gt;graphql-nextjs
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set up the database (this uses SQLite for ease of set up)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma migrate dev &lt;span class="nt"&gt;--name&lt;/span&gt; init    &lt;span class="c"&gt;# Creates a database and applies the schema against it&lt;/span&gt;
npx prisma db seed &lt;span class="nt"&gt;--preview-feature&lt;/span&gt;  &lt;span class="c"&gt;# Seeds the database based on `prisma/seed.ts&lt;/span&gt;
npm run dev                           &lt;span class="c"&gt;# Starts the application server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a separate terminal, install &lt;code&gt;playwright&lt;/code&gt; as a &lt;code&gt;devDependency&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @playwright/test
npx playwright &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's now time to write an example test for the application. At the root of the project, create a folder called &lt;code&gt;tests&lt;/code&gt; and a file called &lt;code&gt;test.spec.ts&lt;/code&gt;. In &lt;code&gt;test.spec.ts&lt;/code&gt;, paste in the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User flow:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 2&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="c1"&gt;// 3&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 4&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=Signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 5&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=Signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[placeholder="Name"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[placeholder="Email address"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;john@email.io&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[value="Signup"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=My Blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cancel signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=Signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=Signup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=or Cancel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;waitForSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text=My Blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000/#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following test does a number of things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This groups logically related tests&lt;/li&gt;
&lt;li&gt;Creates a hook that executes before a test is run. In this case, it navigates to the application&lt;/li&gt;
&lt;li&gt;The test definition&lt;/li&gt;
&lt;li&gt;An assertion to verify what is expected to be on the user's device&lt;/li&gt;
&lt;li&gt;Simulates user interaction&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Run the test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx playwright &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tests does the following:&lt;/p&gt;

&lt;p&gt;Test case 1:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigates to &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Clicks the &lt;code&gt;Signup&lt;/code&gt; link&lt;/li&gt;
&lt;li&gt;Fills out the user information&lt;/li&gt;
&lt;li&gt;Submits values&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Test case 2: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigates to &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Clicks the &lt;code&gt;Signup&lt;/code&gt; link&lt;/li&gt;
&lt;li&gt;Exits from the flow&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The output on your terminal should resemble this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ID47V7AF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/128688193-4cd1e6c4-1e10-4a45-ae6c-f93aaca89bdc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ID47V7AF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/33921841/128688193-4cd1e6c4-1e10-4a45-ae6c-f93aaca89bdc.png" alt="Output screenshot" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can make the test intentionally fail by playing around with the values in &lt;code&gt;.toBe('random_value')&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The tests run on the CLI – in headless mode, meaning there's no browser window being opened. You can play around with the configuration.&lt;/p&gt;

&lt;p&gt;This is just a glimplse of what e2e tests look like and there's so much more that you can do with e2e tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft skills
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Learning in public
&lt;/h2&gt;

&lt;p&gt;An interesting thought I had earlier this week was on sharing knowledge or learning in public. Most of the time – especially as a beginner or even if you're senior – you may feel like you're not qualified enough to share the knowledge you have for a number of reasons. Maybe, you're not good at it yet, someone else has done it or any other excuse that may come up, preventing you from talking about what you learnt.&lt;/p&gt;

&lt;p&gt;Well, go ahead and do it!&lt;/p&gt;

&lt;p&gt;Am I qualified to talk to you about Playwright, testing, TypeScript (the list is endless) or any other topic? &lt;/p&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

&lt;p&gt;I don't know.&lt;/p&gt;

&lt;p&gt;But, the more you make content about what you love, the easier it gets and someone out there will appreciate your work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Start before you think you're ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Purzzv8G66o"&gt;Matt D'Avella&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Do what brings you joy and enjoy the process. 🙂&lt;/p&gt;

&lt;p&gt;Till next week. ✌🏽&lt;/p&gt;

</description>
    </item>
    <item>
      <title>SE Internship Log[1]</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Mon, 02 Aug 2021 07:03:44 +0000</pubDate>
      <link>https://dev.to/ruheni/se-internship-log-1-3407</link>
      <guid>https://dev.to/ruheni/se-internship-log-1-3407</guid>
      <description>&lt;p&gt;Hello there internet stranger, 👋🏽&lt;/p&gt;

&lt;p&gt;This is the second article in Software Engineering(SE) Log.&lt;/p&gt;

&lt;p&gt;The better part of the week was spent arguing with the TypeScript compiler and we both know who was right.&lt;/p&gt;

&lt;p&gt;It was me. &lt;/p&gt;

&lt;p&gt;JK, The compiler is always right! &lt;/p&gt;

&lt;h2&gt;
  
  
  Technical skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Types! Types! Types!
&lt;/h3&gt;

&lt;p&gt;This week, I learnt there's more to types than &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, &lt;code&gt;Array&lt;/code&gt;, and &lt;code&gt;Object&lt;/code&gt; types. &lt;/p&gt;

&lt;p&gt;TypeScript allows you to do some advanced type wizardry by manipulating types from existing types – besides extending from other types with interfaces. Sounds meta, right? &lt;/p&gt;

&lt;p&gt;When a type/ interface is not specified, TypeScript interprets it as its widest form/type.&lt;/p&gt;

&lt;p&gt;Case example, if you have an array of strings, the type will always be &lt;code&gt;string[]&lt;/code&gt;. However, you can take it a step further and be specific with what the value of the string should be in your array or variable.&lt;/p&gt;

&lt;p&gt;In the example below, no type is assigned to &lt;code&gt;colors&lt;/code&gt;. Therefore, TypeScript will interpret it as &lt;code&gt;string[]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yellow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orange&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, you can create a &lt;code&gt;readonly&lt;/code&gt; type from the above example by appending the key words &lt;code&gt;as const&lt;/code&gt; to the end of the statement. This means that the properties will be immutable – you cannot perform a write to the array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yellow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orange&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The intellisense on hovering on &lt;code&gt;colors&lt;/code&gt; would reveal &lt;code&gt;readonly ["blue", "black", "white", "yellow", "orange"]&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Union Types
&lt;/h4&gt;

&lt;p&gt;You could take the previous example a step further and create a &lt;code&gt;union&lt;/code&gt; type from colors array with a little TypeScript magic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yellow&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orange&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On hovering on &lt;code&gt;type color&lt;/code&gt;, a union type is created: &lt;code&gt;"blue" | "black" | "white" | "yellow" |"orange"&lt;/code&gt;. The &lt;code&gt;[number]&lt;/code&gt; annotation is an &lt;em&gt;Indexed Access Type&lt;/em&gt; – this means that it looks up a property from another type.&lt;/p&gt;

&lt;h4&gt;
  
  
  Template Literal Types
&lt;/h4&gt;

&lt;p&gt;TypeScript also supports Template Literal Types which builds on top of &lt;code&gt;string&lt;/code&gt; literal type. It enables creating types from interpolated strings. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;de&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TypeScript Handbook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Functional Programming&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BookCategories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we're creating "internationalized" – a German and English – versions of the book type. The generated types on hovering is a &lt;code&gt;union&lt;/code&gt; type of each &lt;code&gt;lang&lt;/code&gt; and &lt;code&gt;book&lt;/code&gt;, i.e.: &lt;code&gt;"TypeScript Handbook_en" | "TypeScript Handbook_de" | "Functional Programming_en" | "Functional Programming_de"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Template literal types can be taken to another level be manipulated by conversion to uppercase, lowercase, un-capitalization, and capitalization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TypeScript Handbook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;lowercaseBook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Lowercase&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of &lt;code&gt;lowercaseBook&lt;/code&gt; is &lt;code&gt;"typescript handbook"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is all just a tip of the iceberg of what Type manipulation with TypeScript looks like. &lt;/p&gt;

&lt;p&gt;You can explore the TypeScript documentation and learn more on types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/generics.html" rel="noopener noreferrer"&gt;Generics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/keyof-types.html" rel="noopener noreferrer"&gt;&lt;code&gt;keyof&lt;/code&gt; Type Operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/typeof-types.html" rel="noopener noreferrer"&gt;&lt;code&gt;typeof&lt;/code&gt; Type Operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html" rel="noopener noreferrer"&gt;Indexed Access Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/conditional-types.html" rel="noopener noreferrer"&gt;Conditional Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html" rel="noopener noreferrer"&gt;Mapped Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html" rel="noopener noreferrer"&gt;Template Literal Types&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82c0po4j32wkqkx2b1u0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82c0po4j32wkqkx2b1u0.gif" alt="Steve Balmer Yelling"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Should probably have spent more time reading the docs and not making gifs&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pursuing projects
&lt;/h3&gt;

&lt;p&gt;This is more of a technical skill but I feel like it still falls under the soft skills.&lt;/p&gt;

&lt;p&gt;Advice from my manager was to work on other projects on the side. It is not compulsory and I don't mean that you should sacrifice your time.&lt;/p&gt;

&lt;p&gt;Working on other projects besides work would potentially expose you to new technology and or features of the programming language you're using. Projects may require you to read someone else's code and gain a better understanding of how and why the thing was built the way it is.&lt;/p&gt;

&lt;p&gt;An alternative to side projects is contributing to existing open-source projects.&lt;/p&gt;

&lt;p&gt;This week has been mind blowing watching my manager tackle tasks in 20 minutes that took me a day. It all seemed like magic – especially the TypeScript stuff – but it's all practice and experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next?
&lt;/h2&gt;

&lt;p&gt;It's definitely getting more familiar with TypeScript and digging deeper into the &lt;a href="https://www.typescriptlang.org/docs/handbook/intro.html" rel="noopener noreferrer"&gt;TypeScript Handbook&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;A TS cheat sheet maybe? A project?&lt;/p&gt;

&lt;p&gt;🤞🏽 this week I win a fight with the TS compiler. I mean, what are the odds? &lt;/p&gt;

&lt;p&gt;There's always a lot to learn. It's one step at a time and be patient with the process.&lt;/p&gt;

&lt;p&gt;Till next week. ✌🏽&lt;/p&gt;

</description>
    </item>
    <item>
      <title>SE Internship Log[0]</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Mon, 26 Jul 2021 06:50:10 +0000</pubDate>
      <link>https://dev.to/ruheni/se-internship-log-0-34c5</link>
      <guid>https://dev.to/ruheni/se-internship-log-0-34c5</guid>
      <description>&lt;p&gt;Hello there internet stranger, 👋🏽&lt;/p&gt;

&lt;p&gt;Software engineering can be daunting. This may be true if it's your first time working as a software engineer.&lt;/p&gt;

&lt;p&gt;For the summer of 2021, I'll be interning in one of the engineering teams at &lt;a href="https://www.prisma.io"&gt;Prisma&lt;/a&gt;. I'll share a summary of my learning experience – technical and soft skills – on a weekly basis for a number of reasons. &lt;/p&gt;

&lt;p&gt;One, this is a great opportunity to document my learning experience. This would also serve as a reminder to my future self or whoever stumbles on this article.&lt;/p&gt;

&lt;p&gt;Two, if you happen to doubt yourself, I hope you find some comfort that you're not alone. We're all in this together and true growth takes time. 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Type-Only imports and exports
&lt;/h3&gt;

&lt;p&gt;This week, I learned about &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export"&gt;type-only imports and exports&lt;/a&gt;. It was introduced in TypeScript version 3.8.&lt;/p&gt;

&lt;p&gt;Type-only imports and exports let the TypeScript compiler know that you're only interested in type declarations. The type-declarations won't be included in the build output. &lt;/p&gt;

&lt;p&gt;This feature is be useful in development when you're only interested in inferring types from a library but not shipping it in your application bundle.&lt;/p&gt;

&lt;p&gt;The syntax would resemble something like this in your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// type-only import&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;types&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/** logic here */&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// type-only export&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Design systems
&lt;/h3&gt;

&lt;p&gt;Building good and reusable components is hard. The complexity of components grow over time with changing product requirements.&lt;/p&gt;

&lt;p&gt;When you're building your frontend application, you may have two choices – adopt an existing design system/ styling library such as Bootstrap and Bulma or design and build the components on your own.&lt;/p&gt;

&lt;p&gt;Adopting an existing system offers the advantage of not worrying about styling. The downside is that, when your application will require a custom component, building it to match the existing style may be &lt;em&gt;a little&lt;/em&gt; tricky. Plus, there's the "Bootstrap effect" and your application may be bland because it will resemble many sites on the internet.&lt;/p&gt;

&lt;p&gt;Enter design systems! Now this is not easy, but definitely makes your application, website, web app stand out from the rest. A number of factors to be considered include theming, typography, layouts, icons, internationalization(i18n) and most importantly &lt;strong&gt;accessibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/WU0J9RYTNjKa6XrqB3/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/WU0J9RYTNjKa6XrqB3/giphy.gif" alt="Inclusion and Accessibility for all"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Accessibility
&lt;/h4&gt;

&lt;p&gt;According to &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility"&gt;MDN&lt;/a&gt;, accessibility is the practice of making websites/ applications usable by as many people as possible. This includes people with disabilities – cognitive, mobility, hearing, and visual impairments. Sometimes we assume our users will be like us and accessibility becomes an afterthought. It happens, but this is a grave mistake that would hurt your users.&lt;/p&gt;

&lt;p&gt;The design and development process should conform to the &lt;a href="https://www.w3.org/WAI/standards-guidelines/"&gt;Web Content Accessibility Guidelines (WCAG)&lt;/a&gt;. It states how to make your content more accessible and design guidelines when building an application. For example, making input fields, dialogs, and menus keyboard accessible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://react-spectrum.adobe.com/react-aria/index.html"&gt;React-Aria&lt;/a&gt; provides a set of React hooks that allow you to add behavior and interaction in your React components. It follows the &lt;a href="https://www.w3.org/TR/wai-aria-practices-1.2/"&gt;WAI-ARIA Authoring practices&lt;/a&gt; that provides accessibility out of the box. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The Adobe team built react-aria and use it in their design system – &lt;a href="https://react-spectrum.adobe.com/react-spectrum/index.html"&gt;react spectrum&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're looking to build a design system, react-aria will enable you to build accessible-first components. It doesn't ship with any styling, giving you the freedom to explore your artistic side. 😜&lt;/p&gt;

&lt;h2&gt;
  
  
  Soft Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Be confident - don't put yourself down
&lt;/h3&gt;

&lt;p&gt;In the software engineering field, it's common to experience Imposter Syndrome. The feeling that you're not good enough or don't deserve what you get. You may also feel overwhelmed from every once in a while. And it's okay.&lt;/p&gt;

&lt;p&gt;Despite your background and level of experience, everyone has something to offer. Be you and your team will appreciate that. Remember not to compare yourself with others and be open to learning and taking up any kind of task. That's how you'll grow.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't compare yourself with other people; compare yourself with who you were yesterday&lt;/p&gt;

&lt;p&gt;– Jordan Peterson&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You got this. 💪🏾&lt;/p&gt;

&lt;h3&gt;
  
  
  Asking for feedback
&lt;/h3&gt;

&lt;p&gt;Candid feedback is good. Feedback from a team member or manager will help you evaluate your growth, understand your weaknesses, and develop goals to grow your career.&lt;/p&gt;

&lt;p&gt;1:1s with your manager can help you get on the same page with your manager on goals, overcome the daunting feeling when you're new, and motivate you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What comes next?
&lt;/h2&gt;

&lt;p&gt;I have no idea. Could be breaking prod, dropping all tables... it's all uncertain. I look forward to learning more and sharing it with you folks. &lt;/p&gt;

&lt;p&gt;Till next week. ✌🏽&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover photo by &lt;a href="https://unsplash.com/@bozhstudio?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Vadim Bozhko&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/note-taking?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>a11ly</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Reliable, Scalable, and Maintainable Applications</title>
      <dc:creator>Ruheni Alex</dc:creator>
      <pubDate>Thu, 08 Apr 2021 08:11:08 +0000</pubDate>
      <link>https://dev.to/ruheni/reliable-scalable-and-maintainable-applications-3ale</link>
      <guid>https://dev.to/ruheni/reliable-scalable-and-maintainable-applications-3ale</guid>
      <description>&lt;p&gt;Hello friends 👋🏾&lt;/p&gt;

&lt;p&gt;These are my notes on &lt;a href="https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable-ebook/dp/B06XPJML5D"&gt;Designing Data-Intensive Applications&lt;/a&gt; by &lt;a href="https://twitter.com/martinkl"&gt;Martin Kleppmann&lt;/a&gt;. The book is an incredible read and would recommend you pick up your copy.&lt;/p&gt;

&lt;p&gt;The purpose of sharing this is to keep myself accountable - making sure I read -, share what I learn, make sure what I learn sticks, and serve as a reference to future me.&lt;/p&gt;

&lt;p&gt;I don't have a lot of experience building applications at scale and therefore my notes may contain a lot of content. I hope this summary will be of value to you too. 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability
&lt;/h2&gt;

&lt;p&gt;Software is deemed reliable depending on its ability to tolerate faults, function as expected, ensure the right level of authorization access, and have reasonable performance for its tasks.&lt;/p&gt;

&lt;p&gt;Not all faults and failures can be captured. &lt;/p&gt;

&lt;h3&gt;
  
  
  Types of faults
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware faults&lt;/strong&gt; - e.g., hard drive corruption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Software errors&lt;/strong&gt; - e.g., unhandled exceptions for error handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Systematic errors&lt;/strong&gt;: these are errors within a system - correlated with areas across nodes in a system, e.g., the &lt;a href="https://www.wired.com/2012/07/leap-second-glitch-explained/"&gt;leap second glitch&lt;/a&gt; that caused an outage of popular web services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human error&lt;/strong&gt; - e.g., having faulty configuration during deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inducing faults helps in capturing faults, improving the reliability of an application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making systems more reliable
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System design&lt;/strong&gt; - this reduces opportunity and can include patterns such as having well-designed abstractions, APIs, and admin interfaces make it easy doing the right thing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox environments&lt;/strong&gt; - these are environments for battle testing applications before moving to production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt; - using unit, integration, and end-to-end tests taking software to the extreme to capture "edge cases" users may encounter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Telemetry&lt;/strong&gt; - using monitoring software to track usage, exceptions, and application performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scalability
&lt;/h2&gt;

&lt;p&gt;This is a software's ability to cope with an increased load within a given set of parameters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TIL: &lt;strong&gt;Tail latency amplification&lt;/strong&gt;: An instance where a request gets slower because it is dependent on other calls (e.g., to other services or APIs).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Monitoring the performance of an application can be done in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Option A&lt;/strong&gt;: Keeping a log of requests/ responses every 10 minutes, detailing the response times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Option B&lt;/strong&gt;: Collecting all requests/responses and sorting through them every 10 minutes. This may be a naïve approach, and you can sort through them every 10 minutes using the following algorithms: 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/tdunning/t-digest"&gt;T-Digest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dimacs.rutgers.edu/~graham/pubs/papers/fwddecay.pdf"&gt;Forward Decay&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://hdrhistogram.org/"&gt;HDR Histogram&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Maintaining performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rethinking system architecture&lt;/strong&gt; - taking a different approach on how systems can be scaled. There are two scaling "models": scaling up (vertical scaling) and scaling out(horizontal scaling) alias shared-nothing architecture. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elastic systems&lt;/strong&gt; - having systems that can either be manually or automatically scaled under a load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no &lt;em&gt;magic scaling sauce&lt;/em&gt; or a one-size-fits-all architecture for designing scalable systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintainability
&lt;/h2&gt;

&lt;p&gt;This refers to designing software that makes it less painful to maintain in the long run. Maintainability helps ensure developers avoid building legacy software. No one likes legacy systems. 🤷🏾‍♂️&lt;/p&gt;

&lt;p&gt;While writing this summary, the following &lt;a href="https://twitter.com/pati_gallardo/status/1379464931859386374"&gt;tweet&lt;/a&gt; resonated:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bZA6p66n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33921841/113774368-d5bb2180-972f-11eb-8526-2da1b41a622e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bZA6p66n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/33921841/113774368-d5bb2180-972f-11eb-8526-2da1b41a622e.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To ensure maintainability, development teams have to follow a couple of design principles when building systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operability&lt;/strong&gt; - refers to making a system easy to run (making life easy for the operations team).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt; - refers to the ability to manage complexity when building a platform, e.g., creating abstractions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evolvability&lt;/strong&gt; - refers to adapting software for future needs such as new features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cheers, and stay tuned for more. 📣&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>database</category>
      <category>distributedsystems</category>
    </item>
  </channel>
</rss>
