<?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: cychu42</title>
    <description>The latest articles on DEV Community by cychu42 (@cychu42).</description>
    <link>https://dev.to/cychu42</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%2F923219%2F070b3424-6f91-4ff2-bbfe-0433e25957c2.jpeg</url>
      <title>DEV Community: cychu42</title>
      <link>https://dev.to/cychu42</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cychu42"/>
    <language>en</language>
    <item>
      <title>Starchart: 1.0.0 Release</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 21 Apr 2023 14:42:01 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-100-release-1el7</link>
      <guid>https://dev.to/cychu42/starchart-100-release-1el7</guid>
      <description>&lt;h2&gt;
  
  
  Working Toward First Release
&lt;/h2&gt;

&lt;p&gt;Finally, the &lt;a href="https://github.com/DevelopingSpace/starchart"&gt;Starchart project&lt;/a&gt; has reached 1.0.0 release!&lt;/p&gt;

&lt;p&gt;After the handwork of the team, we managed to have it running on staging and then production. We encountered issues, such as incorrect AWS credential in production, having to deal with certificate request duplication (See &lt;a href="https://github.com/DevelopingSpace/starchart/pull/652"&gt;PR&lt;/a&gt;), and splitting Docker image deployment between staging and production (See &lt;a href="https://github.com/DevelopingSpace/starchart/pull/639"&gt;PR&lt;/a&gt;), but it's working now!&lt;/p&gt;

&lt;p&gt;In the previous week, I was working on code for migration for both staging and production, as mentioned in the &lt;a href="https://dev.to/cychu42/starchart-migration-3mba"&gt;previous blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This week, I made &lt;a href="https://github.com/DevelopingSpace/starchart/pull/630"&gt;a PR&lt;/a&gt; to remove all mentions of &lt;code&gt;deactivated&lt;/code&gt; user field, as well as related functions: &lt;code&gt;deactivateUserByUsername&lt;/code&gt;, and &lt;code&gt;isUserDeactivated&lt;/code&gt;.&lt;br&gt;
This is because we decided we no longer need it and would simply delete user, which would cascade the delete to all DNS records and certificates belonged to the user, due to &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#cascade"&gt;how&lt;/a&gt; it's set up in Prisma schema. Then, the &lt;a href="https://github.com/DevelopingSpace/starchart/pulls?q=is%3Apr+reconciler"&gt;reconciler code&lt;/a&gt; would sync the changes with &lt;a href="https://aws.amazon.com/route53/"&gt;AWS Route 53&lt;/a&gt; we use.&lt;br&gt;
The PR is important because it changes schema, and the migration code from my previous work successfully perform migration to update the databases in staging and production.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reflection: The Work
&lt;/h2&gt;

&lt;p&gt;I'm glad I had this experience and know that this is something I can do. It was great to be part of a team and build a project from the ground up, which is very valuable to me as a developer. When it started, I choose to be the expert on the database side of the project, because I'm interested in database and the management. While the actual maintenance is handled by Seneca ITS, I still got to work with database and have the experience of being the go-to person for that area on the team.&lt;/p&gt;

&lt;p&gt;I got to learn new technologies, such as &lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt;, and use them for the project. It's nice to experience having to pick up new technologies to work on a project, which I imagine won't be the last time I do it.&lt;/p&gt;

&lt;p&gt;The people on the team are great. They are open and helpful. When you step out of of specialty on a project, it can be a bi intimidating to pick up what has been done in other areas of the project, and having someone who's willing to walk you through their area and answer your question is very valuable for the process and learning. I'm thankful for all the teammates who gave me a hand.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reflection: Prisma
&lt;/h2&gt;

&lt;p&gt;Prisma is the chosen tool for bridging the rest of the code and the database, and it has been pretty pleasant to use. Partially due to use of &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;, it's very robust in catching mistakes even before you have to run tests for your code. It also simplifies the work of issuing SQL statements interact with database. For example, instead of writing a lot of SQL statements to create a table, you can just code a visual layout with far less things, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model DnsRecord {
  id           Int             @id @default(autoincrement())
  username     String
  subdomain    String
  type         DnsRecordType
  value        String
  description  String?
  course       String?
  ports        String?
  challengeId  Int?
  createdAt    DateTime        @default(now())
  updatedAt    DateTime        @updatedAt
  expiresAt    DateTime
  lastNotified DateTime?
  challenge    Challenge?      @relation(fields: [challengeId], references: [id], onDelete: Cascade)
  user         User            @relation(fields: [username], references: [username], onDelete: Cascade)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrote about how this work in &lt;a href="https://dev.to/cychu42/startchart-prisma-schema-4i6d"&gt;another blog post&lt;/a&gt; when working on the first iteration of this schema.&lt;br&gt;
It's easy to write and see visually. The varies &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-client/crud#create"&gt;Prisma API calls&lt;/a&gt; also lets you interact with database from rest of your code in a project.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>prisma</category>
    </item>
    <item>
      <title>Starchart: Migration!</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 14 Apr 2023 01:05:48 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-migration-3mba</link>
      <guid>https://dev.to/cychu42/starchart-migration-3mba</guid>
      <description>&lt;p&gt;This week, I created worked on utilized Prisma migration for &lt;a href="https://github.com/DevelopingSpace/starchart"&gt;Starchart&lt;/a&gt; project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Work
&lt;/h2&gt;

&lt;p&gt;This &lt;a href="https://github.com/DevelopingSpace/starchart/pull/601"&gt;PR&lt;/a&gt; allows staging and production to use &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-migrate"&gt;Prisma migration&lt;/a&gt;, through deploying migration files. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add migration in &lt;code&gt;docker-entrypoint.sh&lt;/code&gt;, when environment variable &lt;code&gt;DATABASE_SETUP=1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add migration file creation script, with required permission, in &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create an initial migration file in &lt;code&gt;prisma/migrations&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add documentation for making migration files in &lt;code&gt;DEPLOY.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Adjust docker deployment for update&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Update (April 20, 2023):&lt;/em&gt; we later decided to change &lt;code&gt;DATABASE_SETUP&lt;/code&gt; to &lt;code&gt;DANGER_DATABASE_WIPE_REINITIALIZE&lt;/code&gt; in this PR to warn future devs about turning this variable on.&lt;/p&gt;

&lt;p&gt;Essentially, a migration file is essentially a set of SQL queries Prisma generates that would get a database to a desired state, by comparing your current schema and the latest migration file. Think of Prisma migration as git tracking your commits. For more details, see &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-migrate/mental-model"&gt;Prisma documentation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Migration normally keep data in the database while updating the database schema. A part of this is done through shell script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shell Script Snippet (&lt;a href="https://github.com/DevelopingSpace/starchart/pull/601/files#diff-79738685a656fe6b25061bb14181442210b599f746faeaba408a2401de45038a"&gt;file from the PR&lt;/a&gt;)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;database_setup() {
  echo "Running database reset and setup..."
  DATABASE_URL=$(&amp;lt;/run/secrets/DATABASE_URL)
  export DATABASE_URL

  npx prisma migrate reset --force --skip-seed

  unset DATABASE_URL
  echo "Database setup complete"
}

