<?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: instanceofGod</title>
    <description>The latest articles on DEV Community by instanceofGod (@instanceofgod).</description>
    <link>https://dev.to/instanceofgod</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%2F476942%2F6f47c250-511a-46f0-b526-f4718b536d38.jpeg</url>
      <title>DEV Community: instanceofGod</title>
      <link>https://dev.to/instanceofgod</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/instanceofgod"/>
    <language>en</language>
    <item>
      <title>PIN Encryption &amp; Decryption with RSA in Node.js</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Tue, 17 Mar 2026 16:41:57 +0000</pubDate>
      <link>https://dev.to/instanceofgod/pin-encryption-decryption-with-rsa-in-nodejs-22d1</link>
      <guid>https://dev.to/instanceofgod/pin-encryption-decryption-with-rsa-in-nodejs-22d1</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why PIN encryption matters&lt;/li&gt;
&lt;li&gt;Core terms defined&lt;/li&gt;
&lt;li&gt;How RSA works&lt;/li&gt;
&lt;li&gt;Anatomy of a key pair&lt;/li&gt;
&lt;li&gt;The OpenSSLUtil class, line by line&lt;/li&gt;
&lt;li&gt;The full encrypt → transmit → decrypt flow&lt;/li&gt;
&lt;li&gt;Working with keys in the terminal&lt;/li&gt;
&lt;li&gt;Common pitfalls &amp;amp; security notes&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Why PIN encryption matters
&lt;/h2&gt;

&lt;p&gt;Every time a user taps their 4-digit PIN into a mobile banking app or payment terminal, those four digits travel from device to server. If they travel as plain text — say, &lt;code&gt;{"pin": "1234"}&lt;/code&gt; — anyone who can intercept the HTTP request, peek at server logs, or read a database dump will see that PIN immediately. That is a catastrophic failure mode.&lt;/p&gt;

&lt;p&gt;The solution is asymmetric encryption. The server holds a private key that it never shares. The client has a copy of the corresponding public key. The client encrypts the PIN before it leaves the device, and only the server — with its private key — can decrypt it. No intermediary, no log, no network sniffer can read the PIN in transit.&lt;/p&gt;

&lt;p&gt;The code snippet in this article is a production-ready implementation of this pattern, built on Node.js's built-in &lt;code&gt;crypto&lt;/code&gt; module using RSA-OAEP encryption with SHA-256 — the modern, recommended approach. This article walks through every part of it, explaining the concepts before the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Core terms defined
&lt;/h2&gt;

&lt;p&gt;Before touching a single line of code, you need a working vocabulary. These terms will come up again and again.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Definition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plaintext&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The original readable data before any encryption. In our case, the PIN — e.g. the string &lt;code&gt;"1234"&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ciphertext&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The scrambled output after encryption. Looks like random bytes. Example: a 256-byte binary blob that encodes to a long base64 string.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Encryption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The process of transforming plaintext into ciphertext using a key and an algorithm. Without the correct decryption key, ciphertext is meaningless.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Decryption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The reverse: transforming ciphertext back into plaintext using the correct key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RSA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rivest–Shamir–Adleman. A widely used &lt;em&gt;asymmetric&lt;/em&gt; encryption algorithm based on the mathematical difficulty of factoring very large numbers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Asymmetric encryption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A scheme that uses &lt;em&gt;two different keys&lt;/em&gt;: a public key to encrypt, and a private key to decrypt. You can freely share the public key — knowing it does not help you decrypt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Symmetric encryption&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A scheme that uses the &lt;em&gt;same key&lt;/em&gt; for both encryption and decryption (e.g. AES). Fast, but the key must be shared securely — which is the hard part.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Public key&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One half of the RSA key pair. Safe to share with anyone. Used to &lt;em&gt;encrypt&lt;/em&gt; data or &lt;em&gt;verify&lt;/em&gt; signatures.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Private key&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The other half. Must be kept secret. Used to &lt;em&gt;decrypt&lt;/em&gt; data or &lt;em&gt;create&lt;/em&gt; signatures. If an attacker gets this, all security is lost.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OAEP padding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Optimal Asymmetric Encryption Padding. The modern, secure padding scheme for RSA. Uses a hash function (SHA-256 in this codebase) to produce randomised, tamper-resistant ciphertext. Resistant to padding oracle attacks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PKCS#8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A standard format for encoding private keys. Node.js v17+ requires private keys to be in PKCS#8 format (begins with &lt;code&gt;-----BEGIN PRIVATE KEY-----&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PEM format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Privacy Enhanced Mail. A base64-encoded wrapper for certificates and keys with a human-readable header and footer. The &lt;code&gt;-----BEGIN ...-----&lt;/code&gt; / &lt;code&gt;-----END ...-----&lt;/code&gt; lines you see in key files.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Base64&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An encoding (not encryption!) that converts binary data into printable ASCII characters. Used to safely include binary ciphertext in JSON or URL parameters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Digital signature&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A cryptographic proof that a message was created by the holder of a private key and has not been tampered with. Created with the private key; verified with the public key.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Buffer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Node.js's representation of raw binary data. Crypto operations work on Buffers, not JavaScript strings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SHA-256&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A cryptographic hash function that produces a fixed 256-bit digest of any input. Used both in OAEP padding and in the signing algorithm.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  3. How RSA works
&lt;/h2&gt;

&lt;p&gt;You do not need to understand the mathematics in depth, but a conceptual model will prevent a lot of confusion later.&lt;/p&gt;

&lt;p&gt;RSA relies on a simple fact: multiplying two large prime numbers together is easy, but factoring the result back into those two primes is computationally infeasible. The public and private keys are derived from this relationship — one cannot be practically computed from the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encryption with the public key:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anyone can encrypt a message&lt;/li&gt;
&lt;li&gt;Freely distribute your public key&lt;/li&gt;
&lt;li&gt;OAEP padding makes output non-deterministic&lt;/li&gt;
&lt;li&gt;Only the private key holder can read it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Decryption with the private key:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only the key holder can decrypt&lt;/li&gt;
&lt;li&gt;Private key never leaves the server&lt;/li&gt;
&lt;li&gt;Decryption always yields the same original plaintext&lt;/li&gt;
&lt;li&gt;Losing the private key = losing access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A common analogy: the public key is like an open padlock you hand to everyone. Anyone can snap it shut (encrypt). Only you have the physical key that opens it (decrypt).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note — RSA is not for bulk data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RSA can only encrypt data smaller than its key size minus padding overhead. A 2048-bit key with OAEP-SHA256 can encrypt at most ~190 bytes of data. This is perfect for short secrets like PINs, passwords, or symmetric keys — but you would never RSA-encrypt a file. For large data, RSA is used to encrypt a random AES key, then AES encrypts the actual data. This hybrid approach is what TLS does.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. Anatomy of a key pair
&lt;/h2&gt;

&lt;p&gt;The example gives you a 2048-bit RSA key pair. Let's understand what you are looking at.&lt;/p&gt;

&lt;h3&gt;
  
  
  The public key
&lt;/h3&gt;

