Tuesday, 5 August 2025

React useCallback Hook



We'll use useCallback to :

  • Passing a function as prop to React.memo child
  • Prevents unnecessary re-renders
  • Setting up event handlers inside components
  • Prevents recreation of handler functions
  • Functions inside useEffect/useMemo that need stable reference
  • Avoids infinite loops or unnecessary logic execution
Example : 

import React, { useCallback, useState } from 'react';
import './App.css';
import Dashboard from './component/Dashboard';

const Child = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Click Me</button>;
});

function App() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log('Clicked');
  }, []);

  return (
    <div className="App">
      <Dashboard />
      <h2>React useCallback Example</h2>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child onClick={handleClick} />
    </div>
  );
}

export default App;

React useRef Hook


We'll use useRef to :

  • Automatically focus the input on mount.
  • Allow the user to click a "Focus Input" button to manually refocus.
  • Autofocuses an input on mount
  • Tracks the previous input value
  • Shows how many times the input changed without causing re-renders
Example : 

import { useRef, useEffect, useState } from 'react';

const TodoAppUseRef = () => {
  const inputRef = useRef(null); // Ref for input focus
  const prevInputRef = useRef(''); // Ref for previous input value
  const [tasks, setTasks] = useState([]);
  const [inputValue, setInputValue] = useState('');

  // Auto-focus input on mount
  useEffect(() => {
    inputRef.current?.focus();
  }, []);

  // Update previous input value after each change
  useEffect(() => {
    prevInputRef.current = inputValue;
  }, [inputValue]);

  const handleAddTask = () => {
    if (inputValue.trim()) {
      setTasks([...tasks, inputValue.trim()]);
      setInputValue('');
      inputRef.current?.focus(); // Refocus after adding
    }
  };

  return (
    <div style={{ padding: '2rem', fontFamily: 'Arial', maxWidth: 500 }}>
      <h2>📝 To-Do List</h2>

      {/* Input with ref and value tracking */}
      <input
        ref={inputRef}
        type="text"
        value={inputValue}
        placeholder="Enter a task..."
        onChange={(e) => setInputValue(e.target.value)}
        style={{
          padding: '0.5rem',
          width: '100%',
          marginBottom: '0.5rem',
          fontSize: '1rem',
        }}
      />

      {/* Previous value display */}
      <p style={{ fontSize: '0.9rem', color: 'gray' }}>
        🔙 Previous Input: <strong>{prevInputRef.current}</strong>
      </p>

      {/* Action buttons */}
      <div style={{ display: 'flex', gap: '1rem', marginBottom: '1rem' }}>
        <button onClick={handleAddTask}>Add Task</button>
        <button onClick={() => inputRef.current?.focus()}>🔍 Focus Input</button>
      </div>

      {/* Task list */}
      <ul>
        {tasks.map((task, index) => (
          <li key={index} style={{ padding: '0.3rem 0' }}>
            ✅ {task}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoAppUseRef;

Sunday, 3 August 2025

Crawl Page And Capture Screenshot PDF


This function does :

  • Full-Page PDF Generation
  • Recursive Internal Link Crawling
  • Content and Metadata Extraction
  • Intelligent Overlay & Popup Handling
  • Auto Scroll to Load Dynamic Content
  • Persistent File & DB Storage
  • User and Context-Aware
  • Timeout and Error Handling

private async crawlPage(
        browser: Browser,
        url: string,
        user: User,
        depth: number,
        visited: Set<string>,
        parent: any,
    ) {
        if (visited.has(url) || depth < 0) return;
        visited.add(url);

        this.logger.log(`🔍 Crawling URL: ${url} (Depth: ${depth})`);

        const existingEntryURL = await this.KnowledgeBaseDetailRepo.findOne({
            where: { url, user: { id: user.id } },
            relations: ['user'],
        });

        const page = await browser.newPage();

        try {
            await page.setUserAgent(
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36',
            );
            await page.setExtraHTTPHeaders({ 'Accept-Language': 'en-US,en;q=0.9' });
            await page.setDefaultNavigationTimeout(60000);
            await page.goto(url, { waitUntil: 'networkidle2' });

            // Reject cookie popups
            const rejectButtonSelectors = [
                '[id*="reject"]', '[id*="deny"]', '[id*="decline"]',
                '[class*="reject"]', '[class*="deny"]', '[class*="decline"]',
                'button:text("Reject")', 'button:text("Deny")', 'button:text("Decline")',
                'button:text("Manage preferences")'
            ];
            for (const selector of rejectButtonSelectors) {
                try {
                    const button = await page.waitForSelector(selector, { timeout: 2000 });
                    if (button) {
                        await button.click();
                        this.logger.log(`✅ Rejected popup on ${url}`);
                        break;
                    }
                } catch { }
            }

            // Scroll entire page to trigger lazy loading
            await page.evaluate(async () => {
                const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
                let totalHeight = 0;
                const distance = 500;
                while (totalHeight < document.body.scrollHeight) {
                    window.scrollBy(0, distance);
                    await delay(500);
                    totalHeight += distance;
                }
            });

            // Remove sticky/fixed overlays
            await page.evaluate(() => {
                const elements = Array.from(document.querySelectorAll('*')) as HTMLElement[];

                // Remove cookie overlays and full-screen modals
                const overlaySelectors = [
                    '[class*="overlay"]', '[id*="overlay"]',
                    '.popup', '.modal', '[class*="cookie"]', '[id*="cookie"]',
                    '[class*="consent"]', '[id*="consent"]'
                ];
                overlaySelectors.forEach(selector => {
                    document.querySelectorAll(selector).forEach(el => el.remove());
                });

                // Ensure sticky headers are visible (don't forcibly un-stick)
                const headers = document.querySelectorAll('header') as NodeListOf<HTMLElement>;
                headers.forEach(header => {
                    header.style.position = 'relative';
                    header.style.top = '0';
                    header.style.left = '0';
                    header.style.width = '100%';
                    header.style.zIndex = '9999';
                    header.style.display = 'block';
                    header.style.visibility = 'visible';
                    header.style.opacity = '1';
                });               
            });

            await page.evaluate(() => window.scrollTo(0, 0));
            await new Promise(res => setTimeout(res, 2000));
                     
            const pdfBuffer: Buffer = Buffer.from(await page.pdf({
                format: 'A4',
                printBackground: true,
                // margin: { top: '20px', bottom: '20px', left: '20px', right: '20px' },
            }));

            // Metadata
            const title = await page.title();
            const content = await page.evaluate(() => document.body?.innerText || '');
            const language = langdetect.detectOne(content.slice(0, 5000)) || 'unknown';
            const safeTitle = (title || 'page').replace(/[^a-zA-Z0-9-_]/g, '_').slice(0, 300);
            const filename = `${safeTitle}.pdf`;
            const folderName = user?.id?.toString();
            const pdfDir = path.resolve(__dirname, '..', '..', 'screenshots', folderName);
            if (!fs.existsSync(pdfDir)) fs.mkdirSync(pdfDir, { recursive: true });
            const pdfPath = path.join(pdfDir, filename);

            // Save PDF and entry
            if (!existingEntryURL) {
                fs.writeFileSync(pdfPath, pdfBuffer);
                this.logger.log(`📄 PDF saved at: ${pdfPath}`);

                await this.KnowledgeBaseDetailRepo.save(
                    this.KnowledgeBaseDetailRepo.create({
                        url,
                        title,
                        content,
                        language,
                        s3path: pdfPath,
                        status: true,
                        uploadDocument: false,
                        user,
                        parent,
                    }),
                );
                this.logger.log(`✅ Saved crawl entry for ${url}`);
            }

            // Recursive crawl internal links
            if (depth > 0) {
                const internalLinks: string[] = await page.evaluate((currentUrl) => {
                    const anchors = Array.from(document.querySelectorAll('a[href]'));
                    return anchors
                        .map(a => a.getAttribute('href'))
                        .filter(Boolean)
                        .map(href => {
                            try {
                                return new URL(href!, currentUrl).href;
                            } catch {
                                return null;
                            }
                        })
                        .filter(href => href && href.startsWith(new URL(currentUrl).origin))
                        .map(href => href!.split('#')[0])
                        .filter((v, i, self) => self.indexOf(v) === i);
                }, url);

                for (const link of internalLinks) {
                    if (!visited.has(link)) {
                        await this.crawlPage(browser, link, user, depth - 1, visited, parent);
                    }
                }
            }

        } catch (error) {
            this.logger.warn(`⚠️ Error crawling ${url}: ${error.message}`);
        } finally {
            await page.close();
        }
    }

Wednesday, 22 January 2025

Git commands


Git commands : 

1. Git configuration :

git config --global user.name "<Your-Full-Name>" // Sets your name for all Git repositories.

git config --global user.email "<your-email-address>" // Sets your email for all Git repositories.

2. Git repository management :

git init // Initializes a new Git repository in the current directory.

git clone <url> // Clones a repository from a remote URL.

3. File status and staging :

git status // Displays the status of the working directory and staging area.

git add . // Stages all changes (new files, modifications, and deletions) for commit.

git commit -m 'message' // Commits the staged changes with a descriptive message.

4. Pushing changes :

git push // Pushes local commits to the remote repository.

5. Branching and switching branches:

git branch <branch-name> // Creates a new branch locally.

git checkout <branch-name> // Switches to an existing branch.

git checkout -b <branch-name> // Creates and switches to a new branch.

git merge <branch-name> // Merges the specified branch into the current branch.

6. Fetching and pulling changes :

git pull // Fetches and merges changes from the remote repository to your local repository.

7. Commit history and differences :

git log // Displays the commit history of the repository.

git diff // Shows the differences between files or commits.

8. Resetting changes :

git reset // Resets changes to the last commit or a specific state (e.g., git reset HEAD <file> to unstage changes).

git reset --hard // Resets the working directory and staging area to the last commit (losing local changes).

9. git stash :

git stash // Saves all uncommitted changes (tracked files only). Resets your working directory to the last committed state.

Tuesday, 21 January 2025

Docker: Accelerated Container Application Development

 

Docker: Accelerated Container Application Development

1. Developers can deploy, run, and manage applications.

2. Deploy applications quickly.

3. Docker is a containerization platform that simplifies the process of deploying and managing applications. Applications run along with their dependencies. 

Docker Images :

1. A copy of our project.

2. Images are made from source code, libraries, and external dependencies.

3. Images are created from source code.

4. Example: Node setup, application code, installed libraries, Docker files.

5. Once an image is created, it cannot be updated; we can create a new image instead.

Docker Container :

1. A container runs applications using images.

2. Containers run independently.

3. Example: If 3 images are available, all these images can run independently.  

Docker Commands :

1. docker build -t folder/dockername . // Creates a project image.

2. docker run -p 5000:5000 -d dockerImageName // Runs a container.

3. docker ps // Shows all running containers.

4. docker logs container_id // Displays project logs.

5. docker image prune // Removes unused images.

6. docker service scale web-app=2 // Scales the web-app service to two replicas.

7. docker service update --image <new-image> service_name // Updates a Docker container's image without causing downtime. 

Docker File Example :

1. Create a file named Dockerfile in the root directory of your backend project.

2. In this Dockerfile, write the following code:

# Use Node.js version 20 as the base image
FROM node:20  

# Set the working directory inside the container
WORKDIR /node-practical  

# Copy package.json and package-lock.json to the working directory
COPY package*.json ./  

# Install dependencies
RUN npm install  

# Copy the entire project to the container
COPY . .  

# Specify the command to run the application
CMD ["node", "index.js"]

3. Here’s an example of a docker-compose.yml file for a microservices architecture:

    docker-compose.yml Example : 

version: '3.9'
services:
  db:
    image: postgres:14-alpine
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: DBPass@123
      POSTGRES_DB: DBNAME
      POSTGRES_HOST_AUTH_METHOD: trust        
     
  gateway:
    build:
      dockerfile: Dockerfile
      context: ./gateway
    command: npm run start:prod
    restart: always  
    ports:
      - "5000:5000"
    depends_on:
      - db      
    environment:
      JWT_SECRET: secret@123
      JWT_EXPIRESIN: 2d
      REDIS_HOST: localhost
      REDIS_PORT: 6379
      REDIS_DB: TestFinAssetMgmt //if use redis
    volumes:          
      - /gateway/src/app/node_modules
 
  auth:
    build:
      dockerfile: Dockerfile
      context: ./auth
    command: npm run start:prod
    restart: always
    ports:
      - "5100:5100"
    depends_on:
      - db      
    environment:
      DB_TYPE : postgres
      DB_HOST : HOST_name
      DB_PORT : 5432
      DB_USERNAME : DBUSERNAME
      DB_PASSWORD : DB PASS
      DB_DATABASE : DBDATABASENAME
      DB_SYNC : true
      JWT_SECRET : secret@123
      JWT_EXPIRESIN : 2d
      RESET_PASSWORD_URL : http://3.15.153.226:3000
    volumes:          
      - /auth/src/app/node_modules

  mail:
    build:
      context: ./mail
    command: npm run start:prod
    restart: always
    ports:
      - "5200:5200"
    depends_on:
      - db
      - auth
      - gateway      
    environment:
      EMAIL_HOST : smtp.gmail.com
      EMAIL_USER : SMTP-email-pass
      EMAIL_PASSWORD : smtp-password
    volumes:          
      - /mail/src/app/node_modules



Gmail : SMTP : Simple Mail Transfer Protocol

Gmail : SMTP : Simple Mail Transfer Protocol

1. Go to google Gmail account setting 

    → Go to Forwarding and POP/IMAP 

    → Enabled IMAP access.

2. After go to : manage your google account 

    → Go to security page 

    → Less secure option is enable

3. Email smtp setting : 

    → Server name : smtp.gmail.com ,

    → Port : 587 for Gmail account,

    → Username and password google account

    → Sender name enter 

    → Save 

 

AWS SES : Simple Email Service

 


AWS SES : Simple Email Service

1. Download access key and secret key excel file.

2. Go to verified identity -> Create Identity -> Verify email received in email account and verified.

3. npm install aws-sdk

const AWS = require("aws-sdk");

const awsConfig = {
  accessKeyId: AWS_ACCESS_KEY_ID,
  secretAccessKey: AWS_SECRET_ACCESS_KEY,
  region: process. AWS_REGION,
};

const SES = new AWS.SES(awsConfig);

const sendEmail = async () => {

  try {
    //prepare email to send

    const params = {
      Source: "verifiedemailaddress@gmail.com"  //verified email address
      Destination: {
        ToAddresses: "to@gmail.com",
      },
      Message: {
        Subject: {
          Charset: "UTF-8",
          Data: "OTP Verification",
        },
        Body: {
          Html: {
            Charset: "UTF-8",
            Data: `<h1>Your verification code is 12345</h1>`,
          },
        },
      },
    };

    const emailSent = SES.sendEmail(params).promise();
    emailSent
      .then((data) => {
        console.log(data);
      })
      .catch((err) => {
        console.log(err);
      });
  } catch (error) {
    console.log(error);
  }
};

module.exports = sendEmail;

Difference between MySQL and PostgreSQL

 


Difference between MySQL and PostgreSQL.

1. MySQL:

    Relational database.

    Case-insensitive.

    Limited basic data type support.

    Uses indexes: R, B, Hash.

    Concurrency control.

2. PostgreSQL:

    Object-relational database (DB).

    Case-sensitive.

    Advanced data type support.

    Multiple types of indexes.

    Multiversion concurrency control (MVCC).

JavaScript Hoisting


JavaScript Hoisting :

1. Functions, variables, and class definitions are hoisted to the top.

2. let and const are initialized only after they are used.

3. The most important concepts in JavaScript.

4. To avoid bugs, always declare all variables at the beginning of every scope.

Monday, 20 January 2025

Pure and Impure Functions in JavaScript.

 

JavaScript Pure and Impure Functions.

1. JavaScript Pure Functions.

    JavaScript Pure Function Without modifying value return. like predictable out value.

function add(x) {
    return x + 1;
}
console.log(add(10)); // output : 11
console.log(add(11)); // output : 12
console.log(add(12)); // output : 13

2. JavaScript Impure Functions. 

    JavaScript Impure Function value is change every time.

let x = 10;
function add() {
    return x++;
}
console.log(add()); // output : 10
console.log(add()); // output : 11
console.log(add()); // output : 12

JavaScript Spread and Rest Operators.

 


JavaScript Spread and Rest Operators.

1. JavaScript Spread Operator.

    JavaScript spread operator used for modifying or merging array.    

let a = [1,2,3,3];
let b = [4,5,6,7,3];

let output = [...a, ...b];
console.log('output--->', output);
// output : output---> [1, 2, 3, 3, 4, 5, 6, 7, 3]

2. JavaScript Rest Operator.

    JavaScript Rest Operator used for We don't know the number of parameters come in the function.

function call(...data) {
    console.log('data---->', data);    
}
call(1,2,3,4,5);
// output : data----> [ 1, 2, 3, 4, 5 ]

JavaScript Closures, Callbacks and Callback Hell, Currying.



JavaScript Closures, Callbacks and Callback Hell, Currying Function.

1. JavaScript Closures.

   Closures is the combination of a bundled function.

   Closures gives you access to an outer function's scope from an inner function.

function init() {
    var name = 'Mozilla';
    function displayName() {
        console.log('name --->', name);
        // output : name ---> Mozilla
    }
    displayName();
}
init();

2. JavaScript Callbacks.

   Function passed as an argument.

   
function test1(name, callback) {
    console.log('name---->', name);    
    callback();    
}

function test2() {
    console.log('test2---->');    
}

test1("Ankit", test2);
//output :
// name----> Ankit
// test2---->

3. JavaScript Callback Hell.

   Every callback depends / waits for the previous callback.

setTimeout(() => {
    console.log('test 1--->');
    setTimeout(() => {
        console.log('test 2--->');
    }, 2000);    
}, 5000);
// output :
// test 1--->
// test 2--->

4. JavaScript Currying Function.

function sendEmail(to) {
    return function (from) {
        return function (body) {            
            return to + ' - ' + from + ' - ' + body;
        }
    }
}

let to = sendEmail('to@gmail.com');
let from = to('from@gmail.com');
console.log(from('Body data'));
// output : to@gmail.com - from@gmail.com - Body data.

function sendEmail(to) {
    return function (from) {
        return function (body) {            
            return to + ' - ' + from + ' - ' + body;
        }
    }
}

console.log(sendEmail('to@gmail.com')('from@gmail.com')('Body data.'));
// output : to@gmail.com - from@gmail.com - Body data.

//using arrow function
const sendemail = (to) => (from) => (body) => { return to + ' - ' + from + ' - ' + body};
console.log('sendemail--->', sendemail('to@gmail.com')('from@gmail.com')('Body data.'));
// output : sendemail---> to@gmail.com - from@gmail.com - Body data.