Why is Next.js shipping 1.3MB of JavaScript for a simple static page?

I’ve just started a new Next.js project, and I’m puzzled about why so much JavaScript is being shipped for a static page that has no interactivity. Here are the steps I followed:

  1. npx create-next-app@latest app
  2. create a simple page at src/app/welcome/page.tsx
export default function Welcome() {
    return <p>welcome</p>;
}
  1. run the development server and visit http://localhost:3000/welcome
  2. open network tab and see 1.3MB of main-app.js is being sent

Why is all this JavaScript being sent when the page has no interactivity? I would expect minimal to no JavaScript for such a static page. I’m totally new to SSR, but this seems like no javascript by default should be sent for this type of page. Any insights would be appreciated!

How to save as Blob the displayed image with object-fit: cover property

I have an image in my Vue.js component with the following HTML:

<img :src="thumbnail" style="height: 165px; width: 290px; object-fit: cover;">

The image is displayed with the object-fit: cover CSS property. I need to capture and save exactly what is shown on the page (with the cropping effect) as a Blob using JavaScript.

I’ve searched online for solutions, but I haven’t been able to find anything useful.

Any help or examples would be greatly appreciated!

Why is this code not checking the validity of the passcode?

**This is the HTML Part**

    <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>
</head>
<body style="background-color: rgb(0, 255, 195); text-align: center">
    <div id="display">
        <p style="color:black">Enter your Passcode:</p>
        <input id="passcode" type = "password">
        <button onclick="checkValidity()">Enter↵</button>
    </div>
    <script src = "script.js"></script>
</body>
</html>

**This is the JAVASCRIPT Part**
const Pass = '2207'

function checkValidity(){
    const pass_code = document.getElementById("passcode").value;
    if (pass_code == Pass){
        alert("Correct Passcode!");
    }

    else{
        alert("Wrong Passcode!");
    }
}

*****The checkValidity function does not work and there is no alert dialogue box that appears, I want so that the passcode entered by the user is compared with the constant “Pass” *****

EventListener doesn’t work after clicking form button in iframe

I have the code to close form when clicking button inside iframe:

<!DOCTYPE html>
<html lang="en-US" prefix="og: http://ogp.me/ns#">
   <head>
      <script>
         $(document).ready(function(){
    $("#popup1").hide();
});
window.onload=function(){
    document.getElementById("popup1").contentWindow.document.getElementById("hidepopout").addEventListener("click", PopUpHide, false);
function PopUpHide(){
    $("#popup1").hide();
    document.getElementById("popup1").contentWindow.document.getElementById("form").reset();
}
}
      </script>
   </head>
   <body>
      <iframe class="b-popup" id="popup1" src="index2.php" title="contact form">
      </iframe>
            <button onclick="PopUpShow()">Contact me</button>
            <script>
            function PopUpShow(){
    $("#popup1").show();
}
            </script>
         </main>
         <footer></footer>
      </div>
   </body>
</html>

index2.php – iframe content with button

<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    
    <link rel="stylesheet" href="../CSS/Form.css">

    <title>Contact Us</title>
</head>

<body>

                    <?php
                    if (!empty($success)) {
                        ?>
                        <div class="alert alert-success">Your message was sent successfully!</div>
                        <?php
                    }
                    ?>

                    <?php
                    if (!empty($error)) {
                        ?>
                        <div class="alert alert-danger"><?= $error ?></div>
                        <?php
                    }
                    ?>
                    <button id="hidepopout">&#10006;</button>
                    <form id="form" method="post" action="submit.php">

                        <button id="sendmsg" class="btn btn-primary btn-block">Send Message</button>
                    </form>
</body>
</html>

The button doesn’t hide iframe, if I click on form button with id “sendmsg”. Looks like there is no event handler in that case. But it works if I don’t touch this button.

How do I import a module I made into my JS code that is a script in HTML?

I want to import a module that I made

Okay so I made a simple little thing to test it that doesn’t really DO anything except confirm if it works…which it doesn’t.

here’s my “module” (testmodule.js):

export class Test {
    static printTest() {
        console.log("it works");
    }
}

I added a line in my HTML file importing it as a module

<!doctype html>
<html>
    <head>
    </head>
    <body>
        <script type="module" src="testmodule.js"></script>
        <script src="script.js"></script>
    </body>
</html>

and then I tried using the function in my js (script.js):

Test.printTest();

and that gave me the error: Uncaught ReferenceError: Test is not defined
http://0.0.0.0:8000/script.js:1

so I tried importing it in my script. updated script.js:

import Test from "moduletest";
Test.printTest();