&lt;p&gt;Safe to share, embed in your mobile app, or publish in your documentation. It begins with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFBPODvVUdzXxGkXG0OP
HQ0zDS3xf1uD7tY8mJKWrjSLMf2CeZtWYNlT2xq40R7x5VTn1rnKbgnBZg2ynyLh...
-----END PUBLIC KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is PEM format — the binary key data encoded in base64, wrapped with header and footer lines. The actual key material is the base64 between the markers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The private key (PKCS#8)
&lt;/h3&gt;

&lt;p&gt;Never share this. It begins with &lt;code&gt;-----BEGIN PRIVATE KEY-----&lt;/code&gt; (not &lt;code&gt;BEGIN RSA PRIVATE KEY&lt;/code&gt;, which is the older PKCS#1 format). Node.js v17+ requires PKCS#8. This is why the setup guide includes a conversion command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Convert PKCS#1 to PKCS#8 (Node.js v17+ requires this)&lt;/span&gt;
openssl pkcs8 &lt;span class="nt"&gt;-topk8&lt;/span&gt; &lt;span class="nt"&gt;-nocrypt&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; old_private.pem &lt;span class="nt"&gt;-out&lt;/span&gt; new_private_pkcs8.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key format summary
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header line&lt;/th&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Used for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BEGIN RSA PRIVATE KEY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PKCS#1&lt;/td&gt;
&lt;td&gt;Older OpenSSL tools. Not accepted by Node.js v17+.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BEGIN PRIVATE KEY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PKCS#8&lt;/td&gt;
&lt;td&gt;Modern standard. Required by Node.js &lt;code&gt;createPrivateKey&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BEGIN ENCRYPTED PRIVATE KEY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PKCS#8 encrypted&lt;/td&gt;
&lt;td&gt;Private key protected with a passphrase.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BEGIN PUBLIC KEY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;X.509 SubjectPublicKeyInfo&lt;/td&gt;
&lt;td&gt;Standard public key format.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  5. The OpenSSLUtil class, line by line
&lt;/h2&gt;

&lt;p&gt;Now let's walk through the implementation. The class has three main responsibilities: loading the key pair, encrypting with the public key, and decrypting with the private key. There is also a bonus signing method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constructor and key loading
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OpenSSLUtil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyPair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_readKeyPair&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Key parsing happens once at startup — not on every request.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;_readKeyPair&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;privatePem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;passphrase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rsaConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPrivateKey&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;privatePem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pem&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;passphrase&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;passphrase&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Derive the public key from the private key — no need to store both&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createPublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKey&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why derive the public key from the private key?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A private key mathematically contains all the information needed to reconstruct the public key. Calling &lt;code&gt;crypto.createPublicKey(privateKey)&lt;/code&gt; is safe, convenient, and avoids having to store or sync two separate key files. You only need to protect the private key.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Encrypt method — OAEP-SHA256
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;encrypt&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publicEncrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RSA_PKCS1_OAEP_PADDING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;oaepHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="c1"&gt;// OAEP with SHA-256: secure, modern, tamper-resistant&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&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="c1"&gt;// convert string → binary Buffer&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// binary → base64 string&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Could not encrypt data: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;Breaking this down step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Buffer.from(text)&lt;/code&gt;&lt;/strong&gt; — Converts the string &lt;code&gt;"1234"&lt;/code&gt; into raw bytes. RSA encryption operates on binary data, not JavaScript strings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;RSA_PKCS1_OAEP_PADDING&lt;/code&gt;&lt;/strong&gt; — Applies OAEP padding using SHA-256 as the hash function. OAEP uses a random seed internally, so encrypting the same PIN twice produces completely different ciphertexts — making brute-force and rainbow-table attacks impractical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;oaepHash: 'sha256'&lt;/code&gt;&lt;/strong&gt; — Specifies SHA-256 as the hash used inside the OAEP padding scheme. This must match on both encrypt and decrypt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.toString('base64')&lt;/code&gt;&lt;/strong&gt; — Encodes the binary output as a base64 string, making it safe to include in JSON request bodies or HTTP headers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Decrypt method — OAEP-SHA256
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Accept either a base64 string or a raw Buffer&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// base64 string → binary Buffer&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                         &lt;span class="c1"&gt;// already a Buffer, use as-is&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;privateDecrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RSA_PKCS1_OAEP_PADDING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;oaepHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  &lt;span class="c1"&gt;// must match what was used in encrypt()&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;buffer&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;decrypted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// binary → original string&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Could not decrypt data: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning — Padding scheme and hash must match on both ends&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both &lt;code&gt;encrypt()&lt;/code&gt; and &lt;code&gt;decrypt()&lt;/code&gt; use &lt;code&gt;RSA_PKCS1_OAEP_PADDING&lt;/code&gt; with &lt;code&gt;oaepHash: 'sha256'&lt;/code&gt;. If you encrypt with one hash and attempt to decrypt with another, decryption will silently fail and return &lt;code&gt;null&lt;/code&gt;. Always keep these parameters consistent across your entire stack — including any client-side or terminal-based encryption.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Sign method
&lt;/h3&gt;

&lt;p&gt;Signing is separate from encryption. A signature does not hide the content — it &lt;em&gt;proves authorship&lt;/em&gt; and integrity. You sign with your private key; anyone with your public key can verify the signature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;sign&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SHA256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Feed the data into the sign object&lt;/span&gt;
    &lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// 2. Finalize: hash the data with SHA-256, then RSA-sign the hash&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Could not sign data: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The signing algorithm does two things internally: it first runs &lt;code&gt;SHA256(text)&lt;/code&gt; to produce a 32-byte digest, then RSA-encrypts that digest with the private key. The result is a 256-byte (2048-bit) signature, returned as base64.&lt;/p&gt;

&lt;h3&gt;
  
  
  Module export as singleton
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Export a single shared instance (not the class itself)&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenSSLUtil&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Usage elsewhere in the codebase:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openssl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./utils/openssl-util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encryptedPin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;openssl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recoveredPin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;openssl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encryptedPin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exporting &lt;code&gt;new OpenSSLUtil()&lt;/code&gt; rather than the class itself means the key parsing happens once at startup. Every module that requires this file gets the same instance with the already-loaded keys — no repeated I/O or parsing overhead per request.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. The full encrypt → transmit → decrypt flow
&lt;/h2&gt;

&lt;p&gt;Here is the complete lifecycle of a PIN from a client device to a server response, as the codebase implements it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client has public key
        ↓
User enters PIN
        ↓
Encrypt with public key (OAEP-SHA256)
        ↓
Base64 encode
        ↓
HTTPS POST
        ↓
Server decrypts with private key
        ↓
Plaintext PIN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1 — Client encrypts the PIN (terminal simulation)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Encrypt "1234" using OAEP with SHA-256 and output as base64&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"1234"&lt;/span&gt; | openssl pkeyutl &lt;span class="nt"&gt;-encrypt&lt;/span&gt; &lt;span class="nt"&gt;-pubin&lt;/span&gt; &lt;span class="nt"&gt;-inkey&lt;/span&gt; public.pem &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-pkeyopt&lt;/span&gt; rsa_padding_mode:oaep &lt;span class="nt"&gt;-pkeyopt&lt;/span&gt; rsa_oaep_md:sha256 | &lt;span class="nb"&gt;base64&lt;/span&gt;

&lt;span class="c"&gt;# Output:&lt;/span&gt;
mK9xZq2Tp7fVnBsLuR4dAe8cWyOhXiGj...
&lt;span class="c"&gt;# Run again — you'll get a completely different string (OAEP is non-deterministic)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 — Client sends the encrypted PIN
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why is this safe even over plain HTTP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even if an attacker intercepts this JSON, they see only the base64 ciphertext — not the PIN. Without the private key (which never leaves the server), they cannot decrypt it. That said, you should still use HTTPS. Defence in depth means multiple layers of protection.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 3 — Server decrypts and verifies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openssl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../utils/openssl-util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Decrypt the incoming base64 string back to plaintext&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decryptedPin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;openssl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;decryptedPin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid encrypted PIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Never store the raw PIN — hash it before comparison&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pinHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&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="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decryptedPin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Compare hash against what is stored in the database&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;findUserByPhone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phonenumber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pinHash&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;pinHash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid credentials&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateSessionToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;token&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;h2&gt;
  
  
  7. Working with keys in the terminal
&lt;/h2&gt;

&lt;p&gt;The provided setup guide includes several OpenSSL terminal commands. Here is what each one does and when to use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate a fresh key pair
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a 2048-bit RSA private key and immediately convert to PKCS#8&lt;/span&gt;
openssl genrsa 2048 | openssl pkcs8 &lt;span class="nt"&gt;-topk8&lt;/span&gt; &lt;span class="nt"&gt;-nocrypt&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; private_pkcs8.pem

&lt;span class="c"&gt;# Derive the public key from the private key&lt;/span&gt;
openssl rsa &lt;span class="nt"&gt;-in&lt;/span&gt; private_pkcs8.pem &lt;span class="nt"&gt;-pubout&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; public.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Encrypt a PIN for testing (OAEP)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Encrypt "1234" using OAEP with SHA-256 and output as base64&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"1234"&lt;/span&gt; | openssl pkeyutl &lt;span class="nt"&gt;-encrypt&lt;/span&gt; &lt;span class="nt"&gt;-pubin&lt;/span&gt; &lt;span class="nt"&gt;-inkey&lt;/span&gt; public.pem &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-pkeyopt&lt;/span&gt; rsa_padding_mode:oaep &lt;span class="nt"&gt;-pkeyopt&lt;/span&gt; rsa_oaep_md:sha256 | &lt;span class="nb"&gt;base64&lt;/span&gt;

&lt;span class="c"&gt;# Verify round-trip: decrypt the output back to the original PIN&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"mK9xZq2..."&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; | openssl pkeyutl &lt;span class="nt"&gt;-decrypt&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-inkey&lt;/span&gt; private_pkcs8.pem &lt;span class="nt"&gt;-pkeyopt&lt;/span&gt; rsa_padding_mode:oaep &lt;span class="nt"&gt;-pkeyopt&lt;/span&gt; rsa_oaep_md:sha256
&lt;span class="c"&gt;# Output: 1234&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Convert the key to a JSON-safe escaped string
&lt;/h3&gt;

&lt;p&gt;Config files like &lt;code&gt;config.json&lt;/code&gt; cannot store multi-line strings. The private key PEM has newlines, so you need to escape them as &lt;code&gt;\n&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Node.js method&lt;/span&gt;
node &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"console.log(require('fs').readFileSync('private_pkcs8.pem','utf8').replace(/&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;/g,'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n'))"&lt;/span&gt;

&lt;span class="c"&gt;# Python method (often more reliable across platforms)&lt;/span&gt;
python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"print(open('private_pkcs8.pem').read().replace('&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;', '&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n'))"&lt;/span&gt;

&lt;span class="c"&gt;# awk method&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'NF {printf "%s\\n", $0} END {print ""}'&lt;/span&gt; private_pkcs8.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting single-line string can be pasted directly into your config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"privateKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-----BEGIN PRIVATE KEY-----&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEA...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;-----END PRIVATE KEY-----&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Warning — Never commit private keys to version control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The private key in this article is a test key. Never commit a real private key to a git repository, even a private one. Store keys in environment variables, a secrets manager (AWS Secrets Manager, HashiCorp Vault), or an encrypted config service.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. Common pitfalls &amp;amp; security notes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Don't log decrypted PINs
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;catch&lt;/code&gt; blocks in the utility log errors. Never add a &lt;code&gt;console.log(decryptedPin)&lt;/code&gt; for debugging. Application logs often end up in log aggregation platforms, and PINs in plaintext in logs are a compliance violation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Singleton means shared state
&lt;/h3&gt;

&lt;p&gt;The module exports &lt;code&gt;new OpenSSLUtil()&lt;/code&gt; — a singleton. The key pair is shared across all requests. This is fine if keys are read-only after initialization. But if you ever implement key rotation, you need to handle the transition carefully to avoid decryption failures on in-flight requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  OAEP encryption is non-deterministic — that's a feature
&lt;/h3&gt;

&lt;p&gt;Encrypting &lt;code&gt;"1234"&lt;/code&gt; twice will produce two completely different ciphertexts. OAEP padding incorporates a random seed on every operation. This means an attacker cannot use a pre-computed rainbow table to map ciphertexts back to PINs, and cannot tell whether two encrypted values are the same PIN. Each encryption is cryptographically unique.&lt;/p&gt;

&lt;h3&gt;
  
  
  Encryption vs signing — knowing when to use each
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sending a PIN from client to server&lt;/td&gt;
&lt;td&gt;Encrypt (public key, OAEP)&lt;/td&gt;
&lt;td&gt;Keeps PIN confidential in transit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server proves a response came from it&lt;/td&gt;
&lt;td&gt;Sign (private key)&lt;/td&gt;
&lt;td&gt;Client can verify with public key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client proves a request came from it&lt;/td&gt;
&lt;td&gt;Sign with client's private key&lt;/td&gt;
&lt;td&gt;Requires client-side key management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storing a PIN for comparison&lt;/td&gt;
&lt;td&gt;Hash (bcrypt / SHA-256)&lt;/td&gt;
&lt;td&gt;One-way — even server can't recover plaintext&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  9. Conclusion
&lt;/h2&gt;

&lt;p&gt;PIN encryption with RSA-OAEP in Node.js is a well-trodden pattern that, when implemented correctly, provides strong guarantees: a PIN that leaves a client device is unreadable to anyone who intercepts it, because only the server's private key can unlock it.&lt;/p&gt;

&lt;p&gt;The key ideas to carry forward are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Asymmetric encryption&lt;/strong&gt; solves the key-distribution problem. Share the public key freely; guard the private key absolutely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAEP with SHA-256&lt;/strong&gt; is the modern, secure padding choice. It is non-deterministic, tamper-resistant, and immune to padding oracle attacks — use it for all new RSA encryption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buffer ↔ string conversions&lt;/strong&gt; are explicit in Node.js. Always know whether you are working with binary data or a string, and which encoding (base64, utf8, hex) bridges them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PKCS#8 is the modern format.&lt;/strong&gt; If you see &lt;code&gt;BEGIN RSA PRIVATE KEY&lt;/code&gt;, convert it before passing it to Node.js v17+.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption is not storage.&lt;/strong&gt; After decrypting a PIN on the server, hash it before comparing to the stored value. RSA encryption is for transit security, not at-rest security.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From here, your natural next steps are implementing key rotation, considering hybrid encryption (RSA wrapping an AES key) for any payloads larger than a short PIN, and exploring the browser's WebCrypto API for client-side encryption using the same OAEP scheme.&lt;/p&gt;

</description>
      <category>security</category>
      <category>encryption</category>
      <category>beginners</category>
      <category>node</category>
    </item>
    <item>
      <title>Building a Production-Ready RAG Application with FastAPI, LangChain, and Google Gemini: A Deep Dive</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Fri, 20 Feb 2026 20:02:38 +0000</pubDate>
      <link>https://dev.to/instanceofgod/building-a-production-ready-rag-application-with-fastapi-langchain-and-google-gemini-a-deep-dive-37jl</link>
      <guid>https://dev.to/instanceofgod/building-a-production-ready-rag-application-with-fastapi-langchain-and-google-gemini-a-deep-dive-37jl</guid>
      <description>&lt;p&gt;Picture this: You’ve just deployed a shiny new AI assistant for your company. Your stakeholders are thrilled. Then, a highly-valued client asks it a crucial question about your brand-new, unreleased product documentation. The AI, possessing all the confidence in the world, proceeds to completely hallucinate an answer based on what it read on the internet two years ago. &lt;/p&gt;

&lt;p&gt;This is the fatal flaw of standard Large Language Models (LLMs). Out of the box, they are incredibly articulate but fundamentally ignorant about &lt;em&gt;your&lt;/em&gt; proprietary, real-time, or deeply domain-specific data. They confidently guess when they don't know the answer.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Retrieval-Augmented Generation (RAG)&lt;/strong&gt;—the silver bullet for LLM hallucination. &lt;/p&gt;

&lt;p&gt;Think of RAG as giving your AI an open-book test. Instead of relying on its static memory, a RAG system securely searches your private databases for the exact, relevant context and injects it directly into the prompt &lt;em&gt;before&lt;/em&gt; the LLM generates a response. You instantly transform a generic AI into a precise domain expert on your custom data.&lt;/p&gt;

&lt;p&gt;While there are plenty of simple "hello world" RAG tutorials out there, building something that scales requires careful software design. In this comprehensive deep-dive tutorial, we aren't just writing toy Jupyter cells. I will walk you through building a modular, multi-storage, production-ready RAG web service from scratch using FastAPI, LangChain, and Google Gemini—an architecture that you can actually deploy to the real world.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Our Technology Stack
&lt;/h2&gt;

&lt;p&gt;Instead of bloated orchestrators, we'll build on a lean, highly performant stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt;: A modern, wildly fast web framework for building our backend API. It gives us async capabilities, automatic data validation, and built-in Swagger UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LangChain &amp;amp; LCEL&lt;/strong&gt;: The leading framework to orchestrate LLM workflows. We'll heavily utilize LangChain Expression Language (LCEL) for declarative, readable pipelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Generative AI (Gemini)&lt;/strong&gt;: We'll power our system using two models:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gemini-embedding-001&lt;/code&gt; for mapping text to vectors.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gemini-2.5-flash&lt;/code&gt; for blindingly fast and intelligent text generation.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Durable Vector Stores&lt;/strong&gt;: To store and query embeddings, our application dynamically supports:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pinecone&lt;/strong&gt;: A fully managed, cloud-native vector database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAISS&lt;/strong&gt;: Facebook AI Similarity Search for blistering local performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Backups&lt;/strong&gt;: Built-in support for synchronizing our FAISS indexes with &lt;strong&gt;AWS S3&lt;/strong&gt; or &lt;strong&gt;Google Cloud Storage (GCS)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Project Architecture
&lt;/h2&gt;

&lt;p&gt;Before jumping into the implementation, let's map out our project structure. A good RAG application separates the HTTP layer, the orchestration layer, and the data layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rag-app/
├── main.py                          # FastAPI application entry point
├── endpoints.py                     # API route definitions
├── rag.py                           # Core RAG logic &amp;amp; LLM orchestration
├── vector_stores/                   # Vector Database integrations
│   ├── __init__.py
│   ├── pinecone_store.py            # Managed Cloud Vector DB
│   ├── faiss_store.py               # Local Disk FAISS
│   ├── s3_store.py                  # AWS S3 backed FAISS
│   └── gcs_store.py                 # Google Cloud Storage backed FAISS
├── data/                            # Your raw PDFs, TXTs, MDs, etc.
├── .env                             # Environment variables
└── requirements.txt                 # Dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To follow along, make sure your core dependencies are installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;fastapi uvicorn langchain langchain-core langchain-google-genai langchain-pinecone pinecone pydantic python-dotenv faiss-cpu google-cloud-storage boto3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. The Data Layer: Multi-Backend Vector Stores
&lt;/h2&gt;

&lt;p&gt;Vector stores hold our document "embeddings" (mathematical representations of text in n-dimensional space). This allows us to perform rapid "similarity searches" using cosine similarity or euclidean distance to find text chunks semantically related to a user's question.&lt;/p&gt;

&lt;p&gt;Because production environments vary, we designed our data layer to be dynamic based on environment variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Cloud-Native with Pinecone
&lt;/h3&gt;

&lt;p&gt;For a fully managed experience, we use Pinecone (&lt;code&gt;vector_stores/pinecone_store.py&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_pinecone&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PineconeVectorStore&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_text_splitters&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.document_loaders&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DirectoryLoader&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pinecone&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Pinecone&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup_pinecone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_dir&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Setup Pinecone vector store&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;index_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PINECONE_INDEX_NAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rag-index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pinecone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PINECONE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Idempotency: Avoid re-processing if the index is already populated
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe_index_stats&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;total_vector_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Loading existing Pinecone index...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PineconeVectorStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Creating new Pinecone index from documents...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DirectoryLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/*.*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Chunk the documents to prevent hitting LLM context windows
&lt;/span&gt;    &lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;document_chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;PineconeVectorStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document_chunks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;index_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Takeaways here:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Idempotency&lt;/strong&gt;: We check &lt;code&gt;index.describe_index_stats()&lt;/code&gt; to ensure we don't ingest the same data multiple times on server restarts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chunking&lt;/strong&gt;: &lt;code&gt;RecursiveCharacterTextSplitter&lt;/code&gt; breaks huge documents into smaller 500-character chunks with a 50-character overlap (to prevent cutting ideas in half).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Option B: Local &amp;amp; Cloud-Backed FAISS
&lt;/h3&gt;

&lt;p&gt;If you don't want to use a managed service, FAISS is incredibly fast. However, FAISS runs in-memory. To make it durable across deployments, we've implemented loaders that sync the index directory to S3 or GCS.&lt;/p&gt;

&lt;p&gt;Here is a look at our GCS implementation (&lt;code&gt;vector_stores/gcs_store.py&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.cloud&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_community.vectorstores&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FAISS&lt;/span&gt;
&lt;span class="c1"&gt;# ... imports omitted for brevity
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_faiss_to_gcs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gcs_prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;faiss_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;local_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/faiss_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save_local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Upload local FAISS index files to GCS
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;gcs_prefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upload_from_filename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_faiss_from_gcs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bucket_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gcs_prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;faiss_index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Downloads files back from GCS to local disk before instantiating FAISS
&lt;/span&gt;    &lt;span class="c1"&gt;# ...
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;FAISS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_local&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;allow_dangerous_deserialization&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;setup_faiss_gcs&lt;/code&gt; function tries to load from GCS first; if the index isn't there, it creates it locally from the &lt;code&gt;data/&lt;/code&gt; folder and then pushes it to the bucket. We have an identical setup for AWS S3 using &lt;code&gt;boto3&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The Brains: Orchestrating with LangChain (LCEL)
&lt;/h2&gt;

&lt;p&gt;Now we need to glue together our embedding model, our vector store, our prompt, and our Gemini LLM. LangChain makes this elegant using the LangChain Expression Language (LCEL).&lt;/p&gt;

&lt;p&gt;Let's look at &lt;code&gt;rag.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_google_genai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GoogleGenerativeAIEmbeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ChatGoogleGenerativeAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.prompts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatPromptTemplate&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.runnables&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RunnablePassthrough&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.output_parsers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StrOutputParser&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;vector_stores&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;setup_faiss&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup_pinecone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup_faiss_gcs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;setup_faiss_s3&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;google_api_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GOOGLE_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DATA_DIR&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;vector_store_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VECTOR_STORE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;faiss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;use_gcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USE_GCS_STORAGE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;use_s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USE_S3_STORAGE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Initialize the Generator LLM (Gemini 2.5 Flash)
&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatGoogleGenerativeAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;google_api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;google_api_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup_rag_system&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# 2. Setup Embeddings
&lt;/span&gt;    &lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GoogleGenerativeAIEmbeddings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-embedding-001&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;google_api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;google_api_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Dynamically route to the right vector database
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;vector_store_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pinecone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;vector_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setup_pinecone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;use_gcs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;vector_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setup_faiss_gcs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;use_s3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;vector_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setup_faiss_s3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;vector_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setup_faiss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Create the Retriever (Fetch Top 5 most relevant chunks)
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vector_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_retriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;search_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;similarity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;search_kwargs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;k&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_qa_chain&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;retriever&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setup_rag_system&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# 5. Construct the System Prompt
&lt;/span&gt;    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ChatPromptTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Answer the question based strictly on the following context:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;{context}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Question: {question}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;format_docs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_content&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 6. Build the LCEL Pipeline
&lt;/span&gt;    &lt;span class="n"&gt;chain&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;retriever&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;format_docs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;RunnablePassthrough&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;
        &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;StrOutputParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;

&lt;span class="c1"&gt;# Create a singleton instance to use across API calls
&lt;/span&gt;&lt;span class="n"&gt;qa_chain_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_qa_chain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_rag_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;qa_chain_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deep Dive into LCEL: How data relates
&lt;/h3&gt;

&lt;p&gt;The most beautiful part of this script is Langchain's piping syntax:&lt;br&gt;&lt;br&gt;
&lt;code&gt;{"context": retriever | format_docs, ...} | prompt | llm | StrOutputParser()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here is exactly what happens when &lt;code&gt;qa_chain_instance.invoke("What is our refund policy?")&lt;/code&gt; is called:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Routing&lt;/strong&gt;: The query &lt;code&gt;"What is our refund policy?"&lt;/code&gt; is passed to the dictionary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval&lt;/strong&gt;: For the &lt;code&gt;context&lt;/code&gt; key, the query goes into the &lt;code&gt;retriever&lt;/code&gt;. The retriever converts the text to a vector using &lt;code&gt;gemini-embedding-001&lt;/code&gt;, searches Pinecone/FAISS, and returns the top 5 &lt;code&gt;Document&lt;/code&gt; objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formatting&lt;/strong&gt;: Those 5 documents are piped (&lt;code&gt;|&lt;/code&gt;) into &lt;code&gt;format_docs&lt;/code&gt;, which extracts the raw text and concatenates it with double newlines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompting&lt;/strong&gt;: The filled dictionary (context + question) is piped into the &lt;code&gt;ChatPromptTemplate&lt;/code&gt;, injecting the values into the string.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generation&lt;/strong&gt;: The massive prompt is sent to &lt;code&gt;gemini-2.5-flash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parsing&lt;/strong&gt;: Because ChatModels return metadata-heavy AI Message objects, the &lt;code&gt;StrOutputParser&lt;/code&gt; extracts just the raw markdown string.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of this happens synchronously or asynchronously, abstracted cleanly into one chain.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Exposing the Pipeline via FastAPI
&lt;/h2&gt;

&lt;p&gt;To facilitate the deployment of this pipeline for operational use, we expose it over HTTP using &lt;strong&gt;FastAPI&lt;/strong&gt;. By leveraging FastAPI's Pydantic integrations, we effortlessly add strict input validation and automatic OpenAPI (Swagger) documentation.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;endpoints.py&lt;/code&gt;, we define the &lt;code&gt;/chat&lt;/code&gt; route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;rag&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_rag_response&lt;/span&gt;

&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Define our expected JSON Request Body
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;chat_input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_rag_system&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Pass the input securely to our RAG service
&lt;/span&gt;        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;get_rag_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in &lt;code&gt;main.py&lt;/code&gt;, we strap it all together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;endpoints&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RAG Application with Langchain and Gemini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Register our route controllers
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Running, Testing, and Deployment Options
&lt;/h2&gt;

&lt;p&gt;To fire up your robust new RAG server, spin up Uvicorn in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn main:app &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the server spins up on &lt;code&gt;http://127.0.0.1:8000&lt;/code&gt;. Thanks to FastAPI, you instantly have an interactive UI available.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit &lt;code&gt;http://127.0.0.1:8000/docs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open the &lt;code&gt;POST /chat&lt;/code&gt; endpoint.&lt;/li&gt;
&lt;li&gt;Pass a payload into the &lt;code&gt;chat_input&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"chat_input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What data formatting does our application support?"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, the system will embed your query, search your data sources, generate a context-aware prompt, consult Google Gemini, and seamlessly stream back a laser-accurate answer over HTTP. &lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying to Production
&lt;/h3&gt;

&lt;p&gt;Because the entire app is stateless (state is managed by Pinecone/S3/GCS), you can quickly containerize this application with Docker. &lt;/p&gt;

&lt;p&gt;Example Docker command flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy the image to Google Cloud Run, AWS App Runner, or Railway, provide your &lt;code&gt;.env&lt;/code&gt; variables, and you have an instantaneously scalable AI backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion &amp;amp; Next Steps
&lt;/h2&gt;

&lt;p&gt;Building an intelligent, context-aware chatbot doesn't require a messy monolith of code. By cleanly separating our concerns—FastAPI for networking, Langchain for orchestration, Pinecone/FAISS for storage, and Google Gemini for raw intelligence—we've crafted a highly scalable codebase.&lt;/p&gt;

&lt;p&gt;Where to go from here?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Conversation Memory&lt;/strong&gt;: Try wrapping our chain in &lt;code&gt;RunnableWithMessageHistory&lt;/code&gt; to sustain complex, multi-turn chat interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata Filtering&lt;/strong&gt;: If you serve multiple users, update the Pinecone/FAISS retriever to apply metadata filtering based on &lt;code&gt;user_id&lt;/code&gt;, ensuring strict data isolation per user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentic Workflows&lt;/strong&gt;: Replace our linear chain with &lt;code&gt;langgraph&lt;/code&gt; to allow the LLM to decide whether it needs to search the vector database, search the web, or use an API tool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Happy Coding!&lt;/strong&gt; Let me know in the comments how you plan to use RAG in your own projects, and if you have any questions setting up your vector indexes!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Secure PIN Processing: A Deep Dive into ISO 9564-1 PIN Blocks, RSA, and AES Encryption</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Fri, 13 Feb 2026 21:55:36 +0000</pubDate>
      <link>https://dev.to/instanceofgod/secure-pin-processing-a-deep-dive-into-iso-9564-1-pin-blocks-triple-des-and-rsa-2dip</link>
      <guid>https://dev.to/instanceofgod/secure-pin-processing-a-deep-dive-into-iso-9564-1-pin-blocks-triple-des-and-rsa-2dip</guid>
      <description>&lt;p&gt;In the modern payments landscape, security isn’t just a feature — it’s the absolute foundation. Every time you type your PIN into an ATM, a point-of-sale (POS) terminal, or a payment app, you are trusting a complex, global system with your financial identity. That simple 4-to-12 digit number initiates a sophisticated cryptographic handshake, orchestrated in milliseconds, to ensure your PIN remains a secret (never travels in “clear text”) from the moment it leaves your fingertips to the moment it’s verified by your bank.&lt;/p&gt;

&lt;p&gt;In this article, we’ll break down the mechanics of the &lt;strong&gt;ISO 9564–1 Format 0 (ISO-0)&lt;/strong&gt; PIN block — the industry-standard recipe for protecting a PIN.&lt;/p&gt;

&lt;p&gt;More importantly, we’ll build a robust, full-stack architecture that uses a powerful combination of &lt;strong&gt;RSA-OAEP and AES&lt;/strong&gt; (Advanced Encryption Standard) to keep this sensitive data secure all the way from the browser to the backend.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note on Security Standards: While many legacy systems still use Triple DES (3DES), it’s important to note that NIST deprecated 3DES in 2023 due to vulnerabilities (e.g., CVE-2016–2183) and its small 64-bit block size. Modern implementations should use AES-256 for symmetric encryption, which is what we’ll implement here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&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%2Fjo4jplj7kz0moqbxhlya.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%2Fjo4jplj7kz0moqbxhlya.png" alt="Secure PIN Processing" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: The Anatomy of an ISO-0 PIN Block
&lt;/h2&gt;

&lt;p&gt;The ISO-0 format (also known as ANSI X9.8) is the classic, widely-adopted industry standard for protecting PINs. It works by combining the user’s PIN with their Card Number (&lt;strong&gt;PAN&lt;/strong&gt;) using a bitwise &lt;strong&gt;XOR operation&lt;/strong&gt;. Its genius lies in its simplicity: it combines the secret (&lt;strong&gt;PIN&lt;/strong&gt;) with the known (PAN) to ensure the final encrypted block is unique to that specific card and transaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Constructing the PIN Field.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We start by creating a fixed-length, 8-byte (16 hex character) block dedicated to the PIN.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First Nibble (4 bits)&lt;/strong&gt;: The control digit. For Format 0, this is  always 0.
Second Nibble: The length of the PIN. A PIN 1234 has a length of 4, so we use 4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The PIN&lt;/strong&gt;: The actual PIN digits, stored as hexadecimal characters. 1234 becomes 12 34.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Padding&lt;/strong&gt;: The remaining bytes are filled with the hexadecimal value F (1111 binary) to reach the full 8-byte length.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: PIN 1234 becomes the 16-character hex string: 0 4 12 34 FF FF FF FF -&amp;gt; 041234FFFFFFFFFF.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Constructing the PAN Field.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we encrypted the PIN field directly, the same PIN for two different cards would produce the same encrypted block — a massive security vulnerability. To prevent this, we “salt” the PIN with the cardholder’s PAN. The standard method uses the last 12 digits of the card number, excluding the final check digit (the Luhn digit). This 12-digit number is then left-padded with zeros to create another 8-byte (16 hex character) block.&lt;/p&gt;

&lt;p&gt;Example: PAN 4012345678901234 (last digit 4 is the check digit). We take 012345678901 and pad it: 0000123456789012.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The XOR Operation: The Digital Blender.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final Clear PIN Block is produced by XORing the PIN Field and the PAN Field together. XOR is a bitwise operation that compares two bits. If the bits are the same, the result is 0; if they are different, the result is 1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PIN Field:     04 12 34 FF FF FF FF FF
PAN Field:     00 00 12 34 56 78 90 12
XOR Operation: ---------------------------------
Clear PIN Block: 04 12 26 CB A9 87 6F ED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This resulting 8-byte block is now ready for its final layer of protection: encryption. The beauty of XOR is that it’s mathematically reversible. When the bank receives the encrypted block, they decrypt it and XOR the result with the same PAN digits to retrieve the original PIN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: The Architecture of Trust — Never Expose the Master Key
&lt;/h2&gt;

&lt;p&gt;The formatting is only half the battle. The true test of a secure system is how it manages its cryptographic keys.&lt;/p&gt;

&lt;p&gt;A common mistake in payment app designs is placing the symmetric encryption key &lt;strong&gt;— the Zone PIN Key (ZPK)&lt;/strong&gt; — directly on the frontend. This is a catastrophic security risk. If a malicious actor can inspect your JavaScript code, decompile your mobile app, or intercept network traffic, they can steal the key and decrypt any user’s PIN.&lt;/p&gt;

&lt;p&gt;The solution to this is a Hybrid Encryption Architecture. This approach leverages the strengths of two different types of cryptography to create a robust, defense-in-depth security model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Cryptographic Handshake Workflow&lt;/strong&gt;&lt;br&gt;
Here is how a secure system handles a transaction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Key Exchange (The Setup):&lt;/strong&gt; When the client application (e.g., a web browser) starts, its first action is to request an RSA Public Key from the server. This key is designed for encryption only.&lt;br&gt;
&lt;strong&gt;2. Frontend Encryption (The Seal):&lt;/strong&gt; The user enters their PIN and PAN. The browser, using the Web Crypto API, performs a critical operation. It encrypts the raw JSON data containing the {pin, pan} using the server's RSA Public Key and the secure RSA-OAEP padding scheme. This is the seal. Because RSA is asymmetric, the frontend can encrypt data with the public key, but it is mathematically infeasible for it—or any attacker—to decrypt it. The private key is the only thing that can break the seal.&lt;br&gt;
&lt;strong&gt;3. Secure Transmission (The Courier):&lt;/strong&gt; The resulting encrypted binary blob is sent over HTTPS to the Node.js backend. Even if an attacker were to intercept this message, they would only see ciphertext that is useless without the private key.&lt;br&gt;
&lt;strong&gt;4. Backend Processing (The Vault):&lt;/strong&gt; Inside the secure environment of the server, the private key is used to decrypt the payload. Only now, with the raw pin and pan in memory, does the server perform the sensitive operations:&lt;br&gt;
It constructs the ISO-0 clear PIN block using the XOR logic.&lt;br&gt;
It then encrypts this block using the Zone PIN Key (ZPK) with the AES-256 algorithm.&lt;br&gt;
This layered approach ensures that the most critical secret — the ZPK — remains safely inside the server’s “trusted zone” and is never exposed to the user’s device — a potentially hostile environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 3: Under the Hood — Implementation Highlights (AES Edition)
&lt;/h2&gt;

&lt;p&gt;Let’s look at the code that brings this architecture to life, highlighting the critical security considerations at each layer — now updated to use AES.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend: Sealing the Secret with Web Crypto (JavaScript)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern browsers provide the Web Crypto API, a powerful, native layer for performing secure cryptographic operations without relying on potentially vulnerable external libraries. This part remains unchanged, as it handles the RSA encryption layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The data to protect
const dataToEncrypt = new TextEncoder().encode(
    JSON.stringify({ pin: userPIN, pan: userPAN })
);
const encryptedData = await window.crypto.subtle.encrypt(
    {
        name: "RSA-OAEP"
    },
    importedPublicKey, 
    dataToEncrypt
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backend: The Vault Logic with AES (Node.js)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On the server, we reconstruct the PIN block. A crucial detail here is the use of setAutoPadding(false). PIN block encryption is a very specific operation. The input must be exactly 8 bytes, and the output must be exactly 8 bytes. Standard block cipher padding schemes like PKCS#7 would alter the length, breaking the strict format required by the ISO standard.&lt;/p&gt;

&lt;p&gt;With AES, we must also specify the correct mode. For PIN block encryption, AES in ECB mode is typically used to maintain compatibility with legacy systems, though other modes can be used with careful IV management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const crypto = require('crypto');

/**
 * Encrypts an 8-byte clear PIN block using AES-256
 * @param {Buffer} clearBlockBuffer - The 8-byte clear PIN block
 * @param {string} zpkHex - The Zone PIN Key in hex (32 bytes for AES-256)
 * @returns {Buffer} - The 8-byte encrypted PIN block
 */
function encryptPinBlockWithAES(clearBlockBuffer, zpkHex) {
    // Ensure we're working with a 32-byte key for AES-256
    const key = Buffer.from(zpkHex, 'hex');
    if (key.length !== 32) {
        throw new Error('AES-256 requires a 32-byte (64 hex character) key');
    }

    // Create AES-256 cipher in ECB mode
    // Note: ECB mode is used here for PIN block compatibility
    const cipher = crypto.createCipheriv('aes-256-ecb', key, null);

    // CRITICAL: Disable automatic padding. PIN blocks are exactly 8 bytes.
    cipher.setAutoPadding(false); 

    // Encrypt the 8-byte clear block to produce an 8-byte encrypted block
    return Buffer.concat([cipher.update(clearBlockBuffer), cipher.final()]);
}

// Example usage:
// const encryptedPinBlock = encryptPinBlockWithAES(clearBlockBuffer, zpkHex);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 4: Beyond the PIN Block — The Wider World of Payment Security
&lt;/h2&gt;

&lt;p&gt;While the ISO-0 PIN block is fundamental for “Card Present” transactions (like at an ATM or a chip-enabled terminal), it’s just one piece of a much larger security puzzle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- CVV/CVC (Card Verification Value):&lt;/strong&gt; This is the static 3 or 4-digit code printed on your card. It’s not a random number. It’s cryptographically calculated by the issuing bank using a secret Card Verification Key (CVK) and specific data from your card (like PAN and expiry date). It serves as proof that you are in physical possession of the card during a “Card Not Present” (online) transaction.&lt;br&gt;
&lt;strong&gt;- 3D Secure (3DS):&lt;/strong&gt; This is the protocol behind challenges like “Verified by Visa” or “Mastercard SecureCode.” It’s an active, real-time authentication layer that shifts liability for fraud from the merchant to the card issuer. By redirecting the user to their bank’s authentication page (or sending an OTP), it provides an extra layer of proof that the legitimate cardholder is initiating the transaction.&lt;br&gt;
&lt;strong&gt;- Tokenization:&lt;/strong&gt; Modern payment systems often replace sensitive PAN data with tokens. This further reduces risk by ensuring that even if data is intercepted, the actual card number isn’t exposed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: The Future of PIN Security&lt;/strong&gt;&lt;br&gt;
Building secure payment systems is not about using a single, unbreakable lock. It’s about understanding how to combine different cryptographic primitives — like XOR for formatting, asymmetric RSA for secure key exchange, and symmetric AES for robust data encryption — into a cohesive, layered defense.&lt;/p&gt;

&lt;p&gt;By strictly separating the “encryption” layer on the client from the “translation and final sealing” layer on the server, we create a system where a user’s most sensitive data — their PIN — is protected from the moment it is typed until it reaches the secure confines of the banking switch. It’s a fascinating and critical field where mathematical principles are the bedrock of global financial trust.&lt;/p&gt;

&lt;p&gt;For a complete, runnable implementation of this architecture with AES encryption, check out thi &lt;a href="https://github.com/nielvid/pin-blocks-3des-rsa" rel="noopener noreferrer"&gt;repository&lt;/a&gt;. The code provides a practical, end-to-end example of the concepts discussed in this article.&lt;/p&gt;

</description>
      <category>security</category>
      <category>pin</category>
      <category>encryption</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Cloud Resume API Challenge with GCP</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Sun, 21 Jul 2024 17:26:52 +0000</pubDate>
      <link>https://dev.to/instanceofgod/cloud-resume-api-challenge-with-gcp-c1j</link>
      <guid>https://dev.to/instanceofgod/cloud-resume-api-challenge-with-gcp-c1j</guid>
      <description>&lt;p&gt;The job search can be a competitive landscape, and having a standout resume is crucial. But what if your resume could be even more dynamic and accessible? Enter the Cloud Resume API Challenge, a fantastic opportunity to showcase your technical skills and create a modern, API-driven resume. &lt;/p&gt;

&lt;p&gt;The primary goal of the challenge is to construct a serverless API that can serve resume data in JSON format. In order to achieve the goal of the project i utilised google cloud resources, particularly Google Cloud Functions and Cloud Firestore, along with  GitHub Actions for continuous delivery and continuous deployment (CI/CD).&lt;/p&gt;

&lt;p&gt;Not only did I gain valuable insights into the world of resume APIs, but I also honed my skills in several key areas which I decided to share with you here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Cloud Functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I delved into the world of cloud functions, a serverless execution environment that allows you to run code without managing servers. This was a great way to create a lightweight and scalable backend for my API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Cloud Firestore&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cloud Firestore, a NoSQL database, served as the perfect storage solution for my resume data. Its flexible schema and ease of use made it a breeze to manage my information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Google APIs&lt;/strong&gt;&lt;br&gt;
Working with Google APIs provided a powerful way to interact with my Cloud Firestore data and expose it through the API.&lt;br&gt;
Building the Cloud Function with Node.js&lt;/p&gt;

&lt;p&gt;For the challenge, I opted to use Node.js with JavaScript as my development environment. Here's a sample code snippet showcasing a basic Cloud Function that retrieves resume data from Firestore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Firestore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@google-cloud/firestore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@google-cloud/functions-framework&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&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="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;http&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resume&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Firestore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;projectId&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;PROJECT_ID&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resume&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kZXU70VsRQ2OuDBAjE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;This function retrieves data from a collection named "resume" in Firestore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. CI/CD with GitHub Actions&lt;/strong&gt;&lt;br&gt;
I implemented a CI/CD pipeline using GitHub Actions to ensured automated deployment to cloud function whenever I pushed changes to my code.&lt;/p&gt;

&lt;p&gt;Beyond the Basics&lt;/p&gt;

&lt;p&gt;The Cloud Resume API Challenge offers a springboard for further exploration. Here are some ways to take your project to the next level:&lt;/p&gt;

&lt;p&gt;Authentication and Authorization: Implement mechanisms to control access to your resume data using authentication and authorization techniques.&lt;br&gt;
Versioning: Integrate versioning to track changes to your resume data over time.&lt;br&gt;
Additional Data Points: Include additional data points like portfolio links or project details to make your resume more interactive.&lt;br&gt;
A Rewarding Journey&lt;/p&gt;

&lt;p&gt;Participating in the Cloud Resume API Challenge was a rewarding journey. It allowed me to showcase my technical skills, build a modern resume format, and gain valuable experience with cloud technologies. If you're looking for a way to stand out from the crowd and level up your technical expertise, I highly recommend giving this challenge a try!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>4 Ways to backup mySql database to a csv file</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Thu, 13 Jun 2024 10:44:01 +0000</pubDate>
      <link>https://dev.to/instanceofgod/4-ways-to-backup-mysql-database-to-a-csv-file-3e9j</link>
      <guid>https://dev.to/instanceofgod/4-ways-to-backup-mysql-database-to-a-csv-file-3e9j</guid>
      <description>&lt;p&gt;There are several methods to create a CSV backup of your MySQL database. Some third-party database management tools offer additional features for backing up to CSV.&lt;br&gt;
If you prefer command-line control, the mysqldump utility is powerful and flexible. If you are familiar with the python programing language, there are packages to help you write python scripts to backup your database. The method you choose depends on your comfort level and technical expertise&lt;/p&gt;

&lt;p&gt;In this article, i share 4 different ways to backup your MySQL database to a CSV file.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using &lt;code&gt;mysqldump&lt;/code&gt; and &lt;code&gt;mysql&lt;/code&gt; Command-Line Tools
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Export the Database to SQL File&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use &lt;code&gt;mysqldump&lt;/code&gt; to create a dump of your database. This step is optional but useful for backing up the entire database structure and data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   mysqldump &lt;span class="nt"&gt;-u&lt;/span&gt; username &lt;span class="nt"&gt;-p&lt;/span&gt; database_name &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; database_backup.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;username&lt;/code&gt; with your MySQL username, &lt;code&gt;database_name&lt;/code&gt; with the name of the database, and &lt;code&gt;database_backup.sql&lt;/code&gt; with the name you want for your backup file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Export Table to CSV File&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can export a specific table to a CSV file using the &lt;code&gt;SELECT&lt;/code&gt; statement with &lt;code&gt;INTO OUTFILE&lt;/code&gt; in MySQL. Here’s how you can do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;   &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;
   &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;OUTFILE&lt;/span&gt; &lt;span class="s1"&gt;'/path/to/your/file.csv'&lt;/span&gt;
   &lt;span class="n"&gt;FIELDS&lt;/span&gt; &lt;span class="n"&gt;TERMINATED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;
   &lt;span class="n"&gt;ENCLOSED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt;
   &lt;span class="n"&gt;LINES&lt;/span&gt; &lt;span class="n"&gt;TERMINATED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;table_name&lt;/code&gt; with the name of the table you want to export, and &lt;code&gt;/path/to/your/file.csv&lt;/code&gt; with the full path where you want to save the CSV file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the MySQL server has the appropriate permissions to write to the specified path.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;FIELDS TERMINATED BY ','&lt;/code&gt; specifies that fields are separated by commas.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ENCLOSED BY '"'&lt;/code&gt; ensures that fields are enclosed in double quotes.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;LINES TERMINATED BY '\n'&lt;/code&gt; specifies the end of a row.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Run the SQL Command&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can execute the SQL command directly through the MySQL shell or using a script. Here’s how to do it from the MySQL shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   mysql &lt;span class="nt"&gt;-u&lt;/span&gt; username &lt;span class="nt"&gt;-p&lt;/span&gt; database_name &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"SELECT * FROM table_name INTO OUTFILE '/path/to/your/file.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;' LINES TERMINATED BY '&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;';"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the placeholders with your actual database details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example in MySQL Shell
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to MySQL:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   mysql &lt;span class="nt"&gt;-u&lt;/span&gt; username &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Select the database:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;   &lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="n"&gt;database_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Export the table:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;   &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;
   &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;OUTFILE&lt;/span&gt; &lt;span class="s1"&gt;'/path/to/your/file.csv'&lt;/span&gt;
   &lt;span class="n"&gt;FIELDS&lt;/span&gt; &lt;span class="n"&gt;TERMINATED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;
   &lt;span class="n"&gt;ENCLOSED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt;
   &lt;span class="n"&gt;LINES&lt;/span&gt; &lt;span class="n"&gt;TERMINATED&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Permissions Note&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure the MySQL user has the &lt;code&gt;FILE&lt;/code&gt; privilege to write files to the server.&lt;/li&gt;
&lt;li&gt;The directory specified in the &lt;code&gt;INTO OUTFILE&lt;/code&gt; path must be writable by the MySQL server process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using a Bash Script
&lt;/h2&gt;

&lt;p&gt;For automation, you can create a script (e.g., &lt;code&gt;db_backup.sh&lt;/code&gt;) to export the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;DB_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;
&lt;span class="nv"&gt;DB_PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;
&lt;span class="nv"&gt;DB_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"database_name"&lt;/span&gt;
&lt;span class="nv"&gt;TABLE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"table_name"&lt;/span&gt;
&lt;span class="nv"&gt;OUTPUT_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/your/file.csv"&lt;/span&gt;

mysql &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nv"&gt;$DB_USER&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASS&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"SELECT * FROM &lt;/span&gt;&lt;span class="nv"&gt;$TABLE_NAME&lt;/span&gt;&lt;span class="s2"&gt; INTO OUTFILE '&lt;/span&gt;&lt;span class="nv"&gt;$OUTPUT_FILE&lt;/span&gt;&lt;span class="s2"&gt;' FIELDS TERMINATED BY ',' ENCLOSED BY '&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;' LINES TERMINATED BY '&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;';"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make the script executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x db_backup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The run the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./db_backup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Python and the pandas library
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install the necessary packages&lt;/strong&gt;:
You need to install &lt;code&gt;pandas&lt;/code&gt; and &lt;code&gt;mysql-connector-python&lt;/code&gt; (or &lt;code&gt;PyMySQL&lt;/code&gt;) to connect to the MySQL database and manipulate the data.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   pip &lt;span class="nb"&gt;install &lt;/span&gt;pandas mysql-connector-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a Python script&lt;/strong&gt;:
sample script to export a MySQL table to a CSV file using &lt;code&gt;pandas&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
   &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mysql.connector&lt;/span&gt;

   &lt;span class="c1"&gt;# Database configuration
&lt;/span&gt;   &lt;span class="n"&gt;db_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="c1"&gt;# SQL query to select data from the table
&lt;/span&gt;   &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM table_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

   &lt;span class="c1"&gt;# Connect to the MySQL database
&lt;/span&gt;   &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;db_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="c1"&gt;# Read data from the database into a pandas DataFrame
&lt;/span&gt;   &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="c1"&gt;# Close the connection
&lt;/span&gt;   &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

   &lt;span class="c1"&gt;# Export the DataFrame to a CSV file
&lt;/span&gt;   &lt;span class="n"&gt;output_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/path/to/your/file.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
   &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data has been exported to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code Explanation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Database Configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;'username'&lt;/code&gt;, &lt;code&gt;'password'&lt;/code&gt;, &lt;code&gt;'localhost'&lt;/code&gt;, and &lt;code&gt;'database_name'&lt;/code&gt; with your actual database credentials.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SQL Query&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;query&lt;/code&gt; variable holds the SQL query to select all data from the specified table. Replace &lt;code&gt;'table_name'&lt;/code&gt; with the name of the table you want to export.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Connecting to the Database&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Establish a connection to the MySQL database using &lt;code&gt;mysql.connector.connect()&lt;/code&gt; with the provided configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reading Data into a DataFrame&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;pd.read_sql(query, connection)&lt;/code&gt; to execute the query and load the data into a pandas DataFrame.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Closing the Connection&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Close the database connection using &lt;code&gt;connection.close()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Exporting to CSV&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;df.to_csv(output_file, index=False)&lt;/code&gt; to export the DataFrame to a CSV file. Replace &lt;code&gt;'/path/to/your/file.csv'&lt;/code&gt; with the desired file path for the CSV file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Confirmation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Print a confirmation message indicating the location of the exported file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Running the Script
&lt;/h3&gt;

&lt;p&gt;Save the script to a file, for example &lt;code&gt;export_to_csv.py&lt;/code&gt;, and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python export_to_csv.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script will connect to the specified MySQL database, execute the query to retrieve data from the specified table, and export the data to a CSV file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using csvkit to Export a MySQL Table to a CSV File
&lt;/h2&gt;

&lt;p&gt;csvkit is a suite of command-line tools for converting to and working with CSV files. &lt;br&gt;
To export a MySQL table to a CSV file using csvkit, you can use the csvsql command.&lt;br&gt;
Certainly! &lt;code&gt;csvkit&lt;/code&gt; is a suite of command-line tools for converting to and working with CSV files. To export a MySQL table to a CSV file using &lt;code&gt;csvkit&lt;/code&gt;, you can use the &lt;code&gt;csvsql&lt;/code&gt; command.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install &lt;code&gt;csvkit and mysql-connector-python&lt;/code&gt;&lt;/strong&gt;:
Make sure you have &lt;code&gt;csvkit and mysql-connector-python&lt;/code&gt; installed. You can install it using pip:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   pip &lt;span class="nb"&gt;install &lt;/span&gt;csvkit mysql-connector-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;mysql.connector&lt;/span&gt;

&lt;span class="c1"&gt;# Database configuration
&lt;/span&gt;&lt;span class="n"&gt;db_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Table name and output file
&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;table_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;output_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/path/to/your/file.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# Connect to the MySQL database to get the connection details
&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;db_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Construct the csvsql command
&lt;/span&gt;&lt;span class="n"&gt;csvsql_command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;csvsql&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--db&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mysql+mysqlconnector://&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;db_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;db_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;db_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;db_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--query&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--output&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_file&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Execute the csvsql command
&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csvsql_command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Close the connection
&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data has been exported to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Database Configuration&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;'username'&lt;/code&gt;, &lt;code&gt;'password'&lt;/code&gt;, &lt;code&gt;'localhost'&lt;/code&gt;, and &lt;code&gt;'database_name'&lt;/code&gt; with your actual database credentials.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Table Name and Output File&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;'table_name'&lt;/code&gt; with the name of the table you want to export.&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;'/path/to/your/file.csv'&lt;/code&gt; with the desired file path for the CSV file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Connecting to the Database&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Establish a connection to the MySQL database using &lt;code&gt;mysql.connector.connect()&lt;/code&gt; with the provided configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Constructing the &lt;code&gt;csvsql&lt;/code&gt; Command&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;csvsql&lt;/code&gt; with the &lt;code&gt;--db&lt;/code&gt; option to specify the database connection string.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--query&lt;/code&gt; option specifies the SQL query to run.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;--output&lt;/code&gt; option specifies the output file for the CSV data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Executing the Command&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;subprocess.run()&lt;/code&gt; to execute the constructed &lt;code&gt;csvsql&lt;/code&gt; command.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Closing the Connection&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Close the database connection and cursor.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Confirmation&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Print a confirmation message indicating the location of the exported file.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Save the script to a file, for example &lt;code&gt;export_to_csv_with_csvkit.py&lt;/code&gt;, and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python export_to_csv_with_csvkit.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script will connect to the specified MySQL database, execute the query to retrieve data from the specified table, and export the data to a CSV file using &lt;code&gt;csvkit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note: The subprocess module in Python is used to spawn new processes, connect to their input/output/error pipes, and obtain their return codes&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It allows you to run external commands and interact with them programmatically. This is especially useful for automating command-line tasks and integrating external tools into your Python scripts.&lt;/p&gt;

&lt;p&gt;Key Functions in subprocess&lt;br&gt;
subprocess.run(): This function runs a command, waits for it to complete, and then returns a CompletedProcess instance.&lt;br&gt;
subprocess.Popen(): This is a more powerful and flexible function for spawning new processes. It allows more complex interactions with the process.&lt;/p&gt;

&lt;p&gt;Example Usage&lt;br&gt;
Here’s a simple example demonstrating the use of subprocess.run():&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;

&lt;span class="c1"&gt;# Define the command to run
&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;echo&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello, World!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Run the command
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capture_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Print the command's output
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Explanation of Parameters:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;command: A list where the first element is the command to run, and the subsequent elements are the arguments to the command.&lt;/p&gt;

&lt;p&gt;capture_output: If set to True, it captures the standard output and standard error.&lt;/p&gt;

&lt;p&gt;text: If set to True, the output is returned as a string instead of bytes.&lt;/p&gt;

&lt;p&gt;NOTE: the csvkit command an also be run as a one line command using if you have csvkitn installed. You can install csvkit with &lt;code&gt;pip install csvkit&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;csvsql &lt;span class="nt"&gt;--db&lt;/span&gt; mysql://[username]:[password]@localhost/[database_name] &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"SELECT * FROM [table_name]"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;output_file.csv]

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

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>JavaScript Array methods</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Sat, 01 Jun 2024 14:10:54 +0000</pubDate>
      <link>https://dev.to/instanceofgod/javascript-array-methods-26n</link>
      <guid>https://dev.to/instanceofgod/javascript-array-methods-26n</guid>
      <description>&lt;p&gt;JavaScript provides a rich set of array methods to manipulate and work with arrays. Here is a comprehensive list of these methods along with sample usage:&lt;/p&gt;

&lt;p&gt;Mutator Methods&lt;br&gt;
These methods modify the array they are called on.&lt;/p&gt;
&lt;h2&gt;
  
  
  push()
&lt;/h2&gt;

&lt;p&gt;Adds one or more elements to the end of an array and returns the new length of the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// arr is now [1, 2, 3, 4]&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  pop()
&lt;/h2&gt;

&lt;p&gt;Removes the last element from an array and returns that element.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// arr is now [1, 2]; lastElement is 3&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  shift()
&lt;/h2&gt;

&lt;p&gt;Removes the first element from an array and returns that element.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;firstElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// arr is now [2, 3]; firstElement is 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  unshift()
&lt;/h2&gt;

&lt;p&gt;Adds one or more elements to the beginning of an array and returns the new length of the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// arr is now [0, 1, 2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  splice()
&lt;/h2&gt;

&lt;p&gt;Adds and/or removes elements from an array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// arr is now [1, 'a', 'b', 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  sort()
&lt;/h2&gt;

&lt;p&gt;Sorts the elements of an array in place and returns the sorted array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// arr is now [1, 1, 3, 4, 5, 9]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  reverse()
&lt;/h2&gt;

&lt;p&gt;Reverses the order of the elements in an array in place.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// arr is now [3, 2, 1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Accessor Methods
&lt;/h2&gt;

&lt;p&gt;These methods do not modify the array and typically return a new array or a single value.&lt;/p&gt;

&lt;h2&gt;
  
  
  concat()
&lt;/h2&gt;

&lt;p&gt;Merges two or more arrays.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// newArr is [1, 2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  join()
&lt;/h2&gt;

&lt;p&gt;Joins all elements of an array into a string.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// str is '1-2-3'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  slice()
&lt;/h2&gt;

&lt;p&gt;Returns a shallow copy of a portion of an array into a new array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;slicedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// slicedArr is [2, 3]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  indexOf()
&lt;/h2&gt;

&lt;p&gt;Returns the first index at which a given element can be found in the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// index is 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  lastIndexOf()
&lt;/h2&gt;

&lt;p&gt;Returns the last index at which a given element can be found in the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastIndexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// index is 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  includes()
&lt;/h2&gt;

&lt;p&gt;Determines whether an array includes a certain value.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hasTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// hasTwo is true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  toString()
&lt;/h2&gt;

&lt;p&gt;Returns a string representing the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// str is '1,2,3'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  toLocaleString()
&lt;/h2&gt;

&lt;p&gt;Returns a localized string representing the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// str might vary based on locale&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Iteration Methods
&lt;/h2&gt;

&lt;p&gt;These methods iterate over the array, typically applying a function to each element.&lt;/p&gt;

&lt;h2&gt;
  
  
  forEach()
&lt;/h2&gt;

&lt;p&gt;Executes a provided function once for each array element.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  &lt;span class="c1"&gt;// logs 1, 2, 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  map()
&lt;/h2&gt;

&lt;p&gt;Creates a new array with the results of calling a provided function on every element.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;doubled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// doubled is [2, 4, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  filter()
&lt;/h2&gt;

&lt;p&gt;Creates a new array with all elements that pass the test implemented by the provided function.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;evens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// evens is [2, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  reduce()
&lt;/h2&gt;

&lt;p&gt;Applies a function against an accumulator and each element to reduce it to a single value.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;curr&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;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// sum is 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  reduceRight()
&lt;/h2&gt;

&lt;p&gt;Applies a function against an accumulator and each element (from right to left) to reduce it to a single value.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduceRight&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;curr&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;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;curr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// sum is 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  some()
&lt;/h2&gt;

&lt;p&gt;Tests whether at least one element passes the test implemented by the provided function.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hasEven&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// hasEven is true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  every()
&lt;/h2&gt;

&lt;p&gt;Tests whether all elements pass the test implemented by the provided function.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;allPositive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// allPositive is true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  find()
&lt;/h2&gt;

&lt;p&gt;Returns the first element that satisfies the provided testing function.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// found is 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  findIndex()
&lt;/h2&gt;

&lt;p&gt;Returns the index of the first element that satisfies the provided testing function.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// index is 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  flat()
&lt;/h2&gt;

&lt;p&gt;Creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]]];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;flatArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// flatArr is [1, 2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  flatMap()
&lt;/h2&gt;