database_migration() {
  echo "Running database migration..."
  DATABASE_URL=$(&amp;lt;/run/secrets/DATABASE_URL)
  export DATABASE_URL

  npx prisma migrate deploy

  unset DATABASE_URL
  echo "Database migration complete"
}

if [[ $DATABASE_SETUP == "1" ]]; then
  database_setup
  clear_redis

else
  database_migration
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only when &lt;code&gt;DATABASE_SETUP =1&lt;/code&gt; is an environment variable, we would wipes the existing database and apply migration files with &lt;code&gt;database_setup&lt;/code&gt;. &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference#migrate-reset"&gt;&lt;code&gt;npx prisma migrate reset --force --skip-seed&lt;/code&gt;&lt;/a&gt; resets/wipes the database and applies migration files, and Prisma would know what migration is applied already and skip them, instead of causing conflict.&lt;br&gt;
&lt;code&gt;--force&lt;/code&gt; skips confirmation, and &lt;code&gt;--skip-seed&lt;/code&gt; skips seeding.&lt;/p&gt;

&lt;p&gt;Otherwise, &lt;code&gt;database_migration&lt;/code&gt; applies migration files for normal database updates, assuming no changes to the database schema is done without Prisma migration. &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference#migrate-deploy"&gt;&lt;code&gt;npx prisma migrate deploy&lt;/code&gt;&lt;/a&gt; deploys migration files to change schema without deleting data.&lt;/p&gt;

&lt;p&gt;In both &lt;code&gt;database_migration()&lt;/code&gt; and &lt;code&gt;database_setup()&lt;/code&gt;, we pull the database URL out of secrets, since Prisma requires it to know which database to connect to. After using it, we clear that variable.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating A Migration File For Schema Change
&lt;/h2&gt;

&lt;p&gt;Because staging and production use Prisma migration, changes in the schema need to become migration files for Prisma migration to run the files to apply changes, via &lt;a href="https://www.prisma.io/docs/reference/api-reference/command-reference#migrate-dev"&gt;&lt;code&gt;prisma migrate dev --create-only --skip-seed&lt;/code&gt;&lt;/a&gt;. It would ask for a name for the file.&lt;br&gt;
The script doesn't seed database or apply migration, just creating a migration file and also generating Prisma client (default behavior) in case a dev forgets.&lt;/p&gt;

&lt;p&gt;When Prisma creates a migration file, it requires permission to create a temporary shadow database in a database to do this, which means a user of said database needs &lt;code&gt;CREATE&lt;/code&gt;, &lt;code&gt;ALTER&lt;/code&gt;, &lt;code&gt;DROP&lt;/code&gt;, and &lt;code&gt;REFERENCES&lt;/code&gt; privilege to do this. Make sure such user is used for &lt;code&gt;DATABASE_URL&lt;/code&gt; environment variable that Prisma use to connect to a database.&lt;/p&gt;
&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;We have multiple instance for production and staging, using Docker.&lt;br&gt;
While Prisma does have &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-migrate/migrate-development-production#advisory-locking"&gt;advisory locking&lt;/a&gt;, which would skip repeated deploy within last 10 seconds (can't be configured), it's probably safer to run only one instance to initiate changes to database schema, then bring up the other instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Snippet:&lt;/strong&gt; (&lt;a href="https://github.com/DevelopingSpace/starchart/pull/601/files#diff-15f21dad8b8f4edc4748223f6f275c8b4bb7a406a9aedcb4c05ec88123089de1"&gt;file from the PR&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    deploy:
    ...
      update_config:
        parallelism: 1
        delay: 20s
        failure_action: rollback
        order: stop-first
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the relevant change in our &lt;a href="https://docs.docker.com/compose/"&gt;docker-compose&lt;/a&gt; YAML files for staging and production.&lt;br&gt;
It would stop existing containers, and then update one container at a time. It would waiting 20 seconds in-between. If something fails, it would rollback.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>prisma</category>
      <category>docker</category>
    </item>
    <item>
      <title>Recycle Code: CNAME &amp; Re-request</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 07 Apr 2023 09:15:52 +0000</pubDate>
      <link>https://dev.to/cychu42/recycle-code-cname-re-request-3c1f</link>
      <guid>https://dev.to/cychu42/recycle-code-cname-re-request-3c1f</guid>
      <description>&lt;h2&gt;
  
  
  Recycle Code
&lt;/h2&gt;

&lt;p&gt;This week, I did some work on the &lt;a href="https://github.com/DevelopingSpace/starchart"&gt;Starchart&lt;/a&gt; project where I reuse existing codes to accomplish my tasks. It's always a neat feeling when I find out how I can leverage existing code to achieve a task.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Duplicate CNAME!
&lt;/h2&gt;

&lt;p&gt;The Starchart project allows user to easily create &lt;a href="https://www.cloudflare.com/learning/ssl/what-is-an-ssl-certificate/"&gt;SSL certificate&lt;/a&gt; by taking care of a lot of required steps. Under a certificate, users can have multiple &lt;a href="https://www.cloudflare.com/learning/dns/dns-records/"&gt;DNS Records&lt;/a&gt;.&lt;br&gt;
By design, CNAME DNS Records forward you from one domain to another, so it makes little sense to have two CNAME DNS Records forwarding you from one same domain to two other domains at the same time.&lt;/p&gt;

&lt;p&gt;Because of this, we need to prevent users from creating these kind of duplicate CNAME records.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Small Restriction
&lt;/h2&gt;

&lt;p&gt;I added &lt;a href="https://github.com/DevelopingSpace/starchart/pull/542"&gt;a piece of code&lt;/a&gt; to achieve that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const count = await prisma.dnsRecord.count({
    where: {
      username,
      type,
      subdomain,
      value: type === 'CNAME' ? undefined : value,
    },
  });

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

&lt;/div&gt;



&lt;p&gt;The project already has some code to check for existing DNS records that are the same with the name, type, and value. Name is the subdomain name. Type is the type of record, such as CNAME. Value would be things like IP address or domain, depending on the type of DNS record.&lt;/p&gt;

&lt;p&gt;Most of the relevant code already exist to check for count of duplicate DNS record, and I ended up adding a condition to not care about whether value is the same for CNAME records. As long as an existing CNAME record belongs to the same user and has same subdomain, another one counts as a duplicate. The value doesn't matter. These two criteria are chosen because username and subdomain name are used to create the domain name where a CNAME record would redirect people from, in this project.&lt;br&gt;
Recall that we don't want to redirect from one domain to multiple domain. This is why we check for CNAME records with same user and subdomain.&lt;/p&gt;

&lt;p&gt;It utilizes Prisma's &lt;a href="https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#count"&gt;&lt;code&gt;count&lt;/code&gt;&lt;/a&gt; to do the counting in the database. &lt;code&gt;where&lt;/code&gt; specifies what criteria for a row to count.&lt;/p&gt;
&lt;h2&gt;
  
  
  Re-request Certificate
&lt;/h2&gt;