and that gave me the error: Uncaught SyntaxError: import declarations may only appear at top level of a module
I also tried writing the import command a different way I don’t remember what that was but it gave me that same error

Typescript type for converting array of objects to an object with keys in array objects

interface Item {
  slug: string;
  description: string;
}

interface Params {
  id: number;
  items: Item[];
}

function test(params: Params) {
  const result = {};
  
  for (const item of params.items) {
    result[item.slug] = "Hello";
  }
  
  return result;
}


const data = {
  id: 3,
  items: [
    { slug: "one", description: "This is one" },
    { slug: "two", description: "This is two" },
    { slug: "three", description: "This is three" },
  ]
}

const final = test(data)

OK. I have data and pass it to the test function. The test function returns an object with keys as the value of slugs in the items and a string value. So I want the type of final variable to be like this:

{
  one: string;
  two: string;
  three: string;
}

and not this:

Record<string, string>

I mean it must extract slug values from items and create an object with it. explicitly tell the type. How can I define the return type of test function to achieve this?
thanks.

How to properly clone a Date in Typescript

I have the following function that must clone a class (this) and return a new clone of it. In this case the class is called Tag

clone(): Tag {
        // Create a new instance of Tag
        let newItem = new Tag();

        newItem.id = this.id;
        newItem.userId = this.userId;
        newItem._tag = this._tag;
        newItem._color = this._color;
        
        // deep copy of Date objects
        newItem._createdOn =  new Date(this._createdOn.valueOf());
        newItem._updatedOn =  new Date(this._updatedOn.valueOf());
        newItem._archivedOn = this._archivedOn ? new Date(this._archivedOn.getTime()) : undefined;
        
        return newItem;
    }

In the accompanying Unit Test, I test for equality in the clone

describe("clone", () => {
        it("should create an identical copy of the tag", () => {
            const userId = uuidv4();
            let tag = fakeTag(userId);
            
            const clone = tag.clone();
            
            expect(clone.id).toEqual(tag.id);
            expect(clone.userId).toEqual(tag.userId);
            expect(clone.tag).toEqual(tag.tag);
            expect(clone.color).toEqual(tag.color);

// Errors appear here 
expect(clone.updatedOn.getTime()).toBeCloseTo(tag.updatedOn.getTime(), 2);
            expect(clone.createdOn.getTime()).toBeCloseTo(tag.createdOn.getTime(), 2);
        });
    });

Everything works until

expect(clone.updatedOn.getTime()).toBeCloseTo(tag.updatedOn.getTime(), 2);

This is the test output

expect(received).toBeCloseTo(expected, precision)

Expected: 1728162863968
Received: 1728241129040

Expected precision:    2
Expected difference: < 0.005
Received difference:   78265072

I have also tried the following to no avail

expect(clone.updatedOn.getTime()).toEqual(tag.updatedOn.getTime());

I have read quite a few Date clone S/O texts, but I don’t get why I’m still getting this error. There is something I’m doing wrong

Exporting a const from an external file to use in ReactSearchAutocomplete doesn’t work

I’m building a Pokémon team generator and the user should be able to use ReactSearchAutocomplete before I fetch data from an external API. I wrote an external file including information like pokemon name and id, it looks like this:

const pokemonlist = [
  {
    name: "bulbasaur",
    id: 1,
  },
  {
    name: "ivysaur",
    id: 2,
  },
  {
    name: "venusaur",
    id: 3,
  },
  {
    name: "terapagos",
    id: 1024,
  },
  {
    name: "pecharunt",
    id: 1025,
  },
];

export default pokemonlist;

Since the file is more than 4100 lines long I shortened it here so that it’s easier to read for you.

In my second file for the actual Searchbar Component I wrote this:

import pokemonlist from "./pokemon/pokemonlist";
import { ReactSearchAutocomplete } from "react-search-autocomplete";

export default function SearchbarAutocomplete() {
  
  const handleOnSearch = (string, results) => {
    // console.log(string, results);
  };

  const handleOnHover = (result) => {
    console.log(result);
  };

  const handleOnSelect = (item) => {
    console.log(item);
  };

  const handleOnFocus = () => {
    // console.log("Focused");
  };

  const formatResult = (item) => {
    return (
      <>
        <span style={{ display: "block", textAlign: "left" }}>
          #{item.id} {item.name}
        </span>
      </>
    );
  };

  return (
    <ReactSearchAutocomplete
      items={pokemonlist}
      onSearch={handleOnSearch}
      onHover={handleOnHover}
      onSelect={handleOnSelect}
      onFocus={handleOnFocus}
      autoFocus
      formatResult={formatResult}
      placeholder="Search Pokemon"
    />
  );
}