&lt;p&gt;First maps each element using a mapping function, then flattens the result into a new array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;flatMapped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  &lt;span class="c1"&gt;// flatMapped is [1, 2, 2, 4, 3, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  entries()
&lt;/h2&gt;

&lt;p&gt;Returns a new Array Iterator object that contains the key/value pairs for each index in the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// logs 0 'a', 1 'b', 2 'c'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  keys()
&lt;/h2&gt;

&lt;p&gt;Returns a new Array Iterator that contains the keys for each index in the array.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// logs 0, 1, 2&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  values()
&lt;/h2&gt;

&lt;p&gt;Returns a new Array Iterator object that contains the values for each index in&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Securely Connecting to PostgreSQL on a Virtual Machine from Anywhere</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Mon, 22 Apr 2024 11:21:47 +0000</pubDate>
      <link>https://dev.to/instanceofgod/securely-connecting-to-postgresql-on-a-virtual-machine-from-anywhere-4ank</link>
      <guid>https://dev.to/instanceofgod/securely-connecting-to-postgresql-on-a-virtual-machine-from-anywhere-4ank</guid>
      <description>&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A virtual machine set up on a cloud provider (AWS, Google Cloud, Azure) or a local virtualization platform (VirtualBox).&lt;/li&gt;
&lt;li&gt;Basic understanding of command line and Linux concepts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deploying PostgreSQL on a Virtual Machine (VM) and connecting to it from anywhere involves several steps.  This guide walks you through deploying PostgreSQL on a Virtual Machine (VM) and connecting to it remotely with enhanced security practices.&lt;/p&gt;