&lt;p&gt;Speaking of certificate, I also did a &lt;a href="https://github.com/DevelopingSpace/starchart/pull/533"&gt;PR&lt;/a&gt; with a teammate together with &lt;a href="https://en.wikipedia.org/wiki/Pair_programming"&gt;peer programming&lt;/a&gt;, to add the ability for users to re-request a new certificate when it's about to expire.&lt;/p&gt;
&lt;h2&gt;
  
  
  What we did
&lt;/h2&gt;

&lt;p&gt;The code checks for whether a certificate's &lt;code&gt;validTo&lt;/code&gt; date is less than 30 days from present. If so, a re-request button will become available on the certificate page to allow the user to request another certificate.&lt;br&gt;
Because we already have existing code to allow users to request their first certificate, we simply use/trigger that code again for the button.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Snippet for the button:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              &amp;lt;Flex justifyContent="flex-end"&amp;gt;
                &amp;lt;Form method="post" onSubmit={() =&amp;gt; setIsDisabled(true)}&amp;gt;
                  &amp;lt;IconButton
                    type="submit"
                    aria-label="renew-certificate"
                    icon={&amp;lt;RepeatIcon /&amp;gt;}
                    backgroundColor="transparent"
                    color="black"
                    _hover={{ backgroundColor: 'brand.500', color: 'white' }}
                    isDisabled={isDisabled}
                  /&amp;gt;
                &amp;lt;/Form&amp;gt;
              &amp;lt;/Flex&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the certificate request code is under an action function build with &lt;a href="https://remix.run/"&gt;remix.js&lt;/a&gt;, and it's triggered by submit, we simply make this new button submit to reuse that code.&lt;/p&gt;

&lt;p&gt;We did found out a minor bug where the program was only recognizing the second newest certificate for a user, because the code was sorting certificates by &lt;code&gt;validTo&lt;/code&gt; date in descending order, to fetch the newest one, but a really new one would not have that field filled out for a short period. This caused the new certificate to be placed at the bottom of the sorting and not be select as the current certificate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Peer programming
&lt;/h2&gt;

&lt;p&gt;It's interesting sitting with another developer to work on code together. You get tow different perspectives, and you can learn form each other, whether it's expertise with tools and languages, coding style, or new ideas.&lt;/p&gt;

&lt;p&gt;Because I'm unfamiliar with the front-end of the project, it was very helpful to sit with another developer who is familiar with that area.&lt;br&gt;
He walked me through how the area of the front-end code we wanted to work on is constructed, and we put our ideas together to figure out how to tackle the issue.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Creating Releases And Returned Error</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Sat, 01 Apr 2023 00:17:03 +0000</pubDate>
      <link>https://dev.to/cychu42/creating-releases-and-returned-error-ob4</link>
      <guid>https://dev.to/cychu42/creating-releases-and-returned-error-ob4</guid>
      <description>&lt;h2&gt;
  
  
  Tasks
&lt;/h2&gt;

&lt;p&gt;This week, for the &lt;a href="https://github.com/DevelopingSpace/starchart" rel="noopener noreferrer"&gt;Starchart&lt;/a&gt; project, I added some explanation to how to create releases in GitHub repo, and I added some tests too.&lt;/p&gt;

&lt;p&gt;I wanted to mention how to create releases because I noticed multiple people have been asking how to do it. It seems like a good idea to add some pointers in the wiki.&lt;/p&gt;