Doing it like this the pokemonlist is not found. There’s no error in my console but I get the fallback “No results”. I also tried using a named export, same thing happens.

If I place the const inside the SearchbarAutocomplete function, everything works as expected, it looks like this:

import pokemonlist from "./pokemon/pokemonlist";
import { ReactSearchAutocomplete } from "react-search-autocomplete";

export default function SearchbarAutocomplete() {

const pokemonlist = [
  {
    name: "bulbasaur",
    id: 1,
  },
  {
    name: "ivysaur",
    id: 2,
  },
  {
    name: "venusaur",
    id: 3,
  },
  {
    name: "terapagos",
    id: 1024,
  },
  {
    name: "pecharunt",
    id: 1025,
  },
];
  
  const handleOnSearch = (string, results) => {
    // console.log(string, results);
  };

  const handleOnHover = (result) => {
    console.log(result);
  };

  const handleOnSelect = (item) => {
    console.log(item);
  };

  const handleOnFocus = () => {
    // console.log("Focused");
  };

  const formatResult = (item) => {
    return (
      <>
        <span style={{ display: "block", textAlign: "left" }}>
          #{item.id} {item.name}
        </span>
      </>
    );
  };

  return (
    <ReactSearchAutocomplete
      items={pokemonlist}
      onSearch={handleOnSearch}
      onHover={handleOnHover}
      onSelect={handleOnSelect}
      onFocus={handleOnFocus}
      autoFocus
      formatResult={formatResult}
      placeholder="Search Pokemon"
    />
  );
}

But >4000 lines of text… I’d really like to separate these information from my actual code. Can you help me here please? What do I miss?

Passing cookies through routes Nodejs express

I have an server and i use jws to generate a token and the store it in a cookie, but when i try to authenticate the router cant find the cookie it just returns undefined

Express router

const { adminAuth } = require("../middleware/auth");
router.route("/deleteUser").delete(adminAuth, deleteUser);

middleware/auth

exports.adminAuth = (req, res, next) => {
  console.log(req.cookies);
  const token = req.cookies.jwt;
  if (token) {
    jwToken.verify(token, jwtSecret, (err, decodedToken) => {
      if (err) {
        return res.status(401).json({ message: "Not authorized" });
      } else {
        if (decodedToken.role !== "admin") {
          return res.status(401).json({ message: "Not authorized" });
        } else {
          next();
        }
      }
    });
  } else {
    return res
      .status(401)
      .json({ message: "Not authorized, token not available" });
  }
};

I have checked that the adminAuth works it just dont work when i access it through the router. i where expecting that it would just pass through the router but aprently the cookies does not

Cannot send message to SQS from AWS Lambda function

I have a Lambda function that has some data and must send it to a SQS queue. But it seems like the send is not working. There is no error and it seems to gracefully continue execution without any message being sent. Here is my Lambda code:

  //JavaScript

  import { SendMessageCommand, SQSClient } from "@aws-sdk/client-sqs";
  
  const message = {
    label: "test",
  };

  const client = new SQSClient({});
  const SQS_QUEUE_URL = "https://sqs.us-east-1.amazonaws.com/...";

  const send = async (message, sqsQueueUrl = SQS_QUEUE_URL) => {
    const command = new SendMessageCommand({
      QueueUrl: sqsQueueUrl,
      DelaySeconds: 5,
      MessageAttributes: {
        Label: {
          DataType: "String",
          StringValue: message.label,
        },
      },
      MessageBody:
        "Sent test data to SQS queue",
    });
    console.log("Test");
    const response = await client.send(command);
    console.log(response);
    return response;
  };
  
send(message, SQS_QUEUE_URL);

Viewing the logs on CloudWatch, I can see the “Test” message being printed, but not the response. I have other things after the send(...), all that code works, it’s just the send(...) that isn’t doing anything. My runtime is Node.js 20.x.

I have already attached a policy to provide full SQS access for my Lambda function. I also included the region when initializing the client, didn’t seem to make a difference.

How to generate a burndown chart from a burnup chart?

I am trying to replicate the effect of the burndown chart in the picture of action items which rely upon different fields, called Estimated Completion Date, Original Due Date, and Closed Date, and use them for Risk Mitigation events. I have a list of mitigation events for view and they use Baseline Date ( which corresponds to Original Due Date) and Closed Date which translates to Actual Completion Date for my table. I will have 3 series instead of 4.

As the burndown shows, cumulative effect is seen in the total open action items, which in my desired case which is correct.