&lt;p&gt;Once your VM is running, you'll need to install PostgreSQL. This process varies depending on the operating system of your VM, but it generally involves downloading and installing the PostgreSQL package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install and Configure PostgreSQL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.1. Update and Install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;postgresql postgresql-contrib &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1.2. Verify PostgreSQL user:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostgreSQL creates a user named &lt;code&gt;postgres&lt;/code&gt;. Verify its existence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cat&lt;/span&gt; /etc/passwd | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; postgres
postgres:x:113:120:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To connect to Postgres, switch to the &lt;code&gt;postgres&lt;/code&gt; user and run psql:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql
&lt;span class="nv"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1.3. Create a Secure User (Optional):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For better security, create a dedicated user for remote access instead of using the default &lt;code&gt;postgres&lt;/code&gt; user. We'll create a user named ubuntu and grant them necessary privileges based on your specific needs. Avoid granting superuser access (equivalent to &lt;code&gt;root&lt;/code&gt; in Linux) unless absolutely essential.&lt;/p&gt;

&lt;p&gt;To create a Postgres user run the following command which will give an interactive prompt for configuring the new user. For the sake of simplicity, the ubuntu user will be a superuser, which is the equivalent of being a root user on linux. The super user will have the ability to create/delete/modify databases and users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;createuser &lt;span class="nt"&gt;--interactive&lt;/span&gt;
Enter name of role to add: ubuntu
Shall the new role be a superuser? &lt;span class="o"&gt;(&lt;/span&gt;y/n&lt;span class="o"&gt;)&lt;/span&gt; y