&lt;p&gt;As for test, thing are quite usual except one interesting bug I found. (&lt;a href="https://github.com/DevelopingSpace/starchart/pull/483" rel="noopener noreferrer"&gt;PR&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Create GitHub Releases
&lt;/h2&gt;

&lt;p&gt;This is about making a release version of your application from your GitHub repo, in the repo's release page. This will generate copies of the source code for download, in the release.&lt;br&gt;
GitHub has &lt;a href="https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; on how to manage releases, including creating one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Page to create a release looks like this:&lt;/strong&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2izxq5ak05kjbjtct61k.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%2F2izxq5ak05kjbjtct61k.png" alt="Release Creation Page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assuming you have the access, you do it by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click "Releases" on a repo's main page, then click "Draft a new release" to get to the page shown.&lt;/li&gt;
&lt;li&gt;Choose or create a tag, which can be a version.&lt;/li&gt;
&lt;li&gt;Choose a branch, which might be main.&lt;/li&gt;
&lt;li&gt;Give it a title and some description of what's added/changed. You can click "Generate release notes" to get some information from GitHub, including contributors, change log, and newly committed PRs.&lt;/li&gt;
&lt;li&gt;You can set it as pre-release or latest release. You can even allow discussion under the release note.
6.(Optional) You can attach some files to the release.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;As part of making a release, you might increment project version for a release. You can use CLI command &lt;a href="https://docs.npmjs.com/cli/v8/commands/npm-version" rel="noopener noreferrer"&gt;&lt;code&gt;npm version&lt;/code&gt;&lt;/a&gt; in the project directory.&lt;/p&gt;

&lt;p&gt;For example, assuming you have initialized npm and git, &lt;code&gt;npm version 0.8.0 -m "sample commit"&lt;/code&gt; will change the version in &lt;code&gt;package.json&lt;/code&gt; and create a new commit with the commit message &lt;code&gt;sample commit&lt;/code&gt; by &lt;code&gt;-m&lt;/code&gt; option. This new commit will have a tag &lt;code&gt;v0.8.0&lt;/code&gt;, which you can use for creating a release.&lt;/p&gt;

&lt;p&gt;NOTE: locally created tags don't exist on GitHub repo unless you push them. To push the commit with the tag, you can &lt;code&gt;push&lt;/code&gt; with &lt;code&gt;--tags&lt;/code&gt; flag, such as &lt;code&gt;git push origin main --tags&lt;/code&gt;. For more information on tags, see &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Odd Bug
&lt;/h2&gt;

&lt;p&gt;While writing a test, I noticed an odd behavior when I tested this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function setIsReconciliationNeeded(
  reconciliationNeeded: SystemState['reconciliationNeeded']
) {
  try {
    return prisma.systemState.update({
      data: { reconciliationNeeded },
      where: { unique: StateEnumType.unique },
    });
  } catch (error) {
    return initialize();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is meant to update a row in the &lt;code&gt;SystemState&lt;/code&gt; table, to set &lt;code&gt;reconciliationNeeded&lt;/code&gt; field by the parameter, which is Boolean (True/False). It uses Prisma's &lt;a href="https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#update" rel="noopener noreferrer"&gt;&lt;code&gt;Update&lt;/code&gt;&lt;/a&gt; function to do the update.&lt;br&gt;
The main and interest point is that this &lt;code&gt;try&lt;/code&gt; block will not catch errors throw by [&lt;code&gt;Update&lt;/code&gt;] when it fails to find such row, such as when it simply doesn't exist.&lt;br&gt;
Given that the documentation states the function returns the exception when it can't find the target to update, my guess was that it's returning the error from the function with the &lt;code&gt;return&lt;/code&gt; keyword, which makes the error land outside of the &lt;code&gt;try&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;The expected behavior is to catch the error and then call and return &lt;code&gt;initialize&lt;/code&gt;.&lt;br&gt;
Therefore, I tried to avoid having return in the &lt;code&gt;try&lt;/code&gt; block by doing it later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export async function setIsReconciliationNeeded(
  reconciliationNeeded: SystemState['reconciliationNeeded']
) {
  let result;
  try {
    result = await prisma.systemState.update({
      data: { reconciliationNeeded },
      where: { unique: StateEnumType.unique },
    });
  } catch (error) {
    return initialize();
  }
  return result;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the &lt;code&gt;try&lt;/code&gt; block properly catches the error and execute the &lt;code&gt;catch&lt;/code&gt; block.&lt;br&gt;
Alternatively, a teammate come up with another solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function setIsReconciliationNeeded(
  reconciliationNeeded: SystemState['reconciliationNeeded']
) {
  return prisma.systemState
    .update({
      data: { reconciliationNeeded },
      where: { unique: StateEnumType.unique },
    })
    .catch(() =&amp;gt; {

      return initialize();
    });
}

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

&lt;/div&gt;



&lt;p&gt;This one instead deal with the error before the code hits &lt;code&gt;return&lt;/code&gt;. The error is caught in &lt;code&gt;catch&lt;/code&gt; and dealt with, before anything goes to &lt;code&gt;return&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>testing</category>
      <category>prisma</category>
    </item>
    <item>
      <title>Starchart: 1,2,3, Testing!</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 24 Mar 2023 16:30:32 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-123-testing-58f8</link>
      <guid>https://dev.to/cychu42/starchart-123-testing-58f8</guid>
      <description>&lt;h2&gt;
  
  
  What is it?
&lt;/h2&gt;

&lt;p&gt;After having &lt;a href="https://dev.to/cychu42/starchart-mocking-a-database-part-2-2a88"&gt;created a test database&lt;/a&gt; for the &lt;a href="https://github.com/DevelopingSpace/starchart"&gt;Starchart project&lt;/a&gt;, I went on to working on tests for functions relate to Prisma API calls. (See &lt;a href="https://github.com/DevelopingSpace/starchart/pull/415"&gt;PR&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://vitest.dev/"&gt;Vitest&lt;/a&gt; for unit testing, which is very similar to &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt;. A test suite looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe('createUser()', () =&amp;gt; {
  let user: User;

  beforeAll(async () =&amp;gt; {
    user = await createUser(
      'jsmith',
      'John Smith',
      'jsmith@myseneca.ca',
      'mycustomdomain-students'
    );
  });

  afterAll(async () =&amp;gt; {
    await prisma.user.deleteMany().catch(() =&amp;gt; {});
  });

  test('creates an User row with expected fields', async () =&amp;gt; {
    expect(typeof user).toEqual('object');
    expect(user.username).toEqual('jsmith');
    expect(user.displayName).toEqual('John Smith');
    expect(user.email).toEqual('jsmith@myseneca.ca');
    expect(user.group).toEqual('mycustomdomain-students');
    expect(user.createdAt).not.toBe(null);
    expect(user.createdAt).toEqual(user.updatedAt);
    expect(user.deactivated).toBe(false);
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;describe()&lt;/code&gt; is a test suite, which can include many related individual &lt;code&gt;test()&lt;/code&gt;s. Both let you include a string to state what it's for, which will show up in a formatted display when you run tests.&lt;br&gt;
&lt;code&gt;beforeAll()&lt;/code&gt; is a block of code that executes &lt;strong&gt;before&lt;/strong&gt; all tests of a suite is ran, which can be handy for setting up things, like creating an user for testing.&lt;br&gt;
&lt;code&gt;afterAll()&lt;/code&gt; is a block of code that executes &lt;strong&gt;after&lt;/strong&gt; all tests of a suite is ran, which can be handy for clean-up, like deleting all existing user.&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;expect()&lt;/code&gt; is a condition that must be satisfied for a test to pass. The code is more or like like plain English language, such as &lt;code&gt;expect(user.createdAt).not.toBe(null);&lt;/code&gt; really means expecting &lt;code&gt;user.createdAt&lt;/code&gt; to not be null. You can find all the syntax in &lt;a href="https://vitest.dev/api/expect.html"&gt;their documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can put code, such as variable declaration an function calls, under &lt;code&gt;describe()&lt;/code&gt; or &lt;code&gt;test()&lt;/code&gt;. It's just a matter of scope for what you want to do.&lt;/p&gt;




&lt;p&gt;Assuming you already setup the tool properly (see &lt;a href="https://vitest.dev/guide/"&gt;official guide&lt;/a&gt;), you can run the tests via &lt;code&gt;npx vitest&lt;/code&gt;. A result can look like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ygdCRu91--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6slp0pbnae76nwf7843.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ygdCRu91--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6slp0pbnae76nwf7843.png" alt="npx vitest results" width="880" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For seeing test coverage, run &lt;code&gt;npx vitest run --coverage&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mYpIKTln--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvynxd6jozoirs66thqr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mYpIKTln--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvynxd6jozoirs66thqr.png" alt="coverage result" width="880" height="233"&gt;&lt;/a&gt;&lt;br&gt;
As you can see, it tells you how much of the files are covered by tests, in terms of statements, branching paths, functions, and lines. It also shows uncovered lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do this?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;This provides repeatable and standardized tests that are easy to run and view. You don't have to risk making mistake or forgetting a test like when one does manual testing of codes. The tool also provide good feed back by showing you what tests fail and what files aren't covered.&lt;/li&gt;
&lt;li&gt;It's also something that can be shared in a repository and make collaboration easier.&lt;/li&gt;
&lt;li&gt;An interesting way to use this is to write out some tests and have them act as technical requirements that guide the development of code. Essentially, you write out tests that tells developers what the software is supposed to do, and the developers write codes that would satisfy these tests that act as technical requirements.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>javascript</category>
      <category>prisma</category>
      <category>opensource</category>
      <category>vite</category>
    </item>
    <item>
      <title>Starchart: "Mocking" A Database Part 2</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 17 Mar 2023 23:47:44 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-mocking-a-database-part-2-2a88</link>
      <guid>https://dev.to/cychu42/starchart-mocking-a-database-part-2-2a88</guid>
      <description>&lt;p&gt;As a continuation from &lt;a href="https://dev.to/cychu42/starchart-mocking-a-database-part-1-2kg2"&gt;the previous post&lt;/a&gt;, I managed to make the test database work.&lt;br&gt;
It's not mocking anymore, but I'm keeping the title for consistency. &lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Let's have a snippet of the &lt;code&gt;dock-compose&lt;/code&gt; YAML file, which is what I used to make the test database, so it's easier to talk about this:&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%2Fq59lgygwgmmnnncuubnu.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%2Fq59lgygwgmmnnncuubnu.png" alt="code snippet of dock-compose YAML file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This file is an instruction that will be followed to create docker containers, when you run &lt;a href="https://docs.docker.com/engine/reference/commandline/compose_up/" rel="noopener noreferrer"&gt;&lt;code&gt;docker compose up&lt;/code&gt;&lt;/a&gt; command.&lt;br&gt;
For this bit of code, it tells docker to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a container using image of MySQL version 8.x.x&lt;/li&gt;
&lt;li&gt;name it "database"&lt;/li&gt;
&lt;li&gt;bind port 3306 (left) to the container's port 3306 (right)&lt;/li&gt;
&lt;li&gt;use local machine's directory (left) as source of container's virtual directory (right), such as &lt;code&gt;./mysql-data:/var/lib/mysql&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;set certain environment variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;MYSQL_DATABASE&lt;/code&gt; indicates the database to be made with the name &lt;code&gt;starchart&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;MYSQL_USER&lt;/code&gt; and &lt;code&gt;MYSQL_PASSWORD&lt;/code&gt; are the account and password with &lt;a href="https://en.wikipedia.org/wiki/Superuser" rel="noopener noreferrer"&gt;superuser&lt;/a&gt; access to that database.&lt;br&gt;
&lt;code&gt;MYSQL_ROOT_PASSWORD&lt;/code&gt; sets the password for the &lt;code&gt;root&lt;/code&gt; user, which is a super user. Only this environment variable is mandatory.&lt;/p&gt;
&lt;h2&gt;
  
  
  SQL File for Test Database
&lt;/h2&gt;

&lt;p&gt;As you can see in that code snippet, I source a file &lt;code&gt;01-databases.sql&lt;/code&gt;, which as a few SQL commands to setup a test database on top of &lt;code&gt;starchart&lt;/code&gt; database. The file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- create test databases
CREATE DATABASE IF NOT EXISTS `starchart_test`;

-- create root user and grant rights
CREATE USER 'root'@'localhost' IDENTIFIED BY 'root_password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First line &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/create-user.html" rel="noopener noreferrer"&gt;creates&lt;/a&gt; the database if it doesn't exist already. The second line creates that user with specified password, and then it &lt;a href="https://dev.mysql.com/doc/refman/8.0/en/grant.html" rel="noopener noreferrer"&gt;grants&lt;/a&gt; all access to that user.&lt;br&gt;
When the MySQL database container is made, Docker checks for SQL files under &lt;code&gt;/docker-entrypoint-initdb.d&lt;/code&gt; to run, so these lines would be executed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was the issue?
&lt;/h2&gt;

&lt;p&gt;It turns out there were two issues with my connecting string to the test database.&lt;br&gt;
As an example:&lt;br&gt;
&lt;code&gt;DATABASE_URL="mysql://root:root_password@127.0.0.1:3306/starchart_test"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;starchart&lt;/code&gt; is the account to use to connect.&lt;br&gt;
&lt;code&gt;root_password&lt;/code&gt; is the password for the account.&lt;br&gt;
&lt;code&gt;127.0.0.1&lt;/code&gt; the IP of the database.&lt;br&gt;
&lt;code&gt;3306&lt;/code&gt; is the port.&lt;br&gt;
&lt;code&gt;starchart_test&lt;/code&gt; is the database name.&lt;/p&gt;

&lt;p&gt;First, your system might refuse to connect to a high number port to avoid suspicious ports, so I needed to set it to be lower.  A MySQL database docker container lists 2 ports: 3306 and 33060. I was trying to bind the 33060 port, which was too high, so a lower number port did the trick. Another issue was that I had the wrong name for the database. I mistakenly thought it was meant to be container name instead.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Starchart: Matching Database With SAML Claims</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Sat, 11 Mar 2023 03:04:38 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-matching-database-with-saml-claims-1mki</link>
      <guid>https://dev.to/cychu42/starchart-matching-database-with-saml-claims-1mki</guid>
      <description>&lt;h2&gt;
  
  
  Task
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/DevelopingSpace/starchart/pull/307"&gt;What I did&lt;/a&gt; this week was matching &lt;code&gt;User&lt;/code&gt; table of database in &lt;a href="https://github.com/DevelopingSpace/starchart"&gt;Starchart&lt;/a&gt; project with what useful information &lt;a href="https://en.wikipedia.org/wiki/SAML_2.0"&gt;SAML&lt;/a&gt; would return about users when users log in. &lt;br&gt;
This meant adding &lt;code&gt;group&lt;/code&gt; column in &lt;code&gt;User&lt;/code&gt; table in database, given it's one of the claims. &lt;code&gt;group&lt;/code&gt; claim is used as role assignment, such as user being part of student group, which has specific access attached to the group.&lt;br&gt;
This project uses &lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt; to interact with the database.&lt;/p&gt;

&lt;p&gt;There were 3 things I needed to do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edit the schema file (&lt;code&gt;prisma\schema.prisma&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Edit the file (&lt;code&gt;prisma\seed.ts&lt;/code&gt;) for seeding to make sure these seeded users have groups. &lt;/li&gt;
&lt;li&gt;Chang how relevant functions interact with the database, so a function that make Prisma API call to create a user would need to be changed for the addition of &lt;code&gt;group&lt;/code&gt;. When changing a function definition, one needs to remember to change how the function is used in other area of your code. For example, I changed the parameter of &lt;code&gt;createUser()&lt;/code&gt; to allow argument for &lt;code&gt;group&lt;/code&gt;, so I must change how the function is used elsewhere in the project too.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cover new use cases for the column. This meant I added 3 functions to check whether a user belongs to one of 3 groups. The functions &lt;code&gt;isStudent()&lt;/code&gt;, &lt;code&gt;isFaculty()&lt;/code&gt;, and &lt;code&gt;isAdmin()&lt;/code&gt; accept &lt;code&gt;username&lt;/code&gt; as parameter. They would return &lt;code&gt;true&lt;/code&gt; if they have the role/group, &lt;code&gt;false&lt;/code&gt; if not. The code look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt; export async function isFaculty(username: 
 PrismaUser['username']) {
   const { group } = await prisma.user.findUniqueOrThrow({ where: { username } });
   // The group will have -dev in it on staging but not on prod
   return /mycustomdomain(-dev)?-faculty/.test(group);
 }
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;code&gt;async&lt;/code&gt; marks this function as asynchronous, since it needs to interact with the database and &lt;code&gt;await&lt;/code&gt; a response.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;group&lt;/code&gt; value will be returned by the Prisma function after it fetches the user, by using the primary key &lt;code&gt;username&lt;/code&gt;. Notice typescript syntax is used to limit the type of &lt;code&gt;username&lt;/code&gt; according to Prisma &lt;code&gt;User&lt;/code&gt; model's &lt;code&gt;username&lt;/code&gt; column type.]&lt;br&gt;
 &lt;code&gt;findUniqueOrThrow()&lt;/code&gt; will throw error if nothing is found, as the function name suggests. You can see the documentation &lt;a href="https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#finduniqueorthrow"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After &lt;code&gt;group&lt;/code&gt; is returned, a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions"&gt;regular expression&lt;/a&gt; is used and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test"&gt;test&lt;/a&gt; against the &lt;code&gt;group&lt;/code&gt; value. If there's a match, it will return &lt;code&gt;true&lt;/code&gt;, or &lt;code&gt;false&lt;/code&gt; in the case of no match. This looks for any &lt;code&gt;mycustomdomain-faculty&lt;/code&gt; or &lt;code&gt;mycustomdomain-dev-faculty&lt;/code&gt; in &lt;code&gt;group&lt;/code&gt;.&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider other adjustment to codes relating to &lt;code&gt;User&lt;/code&gt;. There was no need for additional adjustment for this, but I could easily needed to do so. For example, if I changed a column name, I would need to change other references to the name in the project.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also, I merged &lt;code&gt;firstName&lt;/code&gt; and &lt;code&gt;lastName&lt;/code&gt; columns into one &lt;code&gt;displayName&lt;/code&gt; column, given that's what SAML gives back. The same ideas for such changes in database schema apply: edit the schema file, edit the seeding file, change/add relevant functions, and other relevant code adjustment. In this case, no new function was added.&lt;/p&gt;

&lt;h2&gt;
  
  
  Change Log Of The PR:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add group in &lt;code&gt;User&lt;/code&gt; model as String in &lt;code&gt;prisma\schema.prisma&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add examples in &lt;code&gt;prisma\seed.ts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modify &lt;code&gt;createUser()&lt;/code&gt; in &lt;code&gt;app\models\user.server.ts&lt;/code&gt; accordingly&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;isStudent()&lt;/code&gt;, &lt;code&gt;isFaculty()&lt;/code&gt;, and &lt;code&gt;isAdmin()&lt;/code&gt; in &lt;code&gt;app\models\user.server.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Combine &lt;code&gt;firstName&lt;/code&gt; and &lt;code&gt;lastName&lt;/code&gt; into &lt;code&gt;displayName&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modify arguments of &lt;code&gt;createUser()&lt;/code&gt; in &lt;code&gt;app\routes\login\callback.tsx&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;isStudent()&lt;/code&gt;, &lt;code&gt;isFaculty()&lt;/code&gt;, and &lt;code&gt;isAdmin()&lt;/code&gt; accept &lt;code&gt;username&lt;/code&gt; as parameter. They would return &lt;code&gt;true&lt;/code&gt; if they have the role/group, &lt;code&gt;false&lt;/code&gt; if not.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>prisma</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Starchart: Mocking A Database Part 1</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 24 Feb 2023 16:27:07 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-mocking-a-database-part-1-2kg2</link>
      <guid>https://dev.to/cychu42/starchart-mocking-a-database-part-1-2kg2</guid>
      <description>&lt;h2&gt;
  
  
  The story
&lt;/h2&gt;

&lt;p&gt;This week, I'm trying to write some tests for CRUD operation functions I made &lt;a href="https://dev.to/cychu42/starchart-schema-tweak-and-crud-operation-1hl2"&gt;last week&lt;/a&gt;.&lt;br&gt;
The project uses &lt;a href="https://vitest.dev/guide/"&gt;Vitest&lt;/a&gt;, so I had to go over documentation for that to see what I need to do. It similar enough to &lt;a href="https://jestjs.io/docs/getting-started"&gt;Jest&lt;/a&gt; that syntax feels familiar, but there are some differences like how to import certain functions.&lt;br&gt;
Actually writing tests is familiar enough for me that it doesn't cause any issue, but I'm rather stumped about how to mock a database that's interfaced via Prisma, as this is really new to me. Thus, the progress has been slow for the task.&lt;/p&gt;

&lt;p&gt;When I first started, I found &lt;a href="https://www.prisma.io/docs/guides/testing/unit-testing"&gt;Prisma documentation&lt;/a&gt; for writing test and mocking PrismaClient instance that API calls go through, but it's not appropripate for the project, as we use Vitest. Then, I found a &lt;a href="https://www.prisma.io/blog/testing-series-1-8eRB5p0Y8o"&gt;blog post&lt;/a&gt; on Prisma official site that covers using Vitest, but I'm now stuck with an issue of the code not being able to find deeply nested properties that are common for API calls, such as &lt;code&gt;prisma.user.create()&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Mocking Prisma Is Supposed To Works In Vitest
&lt;/h2&gt;

&lt;p&gt;This explanation assumes you are familiar with the &lt;a href="https://jestjs.io/docs/using-matchers"&gt;basics of witting test in Jest&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You install an extension package via &lt;code&gt;npm i -D vitest-mock-extended&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Make a &lt;code&gt;__Mocks__&lt;/code&gt; folder that has a file named after the module you want to mock. In this case, it would be a file that exports an instance of PrismaClient. Make sure to place this folder next to the real module.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the mocked module, place code to mock it:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt; import { PrismaClient } from '@prisma/client'
 import { beforeEach } from 'vitest'
 import { mockDeep, mockReset } from 'vitest-mock-extended'

 beforeEach(() =&amp;gt; {
 mockReset(prisma)
 })

 const prisma = mockDeep&amp;lt;PrismaClient&amp;gt;()
 export default prisma
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This imports all the tools needed, resets the mocked instance before each test, and exports an mocked instance to be used in a test. Because we are dealing with deeply nested properties like &lt;code&gt;prisma.user.create()&lt;/code&gt;, you want to use &lt;code&gt;mockDeep&amp;lt;&amp;gt;()&lt;/code&gt;.&lt;/p&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the test file you are writing, include &lt;code&gt;import { expect, test, vi } from 'vitest'&lt;/code&gt; to import tools you need from Vitest, and use &lt;code&gt;vi.mock(&amp;lt;route to the real module&amp;gt;)&lt;/code&gt; to tell Vitest you are mocking any mention of that route using the mocked modules in the &lt;code&gt;&lt;strong&gt;Mocks&lt;/strong&gt;&lt;/code&gt; folder next to the real one. You also need to import that mocked instance from the mocked module in step 3.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Like using Jest, write test and import any function you want to test. Also, make sure to Vitest what the expected result of a function would be from the mocked module. For example, &lt;code&gt;prisma.user.create.mockResolvedValue({ id: 1 })&lt;/code&gt; tells it that you expect &lt;code&gt;{id:1}&lt;/code&gt; object to be returned from the API call. See other functions &lt;a href="https://vitest.dev/api/mock.html"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What now?
&lt;/h2&gt;

&lt;p&gt;Either I try to figure out why it's not getting deeply nested properties as it's supposed to, or....I got a suggestion from the team that I can alternatively try to look into making a test database instead of mocking, so I need to look more into how to work with the &lt;code&gt;dock-compose&lt;/code&gt; YAML file in the project to make it happen. So far, I managed to make a test database by editing the file, but something is preventing Prisma from connecting to it and throws &lt;code&gt;Error: P1017: Server has closed the connection&lt;/code&gt;, which is an issue I need figure out in order to continue this approach.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>prisma</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Starchart: Schema Tweak and CRUD Operations</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 17 Feb 2023 14:53:54 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-schema-tweak-and-crud-operation-1hl2</link>
      <guid>https://dev.to/cychu42/starchart-schema-tweak-and-crud-operation-1hl2</guid>
      <description>&lt;p&gt;This week, I'm &lt;a href="https://github.com/DevelopingSpace/starchart/pull/201" rel="noopener noreferrer"&gt;tweaking column names&lt;/a&gt; and &lt;a href="https://github.com/DevelopingSpace/starchart/pull/228" rel="noopener noreferrer"&gt;adding CRUD functions&lt;/a&gt; to the Startchart project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did
&lt;/h2&gt;

&lt;p&gt;Because it's in Typescript, I tried to set type for the parameters, and that makes things easier to change. Example: &lt;code&gt;username: Record['username']&lt;/code&gt;&lt;br&gt;
They will look to the &lt;code&gt;Record&lt;/code&gt; model for the type, and I only need to make changes in there to change all related parameters.&lt;/p&gt;

&lt;p&gt;The CRUD functions are essentially simple exported functions that wrap around Prisma related code to allow developers to not worry about how Prisma works. They just enter the arguments and let the functions do what they are supposed to do.&lt;/p&gt;

&lt;p&gt;I tried to write functions to enable basic CRUD operations that will be useful for developers to interact with the database via Prisma. &lt;br&gt;
Part of that was trying to be mindful of how other people might use the functions, so I favored more accessible parameter like &lt;code&gt;username&lt;/code&gt; over things like index &lt;code&gt;id&lt;/code&gt; that might be more obscured, whenever possible. I also try to be consistent, so it's less confusing, which means I try to ask for the same thing in the parameter, such as &lt;code&gt;username&lt;/code&gt;, or &lt;code&gt;id&lt;/code&gt; if &lt;code&gt;username&lt;/code&gt; isn't available or doesn't' make sense.&lt;br&gt;
Another part of that is to think about whether the name properly explains what the function is supposed to do, such as &lt;code&gt;updateRecordById()&lt;/code&gt;, and whether the parameter conveys enough information. I think, if someone sees the functions name and the parameter, they would be able to infer that this is for updating &lt;code&gt;Record&lt;/code&gt; model by &lt;code&gt;id&lt;/code&gt;, and they need an &lt;code&gt;id&lt;/code&gt; and other optional field that they want to change. The parameter is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(
  id: Record['id'],
  username?: Record['username'],
  name?: Record['name'],
  type?: Record['type'],
  value?: Record['value'],
  description?: Record['description'],
  course?: Record['course'],
  ports?: Record['ports'],
  expiresAt?: Record['expiresAt'],
  status?: Record['status']
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, optional fields are marked by &lt;code&gt;?&lt;/code&gt;, and they all have type associated from columns in the model. There was a discusion in the team abotu using this as a way to "document" functions, and I hope this does that.&lt;/p&gt;

&lt;p&gt;Not everyone is going to be comfortable writing Prisma related code, and it's nice to have reusable code across the project.&lt;br&gt;
I also tried to follow the format of the existing CRUD function for User model, for project consistency. &lt;/p&gt;

&lt;h2&gt;
  
  
  Experience
&lt;/h2&gt;

&lt;p&gt;It involved a bit of juggling changes, since I want to change column names while also thinking about CRUD operation, so I operated on the assume of my column name changes when I wrote the functions. If I change something in schema, I then have to follow suit in the functions.&lt;br&gt;
The changes got merged, so all is well, and I was able to push the pull request in a timely manner.&lt;/p&gt;

&lt;p&gt;Because a lot of people from different part of the development team will be using the database, I also got me thinking about not doing too frequent changes to the schema. I tried to wait to accumulate some non-critical changes and pick a good time (such as before CRUD functions are made available) to make the changes.&lt;/p&gt;

&lt;p&gt;Because Prisma client requires you to regenerate every time you change the schema to sync to it, I need to do &lt;code&gt;npx prisma generate&lt;/code&gt; a few times (It's a different command for this project due to scripts used). Otherwise, it would not acknowledge the changes and will complain about it. I do notice I have to restart VS code for complain/error to go away even after regenerating the client.&lt;/p&gt;

</description>
      <category>support</category>
      <category>help</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Starchart: Seeding</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Fri, 10 Feb 2023 20:22:59 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-seeding-2ofk</link>
      <guid>https://dev.to/cychu42/starchart-seeding-2ofk</guid>
      <description>&lt;p&gt;This week, my main focus is to work on seeding the database for Starchart project. (see &lt;a href="https://github.com/Seneca-CDOT/starchart/pull/160"&gt;PR&lt;/a&gt;)&lt;br&gt;
I thought it would be more complicated, but it's actually just writing &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-client/crud"&gt;query with Prisma&lt;/a&gt; to insert rows of data into database tables, and there's a bit of script setup.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup &lt;a href="https://www.prisma.io/docs/guides/database/seed-database"&gt;(official documentation)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Requirement:&lt;/strong&gt;&lt;br&gt;
Make sure you have Prisma &lt;a href="https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch"&gt;setup&lt;/a&gt; already. You need to first have a &lt;code&gt;pakcage.json&lt;/code&gt; generated from &lt;code&gt;npm init&lt;/code&gt; too.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Inside &lt;code&gt;pakcage.json&lt;/code&gt;, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"prisma": {
    "seed": "ts-node prisma/seed.ts"
}
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;If your project needs to use compile option, you should use     this instead:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"prisma": { 
     "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" 
}, 
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code&gt;seed.ts&lt;/code&gt; under &lt;code&gt;prisma&lt;/code&gt; folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add code for &lt;a href="https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgres#write-data-into-the-database"&gt;"create" query&lt;/a&gt; inside the file to add rows of data. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;npx prisma db seed&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There! If the steps are done correctly, you just seeded the database with some data for testing or whatever you need to do!&lt;/p&gt;

&lt;h2&gt;
  
  
  Experience
&lt;/h2&gt;

&lt;p&gt;I realized there are a few things to consider as I worked on this. &lt;br&gt;
You need to thing about cleaning existing data. Because there are some foreign keys in the schema, I need to think about the order I delete data from each table. Otherwise, it can run into errors. It would be easier if one sets up &lt;a href="https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#:~:text=adding%20onDelete%3A%20Cascade"&gt;cascading delete&lt;/a&gt;, where a row is automatically deleted if the referenced row (usually from another table) for the row's foreign key is deleted.&lt;br&gt;
Because of the foreign keys, another thing to consider is to create things in the correct order, so there's something to be referenced before referencing it.&lt;br&gt;
Lastly, it would be intuitive to let index auto-increment and make index the thing to be referenced for foreign keys. However, doing both would present a problem when you are doing seeding. The referenced value need to stay consistent so that you can properly connect one row to a specific row. Therefore, you actually need to specify the index in such scenario, such as the &lt;code&gt;id&lt;/code&gt; here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s0mbtdw2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pet3kva18ndg80feuakp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s0mbtdw2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pet3kva18ndg80feuakp.png" alt="an example of specifying the index" width="240" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>prisma</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Startchart: Prisma Schema</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Sat, 04 Feb 2023 02:40:41 +0000</pubDate>
      <link>https://dev.to/cychu42/startchart-prisma-schema-4i6d</link>
      <guid>https://dev.to/cychu42/startchart-prisma-schema-4i6d</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;This week, I focus on creating an initial schema for the &lt;a href="https://github.com/Seneca-CDOT/starchart" rel="noopener noreferrer"&gt;project&lt;/a&gt; through using &lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt;. This is for a MySQL database, and the PR for the initial schema is &lt;a href="https://github.com/Seneca-CDOT/starchart/pull/79" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This is an example of a model:&lt;br&gt;
&lt;a href="https://media2.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%2Fcbn8yhxqpgdy7kpojqzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcbn8yhxqpgdy7kpojqzb.png" alt="Prisma model" width="673" height="295"&gt;&lt;/a&gt;&lt;br&gt;
A model describes how a table would look like on a database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Record would be the table name.&lt;/li&gt;
&lt;li&gt;Green texts are the value types for the columns.&lt;/li&gt;
&lt;li&gt;The blue texts are the names of the columns.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@id&lt;/code&gt; marks the primary key.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;?&lt;/code&gt; marks a column as nullable. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@default&lt;/code&gt; sets the default value as what's in the parameter.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;now()&lt;/code&gt; returns the current time.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@updatedAt&lt;/code&gt; would provide the value that's the time a row is updated.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Foreign key:&lt;br&gt;
In the example, the line with &lt;code&gt;user&lt;/code&gt; is used to record a relationship between this and the other table, for the purpose of marking a foreign key. &lt;code&gt;fields&lt;/code&gt;'s value is the foreign key, while &lt;code&gt;references&lt;/code&gt;'s value points to a column on another table.&lt;br&gt;
On the other table, it need to have another corresponding line to fully establish the relationship, like:&lt;br&gt;
&lt;a href="https://media2.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%2Fhudeiq1ll95wc4haquwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fhudeiq1ll95wc4haquwj.png" alt="The other table's line" width="186" height="22"&gt;&lt;/a&gt;&lt;code&gt;[]&lt;/code&gt; means it's a to-many relationship. You don't have that if it's to-one relationship.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You might notice some odd type like &lt;code&gt;RecordType&lt;/code&gt;. That's &lt;strong&gt;enumeration&lt;/strong&gt;, and you can declare that in the same file:&lt;br&gt;
&lt;a href="https://media2.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%2Fuz4ojud4ct6g2x35nrac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fuz4ojud4ct6g2x35nrac.png" alt="enumeration example" width="154" height="129"&gt;&lt;/a&gt; As you can see, the green text is the name of the type, and the blue texts are the possible values for such type.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Experience
&lt;/h2&gt;

&lt;p&gt;As far as creating schema goes, Prisma is very friendly and easy to use, once you learn the basic, such as how to mark primary key or make values in a column unique. Establishing foreign key and the relationship between tables take a bit more work to understand. It helps if you already know how a database works.&lt;/p&gt;

&lt;p&gt;Because I need to create the database to serve the need of other parts of the project, such as what user information people who handle login want to store, I ask around the team. I sort of feel like someone who goes around with a clip board and ask what they would like to order for lunch. I ask them what they would like to include and why...to have better comprehension of the project and for my own learning, and it's always interesting to learn more.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Starchart: Planning Toward Release 0.1</title>
      <dc:creator>cychu42</dc:creator>
      <pubDate>Sat, 28 Jan 2023 03:49:52 +0000</pubDate>
      <link>https://dev.to/cychu42/starchart-plan-for-release-01-26ba</link>
      <guid>https://dev.to/cychu42/starchart-plan-for-release-01-26ba</guid>
      <description>&lt;p&gt;This week, we some planning for &lt;a href="https://github.com/Seneca-CDOT/starchart"&gt;Starchart&lt;/a&gt; release 0.1.&lt;br&gt;
The first waves of issues were filed, and tasks were assigned to the team members. I'm to contribute in setting up database schema and the ORM, &lt;a href="https://www.prisma.io/"&gt;Prisma&lt;/a&gt;, as well as finding out how to run it in &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I filed 7 issues in total:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/Seneca-CDOT/starchart/issues/6"&gt;Issue #6&lt;/a&gt; is about adding a wiki entry for Prisma to serve as a start point for helping team members looking into the technology.&lt;br&gt;
&lt;a href="https://github.com/Seneca-CDOT/starchart/issues/9"&gt;Issue #9&lt;/a&gt; is about notifying users about their SSL certificate request status via email&lt;br&gt;
&lt;a href="https://github.com/Seneca-CDOT/starchart/issues/10"&gt;Issue #10&lt;/a&gt; centers around creating a page for user to view information of SSL certificate they have requested.&lt;br&gt;
&lt;a href="https://github.com/Seneca-CDOT/starchart/issues/11"&gt;Issue #11&lt;/a&gt; talks about a feature to notify users about their SSL certificate expiration and next-steps&lt;br&gt;
&lt;a href="https://github.com/Seneca-CDOT/starchart/issues/12"&gt;Issue #12&lt;/a&gt; is regarding documentation for helping developers setup their local environment for development of this project.&lt;br&gt;
&lt;a href="https://github.com/Seneca-CDOT/starchart/issues/13"&gt;Issue #13&lt;/a&gt; is regarding documentation for helping developers follow flow of contribution to contribute to the project.&lt;br&gt;
&lt;a href="https://github.com/Seneca-CDOT/starchart/issues/16"&gt;Issue #16&lt;/a&gt; is for creating a certificate table in the database to record information of SSL certificate created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology Research
&lt;/h2&gt;

&lt;p&gt;Because much of the tech stack is new to me, I have to spend time reading the documentations to familiarize myself with it.&lt;br&gt;
Since I try to focus on database, my primary focus is on MySQL and Prisma, which is the primary way the project uses to interact with a MySQL database. &lt;br&gt;
In my research, I found information for how to &lt;a href="https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgres"&gt;set up Prisma&lt;/a&gt; for a MySQL database, and I have tried the steps.&lt;br&gt;
Through commands, one can run a .prisma file to push/pull table schema to/from the target database. One can also run commands to run a file with code that essentially act like SQL statements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are some basic CLI commands:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npx prisma db pull&lt;/code&gt; to pull database tables into your schema file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npx prisma generate&lt;/code&gt; to sync client to current schema in the local schema file; do this before you do CRUD SQL operation via prisma.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npx ts-node &amp;lt;file location&amp;gt;&lt;/code&gt; to execute CRUD operation code in the file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npx prisma migrate dev --name &amp;lt;any migration name&amp;gt;&lt;/code&gt; to migrate your schema.prisma file to target database.
Because prisma make a shadow database (temporary) every time to make sure database is sync, use &lt;code&gt;npx prisma database push&lt;/code&gt; if you don’t have right to make another database (no benefit from shadow database)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npx prisma studio&lt;/code&gt; to start Prisma studio, the visual editor UI for database.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Also, I tried to look up how to run MySQL database in Docker. It seems you need to download an image of a MySQL database, and then create an instance in Docker, as detailed on &lt;a href="https://dev.mysql.com/doc/mysql-installation-excerpt/8.0/en/docker-mysql-getting-started.html#docker-starting-mysql-server"&gt;MySQL's website&lt;/a&gt;.&lt;br&gt;
The Docker documentation suggests an one-line command to do so:&lt;code&gt;docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>prisma</category>
    </item>
  </channel>
</rss>