What do I need to do to produce the effect in the burndown? The effect is when there is no change in the events based on Baseline Date or based on Actual Date, then their graph rises provided there are accumulating items, an when the actual data shows a date then the series starts to decline, which is done by subtracting from the total mitigation events for that date.

I’m getting a non decreasing graph for the burndown which doesn’t replicate the desired behavior.

Thank you for helping.

Desired Chart from Example
Desired Chart

Current Model
https://jsfiddle.net/4ums7o19/

Shortened Snippet

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Buildup and Burndown Charts</title>
        <!-- Include D3.js -->
        <script src="https://d3js.org/d3.v6.min.js"></script>
        <style>
            body {
                font-family: Arial, sans-serif;
            }
            .chart-container {
                margin: 50px;
            }
            .axis-label {
                font-size: 12px;
                font-weight: bold;
            }
            .legend {
                font-size: 12px;
            }
            .line {
                fill: none;
                stroke-width: 2px;
            }
        </style>
    </head>
    <body>
        <div class="chart-container">
            <h2>Buildup Chart</h2>
            <svg id="buildupChart" width="900" height="500"></svg>
        </div>

        <div class="chart-container">
            <h2>Burndown Chart</h2>
            <svg id="burndownChart" width="900" height="500"></svg>
        </div>

        <script>
            (function() {
                // -------------------------------
                // 2. Parse and Preprocess the Data
                // -------------------------------
                const parseDate = d3.timeParse("%Y-%m-%d");
                const eventsData = [
            {
                "eventid": 1,
                "riskid": null,
                "eventtitle": "Component Sourcing",
                "eventstatus": "Complete",
                "eventownerid": 1,
                "actualdate": "2024-09-01",
                "actuallikelihood": 4,
                "actualtechnical": 5,
                "actualschedule": 3,
                "actualcost": 4,
                "baselinedate": "2024-09-01",
                "baselinelikelihood": 4,
                "baselinetechnical": 5,
                "baselineschedule": 3,
                "baselinecost": 4,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 2,
                "riskid": null,
                "eventtitle": "Supplier Negotiation",
                "eventstatus": "Complete",
                "eventownerid": 1,
                "actualdate": "2024-09-25",
                "actuallikelihood": 3,
                "actualtechnical": 5,
                "actualschedule": 4,
                "actualcost": 4,
                "baselinedate": "2024-09-05",
                "baselinelikelihood": 3,
                "baselinetechnical": 5,
                "baselineschedule": 4,
                "baselinecost": 4,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 3,
                "riskid": null,
                "eventtitle": "Component Delivery",
                "eventstatus": "Complete",
                "eventownerid": 1,
                "actualdate": "2024-10-10",
                "actuallikelihood": 2,
                "actualtechnical": 3,
                "actualschedule": 2,
                "actualcost": 2,
                "baselinedate": "2024-09-10",
                "baselinelikelihood": 2,
                "baselinetechnical": 3,
                "baselineschedule": 2,
                "baselinecost": 2,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 1,
                "riskid": null,
                "eventtitle": "Integration Testing",
                "eventstatus": "Complete",
                "eventownerid": 2,
                "actualdate": "2024-09-05",
                "actuallikelihood": 5,
                "actualtechnical": 4,
                "actualschedule": 4,
                "actualcost": 3,
                "baselinedate": "2024-09-05",
                "baselinelikelihood": 5,
                "baselinetechnical": 4,
                "baselineschedule": 4,
                "baselinecost": 3,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 1,
                "riskid": null,
                "eventtitle": "Machinery Maintenance",
                "eventstatus": "Complete",
                "eventownerid": 3,
                "actualdate": "2024-09-02",
                "actuallikelihood": 3,
                "actualtechnical": 4,
                "actualschedule": 5,
                "actualcost": 4,
                "baselinedate": "2024-09-02",
                "baselinelikelihood": 3,
                "baselinetechnical": 4,
                "baselineschedule": 5,
                "baselinecost": 4,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 2,
                "riskid": null,
                "eventtitle": "Operational Check",
                "eventstatus": "Baseline",
                "eventownerid": 3,
                "actualdate": null,
                "actuallikelihood": null,
                "actualtechnical": null,
                "actualschedule": null,
                "actualcost": null,
                "baselinedate": "2024-09-30",
                "baselinelikelihood": 2,
                "baselinetechnical": 3,
                "baselineschedule": 3,
                "baselinecost": 3,
                "scheduledate": "2024-09-30",
                "scheduledlikelihood": 2,
                "scheduledtechnical": 3,
                "scheduledschedule": 3,
                "scheduledcost": 3
            },
            {
                "eventid": 3,
                "riskid": null,
                "eventtitle": "Final Review",
                "eventstatus": "Baseline",
                "eventownerid": 6,
                "actualdate": null,
                "actuallikelihood": null,
                "actualtechnical": null,
                "actualschedule": null,
                "actualcost": null,
                "baselinedate": "2024-10-31",
                "baselinelikelihood": 2,
                "baselinetechnical": 1,
                "baselineschedule": 2,
                "baselinecost": 1,
                "scheduledate": "2024-10-31",
                "scheduledlikelihood": 2,
                "scheduledtechnical": 2,
                "scheduledschedule": 2,
                "scheduledcost": 1
            },
            {
                "eventid": 1,
                "riskid": null,
                "eventtitle": "Worker Adjustment",
                "eventstatus": "Complete",
                "eventownerid": 5,
                "actualdate": "2024-09-03",
                "actuallikelihood": 4,
                "actualtechnical": 3,
                "actualschedule": 5,
                "actualcost": 4,
                "baselinedate": "2024-09-03",
                "baselinelikelihood": 4,
                "baselinetechnical": 3,
                "baselineschedule": 5,
                "baselinecost": 4,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 2,
                "riskid": null,
                "eventtitle": "Strike Negotiation",
                "eventstatus": "Complete",
                "eventownerid": 5,
                "actualdate": "2024-09-05",
                "actuallikelihood": 3,
                "actualtechnical": 2,
                "actualschedule": 1,
                "actualcost": 3,
                "baselinedate": "2024-09-10",
                "baselinelikelihood": 3,
                "baselinetechnical": 2,
                "baselineschedule": 1,
                "baselinecost": 3,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 1,
                "riskid": null,
                "eventtitle": "Regulatory Submission",
                "eventstatus": "Complete",
                "eventownerid": 6,
                "actualdate": "2024-09-04",
                "actuallikelihood": 3,
                "actualtechnical": 2,
                "actualschedule": 4,
                "actualcost": 5,
                "baselinedate": "2024-09-04",
                "baselinelikelihood": 3,
                "baselinetechnical": 2,
                "baselineschedule": 4,
                "baselinecost": 5,
                "scheduledate": null,
                "scheduledlikelihood": null,
                "scheduledtechnical": null,
                "scheduledschedule": null,
                "scheduledcost": null
            },
            {
                "eventid": 2,
                "riskid": null,
                "eventtitle": "Approval Follow-Up",
                "eventstatus": "Active",
                "eventownerid": 6,
                "actualdate": null,
                "actuallikelihood": null,
                "actualtechnical": null,
                "actualschedule": null,
                "actualcost": null,
                "baselinedate": "2024-09-04",
                "baselinelikelihood": 3,
                "baselinetechnical": 4,
                "baselineschedule": 3,
                "baselinecost": 4,
                "scheduledate": "2024-09-18",
                "scheduledlikelihood": 3,
                "scheduledtechnical": 3,
                "scheduledschedule": 3,
                "scheduledcost": 4
            },
            {
                "eventid": 3,
                "riskid": null,
                "eventtitle": "Regulatory Review",
                "eventstatus": "Active",
                "eventownerid": 6,
                "actualdate": null,
                "actuallikelihood": null,
                "actualtechnical": null,
                "actualschedule": null,
                "actualcost": null,
                "baselinedate": "2024-09-15",
                "baselinelikelihood": 3,
                "baselinetechnical": 4,
                "baselineschedule": 3,
                "baselinecost": 4,
                "scheduledate": "2024-10-09",
                "scheduledlikelihood": 2,
                "scheduledtechnical": 4,
                "scheduledschedule": 4,
                "scheduledcost": 5
            }
        ] 
                const events = eventsData.map(d => ({
                    eventid: d.eventid,
                    eventtitle: d.eventtitle,
                    eventstatus: d.eventstatus,
                    eventownerid: d.eventownerid,
                    actualDate: d.actualdate ? parseDate(d.actualdate) : null,
                    baselineDate: d.baselinedate ? parseDate(d.baselinedate) : null,
                    scheduledDate: d.scheduledate ? parseDate(d.scheduledate) : null
                }));

                // -------------------------------
                // 3. Prepare Data for Buildup Chart
                // -------------------------------
                // Collect all dates with their types
                let buildupDates = [];
                events.forEach(event => {
                    if (event.actualDate) {
                        buildupDates.push({ date: event.actualDate, type: 'actual' });
                    }
                    if (event.baselineDate) {
                        buildupDates.push({ date: event.baselineDate, type: 'baseline' });
                    }
                    // You can include scheduled dates if needed
                });

                // Sort all dates in ascending order
                buildupDates.sort((a, b) => a.date - b.date);

                // Aggregate cumulative counts
                let cumulativeTotal = 0;
                let cumulativeBaseline = 0;
                let cumulativeActual = 0;

                const buildupDataMap = d3.rollup(
                    buildupDates,
                    v => d3.rollups(v, v => v.length, d => d.type),
                    d => d.date
                );

                // Get a sorted array of unique dates
                const uniqueBuildupDates = Array.from(buildupDataMap.keys()).sort((a, b) => a - b);

                const buildupData = uniqueBuildupDates.map(date => {
                    const typeCounts = buildupDataMap.get(date) || new Map();
                    let actuals = 0;
                    let baselines = 0;

                    typeCounts.forEach(([type, count]) => {
                        if (type === 'actual') actuals += count;
                        if (type === 'baseline') baselines += count;
                    });

                    cumulativeTotal += actuals + baselines;
                    cumulativeActual += actuals;
                    cumulativeBaseline += baselines;

                    return {
                        date: date,
                        total: cumulativeTotal,
                        baseline: cumulativeBaseline,
                        actual: cumulativeActual
                    };
                });

                // -------------------------------
                // 4. Prepare Data for Burndown Chart
                // -------------------------------
                // The burndownData will have:
                // - total: same as buildupData.total
                // - remainingBaseline: buildupData.baseline - buildupData.actual
                // - remainingActual: buildupData.total - buildupData.actual

                const burndownData = buildupData.map(d => {
                    const remainingBaseline = d.baseline - d.actual;
                    const remainingActual = d.total - d.actual;

                    return {
                        date: d.date,
                        total: d.total,
                        remainingBaseline: remainingBaseline >= 0 ? remainingBaseline : 0,
                        remainingActual: remainingActual >= 0 ? remainingActual : 0
                    };
                });

                // -------------------------------
                // 5. Function to Create Buildup Chart
                // -------------------------------
                function createBuildupChart(data) {
                    const svg = d3.select("#buildupChart"),
                        margin = { top: 50, right: 150, bottom: 50, left: 60 },
                        width = +svg.attr("width") - margin.left - margin.right,
                        height = +svg.attr("height") - margin.top - margin.bottom;

                    const g = svg.append("g")
                                .attr("transform", `translate(${margin.left},${margin.top})`);

                    // Set up scales
                    const x = d3.scaleTime()
                                .domain(d3.extent(data, d => d.date))
                                .range([0, width]);

                    const y = d3.scaleLinear()
                                .domain([0, d3.max(data, d => Math.max(d.total, d.baseline, d.actual)) * 1.1])
                                .range([height, 0]);

                    // Define lines
                    const lineTotal = d3.line()
                                        .x(d => x(d.date))
                                        .y(d => y(d.total));

                    const lineBaseline = d3.line()
                                           .x(d => x(d.date))
                                           .y(d => y(d.baseline));

                    const lineActual = d3.line()
                                         .x(d => x(d.date))
                                         .y(d => y(d.actual));

                    // Add X axis
                    g.append("g")
                    .attr("transform", `translate(0,${height})`)
                    .call(d3.axisBottom(x));

                    // Add Y axis
                    g.append("g")
                    .call(d3.axisLeft(y));

                    // Add lines
                    g.append("path")
                    .datum(data)
                    .attr("class", "line")
                    .attr("stroke", "red")
                    .attr("d", lineTotal);

                    g.append("path")
                    .datum(data)
                    .attr("class", "line")
                    .attr("stroke", "#5555dd")
                    .attr("d", lineBaseline);

                    g.append("path")
                    .datum(data)
                    .attr("class", "line")
                    .attr("stroke", "orange")
                    .attr("d", lineActual);

                    // Add Labels
                    g.append("text")
                    .attr("x", width / 2)
                    .attr("y", height + margin.bottom - 10)
                    .attr("text-anchor", "middle")
                    .attr("class", "axis-label")
                    .text("Date");

                    g.append("text")
                    .attr("transform", "rotate(-90)")
                    .attr("x", -height / 2)
                    .attr("y", -margin.left + 15)
                    .attr("text-anchor", "middle")
                    .attr("class", "axis-label")
                    .text("Cumulative Count");

                    // Add Legend
                    const legend = svg.append("g")
                                    .attr("transform", `translate(${width + margin.left + 20},${margin.top})`);

                    const legendData = [
                        { name: "Total Events", color: "red" },
                        { name: "Baseline Events", color: "#5555dd" },
                        { name: "Actual Events", color: "orange" }
                    ];

                    legend.selectAll("rect")
                        .data(legendData)
                        .enter()
                        .append("rect")
                        .attr("x", 0)
                        .attr("y", (d, i) => i * 25)
                        .attr("width", 18)
                        .attr("height", 18)
                        .style("fill", d => d.color);

                    legend.selectAll("text")
                        .data(legendData)
                        .enter()
                        .append("text")
                        .attr("x", 25)
                        .attr("y", (d, i) => i * 25 + 9)
                        .attr("dy", ".35em")
                        .text(d => d.name);
                }

                // -------------------------------
                // 6. Function to Create Burndown Chart
                // -------------------------------
                function createBurndownChart(data) {
                    const svg = d3.select("#burndownChart"),
                        margin = { top: 50, right: 150, bottom: 50, left: 60 },
                        width = +svg.attr("width") - margin.left - margin.right,
                        height = +svg.attr("height") - margin.top - margin.bottom;

                    const g = svg.append("g")
                                .attr("transform", `translate(${margin.left},${margin.top})`);

                    // Set up scales
                    const x = d3.scaleTime()
                                .domain(d3.extent(data, d => d.date))
                                .range([0, width]);

                    const y = d3.scaleLinear()
                                .domain([0, d3.max(data, d => d.total) * 1.1]) // Scale based on total to ensure alignment
                                .range([height, 0]);

                    // Define lines
                    const lineTotal = d3.line()
                                        .x(d => x(d.date))
                                        .y(d => y(d.total));

                    const lineRemainingBaseline = d3.line()
                                            .x(d => x(d.date))
                                            .y(d => y(d.remainingBaseline));

                    const lineRemainingActual = d3.line()
                                            .x(d => x(d.date))
                                            .y(d => y(d.remainingActual));

                    // Add X axis
                    g.append("g")
                    .attr("transform", `translate(0,${height})`)
                    .call(d3.axisBottom(x));

                    // Add Y axis
                    g.append("g")
                    .call(d3.axisLeft(y));

                    // Add lines
                    // Total line (matches Buildup's cumulative total)
                    g.append("path")
                    .datum(data)
                    .attr("class", "line")
                    .attr("stroke", "red")
                    .attr("d", lineTotal);

                    // Remaining Baseline line
                    g.append("path")
                    .datum(data)
                    .attr("class", "line")
                    .attr("stroke", "#5555dd")
                    .attr("d", lineRemainingBaseline);

                    // Remaining Actual line
                    g.append("path")
                    .datum(data)
                    .attr("class", "line")
                    .attr("stroke", "green")
                    .attr("d", lineRemainingActual);

                    // Add Labels
                    g.append("text")
                    .attr("x", width / 2)
                    .attr("y", height + margin.bottom - 10)
                    .attr("text-anchor", "middle")
                    .attr("class", "axis-label")
                    .text("Date");

                    g.append("text")
                    .attr("transform", "rotate(-90)")
                    .attr("x", -height / 2)
                    .attr("y", -margin.left + 15)
                    .attr("text-anchor", "middle")
                    .attr("class", "axis-label")
                    .text("Remaining Open Events");

                    // Add Legend
                    const legend = svg.append("g")
                                    .attr("transform", `translate(${width + margin.left + 20},${margin.top})`);

                    const legendData = [
                        { name: "Total Events", color: "red" },
                        { name: "Baseline Remaining", color: "#5555dd" },
                        { name: "Actual Remaining", color: "green" }
                    ];

                    legend.selectAll("rect")
                        .data(legendData)
                        .enter()
                        .append("rect")
                        .attr("x", 0)
                        .attr("y", (d, i) => i * 25)
                        .attr("width", 18)
                        .attr("height", 18)
                        .style("fill", d => d.color);

                    legend.selectAll("text")
                        .data(legendData)
                        .enter()
                        .append("text")
                        .attr("x", 25)
                        .attr("y", (d, i) => i * 25 + 9)
                        .attr("dy", ".35em")
                        .text(d => d.name);
                }

                // -------------------------------
                // 7. Initialize the Charts
                // -------------------------------
                // Create Buildup Chart
                createBuildupChart(buildupData);

                // Create Burndown Chart
                createBurndownChart(burndownData);
            })();
        </script>
    </body>
    </html>