&lt;span class="c"&gt;# Set password for myuser (replace 'password' with a strong password)&lt;/span&gt;
ALTER USER ubuntu PASSWORD &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;# Grant appropriate privileges (adjust as needed)&lt;/span&gt;
GRANT CONNECT ON DATABASE postgres TO ubuntu&lt;span class="p"&gt;;&lt;/span&gt;
GRANT CREATE DATABASE TO ubuntu&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="se"&gt;\q&lt;/span&gt;
&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Login to postgres using the &lt;code&gt;postgres&lt;/code&gt; user for now to verify the new &lt;code&gt;ubuntu&lt;/code&gt; user was created successfully&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql
Type &lt;span class="s2"&gt;"help"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;help.

&lt;span class="nv"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="c"&gt;# \du&lt;/span&gt;
                                   List of roles
 Role name |                         Attributes                         | Member of
&lt;span class="nt"&gt;-----------&lt;/span&gt;+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | &lt;span class="o"&gt;{}&lt;/span&gt;
 ubuntu    | Superuser, Create role, Create DB                          | &lt;span class="o"&gt;{}&lt;/span&gt;

&lt;span class="nv"&gt;postgres&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="c"&gt;#&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exit out of the psql by running &lt;code&gt;\q&lt;/code&gt; and also exit out of the &lt;code&gt;postgres&lt;/code&gt; user by running &lt;code&gt;exit&lt;/code&gt; on the command line&lt;/p&gt;

&lt;p&gt;Let's try to run &lt;code&gt;psql&lt;/code&gt; as the ubuntu user now. An error similar to the one below should be observed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;psql
psql: error: could not connect to server: FATAL:  database &lt;span class="s2"&gt;"ubuntu"&lt;/span&gt; does not exist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason for this is that Postgres by default tries to connect to a database that is the same name as the user. Since the user is &lt;code&gt;ubuntu&lt;/code&gt; it tries to connect to a database called &lt;code&gt;ubuntu&lt;/code&gt; as well which does not exist. We can go in and create a database called &lt;code&gt;ubuntu&lt;/code&gt; so that it will automatically connect, however I find this unnecessary. Instead we can pass in the &lt;code&gt;-d&lt;/code&gt; flag and connect to a database that we know exists like the &lt;code&gt;postgres&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-d&lt;/span&gt; postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above steps we have successfully installed and configured Postgres on the server.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Configure PostgreSQL to accept connections from any location. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default PostgreSQL is configured to be bound to “localhost”, on port 5432 . It means any attempt to connect to the postgresql server from outside the machine will be refused.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netstat &lt;span class="nt"&gt;-nlt&lt;/span&gt;
Proto Recv-Q Send-Q Local Address           Foreign Address         State

tcp        0      0 127.0.0.1:5432          0.0.0.0:&lt;span class="k"&gt;*&lt;/span&gt;               LISTEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To allow your postgres server to accept connection from any location or a specific location (IP address), you will need to edit two files:&lt;/p&gt;