Line chart rendering based on dynamic duration changes with suffixes

  prTimeToMergeChartOptions : any = comboChartOptions;

  prTimeToMergeChartsOptions(){
    this.prTimeToMergeChartOptions.scales.x.title.text = "duration"
    this.prTimeToMergeChartOptions.scales.y.title.text = "Average time taken to merge pull request"
    this.prTimeToMergeChartOptions.plugins = {
      tooltip: {
        callbacks: {
          title: (data) => { 
            const date = `${this.translation.translate("developmentMetrics.date")}: ${data[0].label}`;
            return date;
          },
          label: (context: any) => {
            let tooltipLines = [];
            if (context.dataset.label.toLowerCase() !== 'average') {
              const appName = `${this.translation.translate("developmentMetrics.application")}: ${context.dataset.label}`;
              tooltipLines.push(appName);
            }
            const valueInDays = context.raw;
            let displayValue;
            if (valueInDays >= 1) {
              displayValue = `${valueInDays.toFixed(1)} days`;
            } else {
              const valueInHours = valueInDays * 24;
              if (valueInHours >= 1) {
                displayValue = `${valueInHours.toFixed(1)} hours`;
              } else {
                const valueInMinutes = valueInHours * 60;
                displayValue = `${valueInMinutes.toFixed(0)} minutes`;
              }
            }
            const yAxisLabelWithSuffix = context.dataset.label.toLowerCase() === 'average'
                                        ? "Average Time to merge"
                                        : "Time to merge";
            const changed = `${yAxisLabelWithSuffix}: ${displayValue}`;
            tooltipLines.push(changed);
            return tooltipLines;
          }
        }
      }
    };
  }