&lt;p&gt;i.&lt;code&gt;pg_hba.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ii.&lt;code&gt;postgresql.conf&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use the following command to easily locate the files on your server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; postgres psql &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"SHOW hba_file"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"SHOW config_file"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;pg_hba.conf&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;From &lt;a href="https://www.postgresql.org/docs/11/auth-pg-hba-conf.html" rel="noopener noreferrer"&gt;20.1. The pg_hba.conf File&lt;/a&gt;: "_Client authentication is controlled by a configuration file, which traditionally is named pg_hba.conf and is stored in the database cluster's data directory. (HBA stands for host-based authentication.) _"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;host    all   all   0.0.0.0/0   trust
host    all   all   ::/0        trust

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;postgresql.conf&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The configuration file comes with helpful hints to get this working&lt;/p&gt;

&lt;p&gt;To allow your Postgres server to accept connection from any location or a specific location (IP address), change the listen_addresses from ‘localhost’ to the IP address of the server you want to connect from. To allow for connection from anywhere( not advised), change ‘localhost” to “*”.&lt;/p&gt;

&lt;p&gt;Remember, exposing your database to the internet comes with security risks. Always ensure you have strong, unique passwords and consider setting up additional security measures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;listen_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;          &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;IP&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;es&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="k"&gt;listen&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                                        &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;comma&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;separated&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                                        &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="k"&gt;defaults&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;all&lt;/span&gt;
                                        &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="k"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;For a quick and dirty solution just change it to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;listen_addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'*'&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Restart postgres
&lt;/h3&gt;

&lt;p&gt;After the configuration, you will need to restart the postgres server. Once PostgreSQL is restarted, it will start listening on all IP addresses. &lt;/p&gt;

&lt;p&gt;To restart PostgreSQL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart postgresql@11-main &lt;span class="c"&gt;# change 11 to the version of your postgres&lt;/span&gt;

&lt;span class="c"&gt;# or&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;pg_ctl restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open Postgres port on server firewall rule&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember to open the port that PostgreSQL uses (default is 5432) on your VM's firewall. This step will depend on your VM's operating system and firewall settings.&lt;/p&gt;

&lt;p&gt;Finally, you can connect to your PostgreSQL database from anywhere using a PostgreSQL client. You'll need your VM's public IP address, the database name, and the login credentials.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Secure Remote Connection with SSH Tunneling&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another option to securely connect to postgres server is by using SSH Tunneling. To enable secure remote access, we'll leverage SSH Tunneling. This creates an encrypted tunnel between your local machine and the VM, allowing you to connect to PostgreSQL through this secure channel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.1. Establish an SSH Tunnel:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use your preferred SSH client to create a tunnel. Here's an example command:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bash&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; 5433:localhost:5432 &amp;lt;username&amp;gt;@&amp;lt;VM_IP_Address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Replace the placeholders:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; with your VM username.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;VM_IP_Address&amp;gt;&lt;/code&gt; with the public IP address of your VM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This command creates a local port (5433) on your machine that forwards traffic to the PostgreSQL port (5432) on the VM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.2 Connect to PostgreSQL Remotely:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use a PostgreSQL client on your local machine and connect to:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;localhost:5433  &lt;span class="c"&gt;# Port you forwarded in the tunnel (5433)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use the credentials of the user you created (e.g., &lt;code&gt;ubuntu&lt;/code&gt;).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The steps above establish a secure connection using SSH Tunneling. To further enhance security, consider these additional measures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Never modify &lt;code&gt;listen_addresses&lt;/code&gt; in &lt;code&gt;postgresql.conf&lt;/code&gt; to &lt;code&gt;'*'&lt;/code&gt;. This exposes your database server to the entire internet, making it vulnerable to attacks.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure firewall rules on your VM to restrict access to the PostgreSQL port (default 5432) from only your specific IP address. This adds an extra layer of protection.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implement strong password policies and enforce secure user authentication methods. Utilize the &lt;code&gt;pg_hba.conf&lt;/code&gt; file to control which users can connect from where and how they can authenticate.&lt;/strong&gt; Refer to PostgreSQL documentation for detailed configuration options.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Conclusion:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By following these steps, you can securely connect to your PostgreSQL database on a VM from anywhere or by using SSH tunneling. Remember, security should be a top priority. Implement the additional security measures mentioned above to create a more robust defense for your database server.&lt;/p&gt;

&lt;p&gt;For further details on PostgreSQL configuration and security best practices, refer to the official PostgreSQL documentation &lt;a href="https://www.postgresql.org/docs/" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Helpful link and references:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/24504680/connect-to-postgres-server-on-google-compute-engine" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/24504680/connect-to-postgres-server-on-google-compute-engine&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Enable Password Authentication in AWS EC2 Instance</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Mon, 16 May 2022 13:56:26 +0000</pubDate>
      <link>https://dev.to/instanceofgod/enable-password-authentication-in-aws-ec2-instance-376b</link>
      <guid>https://dev.to/instanceofgod/enable-password-authentication-in-aws-ec2-instance-376b</guid>
      <description>&lt;p&gt;Password authentication is disabled by default in aws ec2 instance. The only way to access your server is by using ssh with  -i flag and followed by private key attached to the server.&lt;/p&gt;

&lt;p&gt;However, there are scenarios when you may need to access the server with just username and password. Take note that this method of accessing your server is not encouraged, as it could open your server to attacks. &lt;/p&gt;

&lt;h3&gt;
  
  
  How to Enable Password Authentication in EC2
&lt;/h3&gt;

&lt;p&gt;First, you have to ssh into your server with your private key to set password for the user and also make some changes to the sshd_config file.&lt;/p&gt;

&lt;p&gt;The steps to enable password authentication are highlighted below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Login to server
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -i privatekey username@host_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Setup a password for the user using the passwd command
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo passwd username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Open  and modify the &lt;code&gt;sshd_config&lt;/code&gt; file.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo vim /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you prefer to use nano as editor&lt;/p&gt;

&lt;p&gt;Changes the PasswordAuthentication line from ‘no’ to ‘yes’&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enable root login, Change value from “&lt;strong&gt;prohibit-password&lt;/strong&gt;” to “&lt;strong&gt;yes”&lt;/strong&gt; (Optional)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PermitRootLogin &lt;span class="nb"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Restart the “&lt;strong&gt;sshd&lt;/strong&gt;” service using the following command.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo service sshd restart

or 
sudo systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s all you have to do. Now you can login to the ec2 server using the password you set for the user, without the private key.&lt;/p&gt;

&lt;p&gt;When you type the command below, you will be prompted to enter your password!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>ssh</category>
      <category>password</category>
    </item>
    <item>
      <title>A beginners' Journey into Web Development.</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Mon, 16 Aug 2021 22:03:27 +0000</pubDate>
      <link>https://dev.to/instanceofgod/a-beginners-journey-into-web-development-2d72</link>
      <guid>https://dev.to/instanceofgod/a-beginners-journey-into-web-development-2d72</guid>
      <description>&lt;p&gt;Hey, thinking of starting a career into web development but don't know how and where to begin?&lt;/p&gt;

&lt;p&gt;One of the most difficult decision to make by beginners when venturing into web development is how to begin, and what resources are available to aid their learning.&lt;/p&gt;

&lt;p&gt;If this is where you find yourself now, like me, when I first  started learning web development ( I wish I had seen and read an article like this then), this article will help to provide a roadmap to help you to learn faster and better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start from the Basic.
&lt;/h2&gt;

&lt;p&gt;As foundation is important in construction, so is it in software development. Starting from the basic means starting from ground up, learning the foundational concepts of &lt;strong&gt;HTML&lt;/strong&gt; such as tags, semantics, structure, layout etc. Want to Start Learning HTML now, &lt;a href="https://www.tutorialrepublic.com/html-tutorial/" rel="noopener noreferrer"&gt;**https://www.tutorialrepublic.com/html-tutorial/&lt;/a&gt;** is one of the good site to start your journey into web development.&lt;/p&gt;

&lt;p&gt;You need to understand how to arrange elements on the web page, that is, putting elements where they ought to be on the page. One good tool that than help you achieve this is &lt;a href="https://figma.com" rel="noopener noreferrer"&gt;FIGMA&lt;/a&gt;. Learn more about figma &lt;a href="https://www.figma.com/resources/learn-design/" rel="noopener noreferrer"&gt;**HERE&lt;/a&gt; &lt;a href="https://trydesignlab.com/figma-101-course/introduction-to-figma/" rel="noopener noreferrer"&gt;https://trydesignlab.com/figma-101-course/introduction-to-figma/&lt;/a&gt;**&lt;/p&gt;

&lt;h2&gt;
  
  
  Advance to Aesthetics
&lt;/h2&gt;

&lt;p&gt;After you are comfortable with html and have a good knowledge of laying out your page, giving your code good visual appearance with &lt;strong&gt;CSS&lt;/strong&gt; is the next step. CSS is used for styling your HTML pages. While HTML is like an unpainted building, CSS is the 'paint' that makes the we page appealing to the eyes. &lt;/p&gt;

&lt;p&gt;Other Things to learn includes Version Control. Want to know more about Version Control using GIT, go to : &lt;a href="https://www.freecodecamp.org/news/learn-the-basics-of-git-in-under-10-minutes-da548267cc91/" rel="noopener noreferrer"&gt;&lt;strong&gt;https://www.freecodecamp.org/news/learn-the-basics-of-git-in-under-10-minutes-da548267cc91/&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose a Programming Language
&lt;/h3&gt;

&lt;p&gt;There are several programming languages that does different or same thing in different ways. &lt;/p&gt;

&lt;p&gt;You will need to decide your goal and objective for the future before deciding which one to learn first. Of course, you can learn many languages over time, but it is better to pick one and be a master of it, than not being able to do anything productive with the knowledge of several programming languages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples of Programming language&lt;/strong&gt; are:  PHP, Python, Java, JavaScript, Go, Rust, C#, C++, MySql, Kotlin, Ruby, Perl and many more. Make proper research about the language, what you can use it to achieve, whether it fulfils your future goal as a software developer. &lt;/p&gt;

&lt;p&gt;Fortunately, the internet abounds with resources- Video, Articles, Guides or Courses to make your learning journey smooth and sound. You can checkout the following resource:&lt;/p&gt;

&lt;p&gt;PHP - &lt;a href="https://www.w3schools.com/php/default.asp" rel="noopener noreferrer"&gt;https://www.w3schools.com/php/default.asp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JavaScript - &lt;a href="https://www.w3schools.com/js/default.asp" rel="noopener noreferrer"&gt;https://www.w3schools.com/js/default.asp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python - &lt;a href="https://www.w3schools.com/python/default.asp" rel="noopener noreferrer"&gt;https://www.w3schools.com/python/default.asp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go - &lt;a href="https://www.w3schools.com/go/index.php" rel="noopener noreferrer"&gt;https://www.w3schools.com/go/index.php&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programing</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>ESLint Prettier &amp; Husky Configuration for Project</title>
      <dc:creator>instanceofGod</dc:creator>
      <pubDate>Thu, 18 Mar 2021 11:39:57 +0000</pubDate>
      <link>https://dev.to/instanceofgod/eslint-prettier-husky-configuration-for-project-5f5a</link>
      <guid>https://dev.to/instanceofgod/eslint-prettier-husky-configuration-for-project-5f5a</guid>
      <description>&lt;h2&gt;
  
  
  Setting up Prettier with ESLint, and also checking commit with husky.
&lt;/h2&gt;

&lt;p&gt;You will need to install Eslint, Prettier and Pre-Commit.&lt;br&gt;
The 3 packages does different things, their usefulness are highlighted below: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ESLint - For Linting, and Enforcing Style Guide.&lt;/li&gt;
&lt;li&gt;Prettier -  For Code Formatting.&lt;/li&gt;
&lt;li&gt;Pre-Commit - For Making sure code that's being committed is followed guidelines and is formatted properly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;The packages can be installed locally in your project or globally:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Setting up ESLint&lt;/strong&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm install --save-dev eslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After installing eslint, you then need to set it up, that is, configure it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx eslint --init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sample of the text that will be inside the eslintrc.json file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"airbnb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint:recommended"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"prettier"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"semi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"quotes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"double"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"prettier/prettier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;choose&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;prettier&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rules.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Setting up Prettier&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm install --save-dev prettier eslint-config-prettier eslint-plugin-prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create .prettierrc file in your project’s root directory.&lt;/p&gt;

&lt;p&gt;You can type echo {} .prettierrc in your terminal to create the file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; .prettierrc 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be where you configure your prettier formatting settings.&lt;/p&gt;

&lt;p&gt;Sample of the settings you can configure inside the prettierrc.json file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"useTabs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"tabSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"semi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"trailingComma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"bracketSpacing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"parser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"typescript"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting up &lt;strong&gt;Pre-commit and Pre-push&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is a pretty important step. This will ensure that before any developer in your team commits any code, the changes made by him are validated with &lt;br&gt;
EsLint, and the code is properly formatted.&lt;/p&gt;

&lt;p&gt;The fastest way to start using lint-staged is to run following command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;npx mrm lint-staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will install and configure &lt;strong&gt;&lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;husky&lt;/a&gt;&lt;/strong&gt; and lint-staged depending on code quality tools from &lt;code&gt;package.json&lt;/code&gt; dependencies, so please make sure you install (&lt;code&gt;npm install --save-dev&lt;/code&gt;) and configure all code quality tools like &lt;strong&gt;&lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESlint&lt;/a&gt;&lt;/strong&gt; prior that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Another alternative to implement this;  we will need to configure some packages
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The First package we need is &lt;strong&gt;husky&lt;/strong&gt; which will make adding 
these hooks very easy.&lt;/li&gt;
&lt;li&gt;We also need a package called &lt;strong&gt;lint-staged&lt;/strong&gt; that will let us 
check only the pages which are changed. So, only the staged files are checked and the rest of the code 
remains untouched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pretty quick&lt;/strong&gt; will check for any unformatted files and 
format them using Prettier.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Installation of the packages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm install &lt;span class="nt"&gt;--save-dev&lt;/span&gt; husky lint-staged pretty-quick
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installing these packages we need to add configuration for these in our package.json file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"lint-staged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"*.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint --cache --fix"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"husky"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"pre-commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lint-staged &amp;amp;&amp;amp; pretty-quick --staged"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As the name suggests, when you're trying to commit the changes, this will run both commands  "lint-staged and pretty-quick".&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The lint-staged will run eslint command on javascript files 
that are staged,&lt;/li&gt;
&lt;li&gt;The pretty-quick will format the JavaScript files if they
 aren't using Prettier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of the staged files are not properly linted or formatted this will give you a warning and will stop you from committing the&lt;br&gt;
changes in the code.&lt;/p&gt;

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