Want to render the chart duration of y axis along with dynamic data with suffixes like Hours, days, and Months based on maxm value present inside of it

Note :
Here context.raw have values coming as days, months and Hours as well
Example : it may come as 2.4 which might be in Days and 7 might be
in Hours and also 3 which might be in months as well

for more details please follow below link :
(https://drive.google.com/file/d/1pMKkneTANw6palN8XnlgfoNVqnzi7H_B/view?usp=drivesdk)

Explicitly clear reference for loop javascript

I am using nodejs and input code as below:

 async batchInsert(
  productList: ProductList[]
 } {
  const productListFilter =
    productList.map((product) => {
        product.createdAt = new Date();
        return product;
    });


    const batchSize = 100;
    const batches = Math.ceil(productList.length / batchSize);

    for (let i = 0; i < batches; i++) {
      const startIndex = i * batchSize;
      const endIndex = (i + 1) * batchSize;
      const batch = productListFilter.slice(startIndex, endIndex);
    }

    return true;
}

Chatgpt suggest me as follow:

Key Strategies for Memory Management
Slice Responsibly:

Use the slice method carefully, as it creates a shallow copy of the array segment. If the array is large, ensure that you release references after processing.

Clear References:
After processing each batch, clear any references to large objects if they are no longer needed.

Batch Length Reset:
After processing each batch with await queryRunner.manager.insert(ProductList, batch);, we reset batch.length = 0;. This explicitly clears the references in the array, making them eligible for garbage collection.

My question is as follow:

  1. Why do I need to explicitly setting batch.length = 0?? Wouldn’t it be clear off and garbage collect on each loop?

  2. Why do i need to explicitly set productListFiltered.length = 0 in finally block? Is it because productListFiltered will not be garbage collect if it failed at catch block?

    async batchInsert(productList: ProductList[]): Promise {
    if (productList.length === 0) {
    return true; // Nothing to insert
    }

         // Create a filtered list without mutating the original products
         const productListFiltered = productList.map((product) => ({
             ...product,
             createdAt: new Date(),
         }));
    
         const batchSize = 100;
         const batches = Math.ceil(productListFiltered.length / batchSize);
    
         const queryRunner = this.dataSource.createQueryRunner();
    
         // Connect and start a transaction
         await queryRunner.connect();
         await queryRunner.startTransaction();
    
         try {
             for (let i = 0; i < batches; i++) {
                 const startIndex = i * batchSize;
                 const endIndex = Math.min(startIndex + batchSize, productListFiltered.length);
                 const batch = productListFiltered.slice(startIndex, endIndex);
    
                 // Perform the batch insert
                 await queryRunner.manager.insert(ProductList, batch);
    
                 // Clear reference to the batch after processing
                 batch.length = 0; // Helps garbage collection
             }
    
             // Commit the transaction
             await queryRunner.commitTransaction();
             return true;
         } catch (error) {
             await queryRunner.rollbackTransaction();
             return false;
         } finally {
             // Release the query runner
             await queryRunner.release();
    
             // Clear references to the filtered list
             productListFiltered.length = 0; // Helps garbage collection
         }
     }