Is it normal for ReadableStream.pipeTo() to close both files?

According to these docs
https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/pipeTo

by default (by not passing preventClose: true) will make the writable stream automatically close when the readable stream closes.

But when does the readble stream close?

I noticed that if I call close() manually I get an error:

const writeFh = await Deno.open(outPath, { write: true, createNew: true });
const readFh = await Deno.open(inputPath, { read: true });
await readFh.readable.pipeTo(writeFh.writable);
readFh.close(); // error: bad resource id

So this means that pipeTo will close the readable stream automatically when there is no more bytes to read? And then if readable stream closes, the writable is automatically closed too, according to the docs above.

React Version problems

I am running to some issues concerning React. i just started a new project and I keep getting this error, which by the way is not showing me which file its coming from:

Cannot read properties of null (reading 'useRef')
TypeError: Cannot read properties of null (reading 'useRef')
at Object.useRef (http://localhost:3000/static/js/bundle.js:10885:25)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:7114:55)
at react-stack-bottom-frame (http://localhost:3000/static/js/bundle.js:31718:18)
at renderWithHooks (http://localhost:3000/static/js/bundle.js:23035:20)
at updateFunctionComponent (http://localhost:3000/static/js/bundle.js:24304:17)
at beginWork (http://localhost:3000/static/js/bundle.js:24922:16)
at runWithFiberInDEV (http://localhost:3000/static/js/bundle.js:20263:14)
at performUnitOfWork (http://localhost:3000/static/js/bundle.js:27507:93)
at workLoopSync (http://localhost:3000/static/js/bundle.js:27401:38)
at renderRootSync (http://localhost:3000/static/js/bundle.js:27385:7)

I tried getting chat gpt’s help to debug but its like I’ve been going in circles because first it tells me that some of the libraries are not compatible with the newest version REACT 19 so i must downgrade then I did that but now the error that shows when I downgrade to version 18 says that some libraries are not compatible with version 18 so I must get 19 again. What can I do to sort this out?

JS in blazor class library not available in app

I created a BCL containing amongst other thins a js file. The file is located in the BCL in wwwroot/scripts. This js should be made available to the blazor app.

The BCL has:

<ItemGroup>
    <Content Include="wwwroot***" CopyToOutputDirectory="Always" />
    <EmbeddedResource Include="wwwroot***" />
</ItemGroup>

The consuming Blazor app:

<ItemGroup>
    <ProjectReference Include="..<abc><abc>.csproj" />
</ItemGroup>

<PropertyGroup>
    <StaticWebAssetBasePath>abc</StaticWebAssetBasePath>
</PropertyGroup>

The script is referenced in the blazor app by:

<script src="scripts/WebView2Bridge.js"></script>

also tried :

<script src="_content/<abc>/WebView2Bridge.js"></script>

In none of the cases the JS is available to the app. I checkec the bin folder of the app, and there it is after rebuild.
I tried adding this to the csproj of the blazor app:

<ItemGroup>
  <Content Update="wwwrootscriptsWebview2Bridge.js">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>

No success.

Any suggestions ?

Having a challenge starting my bun project after running build command

I worked on a project using bun (my first time using bun), and I am struggling to start my project after running the build command.
Anytime I try running bun start this kept happening

$ bun start dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js dist/index.js

And this kept increasing with each retry. For reference, this is what I have on my package.json script.

"scripts": {
   "start": "bun start dist/index.js",
    "dev": "bun --watch src/index.js",
    "test": "bun test",
    "lint": "bun prettier --write .",
    "build": "bun build src/index.js --outdir ./dist"
  },

I have checked my code base and can’t find what might cause it

How to use discriminated union without discriminating

Is there a way to use a discriminated union in TypeScript without discriminating (the following is a React based example, but that is a detail).

Given the following types:

const Options = {
    TYPE_1: 'type1',
    TYPE_2: 'type2',
} as const
type Options = (typeof Options)[keyof typeof Options]

export type Configuration =
    | {
          type: typeof Options.TYPE_1
          componentProps: ComponentType1Properties
          Component: typeof ComponentType1
      }
    | {
          type: typeof Options.TYPE_2
          componentProps: ComponentType2Properties
          Component: typeof ComponentType2
      }

Associated with two react components (again this is totally pretended it’s not interesting the usage of the properties):

// COMPOPONENT 1
type ComponentType1Properties = {
    prop1: string
}
const ComponentType1: React.FC<ComponentType1Properties & { children: ReactNode }> = ({
    children,
    prop1,
}) => {
    return <div className={prop1}>{children}</div>
}
// COMPONENT 2
type ComponentType2Properties = {
    prop2: string
}
const ComponentType2: React.FC<ComponentType2Properties & { children: ReactNode }> = ({
    children,
    prop2,
}) => {
    return (
        <div>
            <p>{prop2}</p>
            {children}
        </div>
    )
}

Why can’t I “merge” the two like this?

export const UnionTypeComponent: React.FC<{
    configuration: Configuration
    children: ReactNode
}> = ({ configuration, children }) => {
    return (
        <configuration.Component {...configuration.componentProps}>
            {children}
        </configuration.Component>
    )
}

TypeScript complains about the fact that the component may not have the proper properties it needs. So I am forced to discriminate the union (please note that each case in the switch is the exact same code as above):

    switch (configuration.type) {
        case Options.TYPE_1: {
            return (
                <configuration.Component {...configuration.componentProps}>
                    {children}
                </configuration.Component>
            )
        }
        case Options.TYPE_2: {
            return (
                <configuration.Component {...configuration.componentProps}>
                    {children}
                </configuration.Component>
            )
        }
    }

P.S.: Of course somewhere I will have the function that creates the proper config discriminating the union type, but again this is a detail:

const getConfig = (type: Options): Configuration => {
    switch (type) {
        case Options.TYPE_1: {
            return {
                type,
                componentProps: { prop1: 'type1' },
                Component: ComponentType1,
            }
        }
        case Options.TYPE_2: {
            return {
                type,
                componentProps: { prop2: 'type2' },
                Component: ComponentType2,
            }
        }
    }
}

Puppeteer not injecting pageNumbers and totalPages using TailwindCSS

I have a TailwindCSS footer. I am trying to use the classes to inject pageNumber and TotalPages on a pdf printed, but I am not getting it right.

I have the Puppeteer API created it display the Vuetify footer correctly but this TailwindCSS one is not displaying.

TailwindCSS footer:

<template>
  <div id="footer-template">
    <div
      class="hidden"
      :id="puppeterId">
      <footer class="border-t">
        <p class="text-xs text-center">
          <span class="pageNumber font-bold text-blue-500" />/<span class="totalPages font-bold text-blue-500" />
        </p>
      </footer>
    </div>
    <footer
      class="w-full mx-auto my-0 p-[22px] flex justify-between"
    >
      <p class="font-sans box-border text-[#003a63] text-[7px]">
        <span class="pageNumber font-bold text-blue-500" />/<span class="totalPages font-bold text-blue-500" />
      </p>
    </footer>
  </div>
</template>

<script setup>
import {
  onMounted,
  toRef,
} from 'vue';

import convertHtmlToImage from '@/utils/convertHtmlToImage';

const props = defineProps({
  puppeterId: {
    required: true,
    type: String,
  },
});

const localId = toRef(props, 'puppeterId');

onMounted(async () => {
  try {
    await convertHtmlToImage({
      sourceSelector: '#footer-template footer',
      targetSelector: `#${localId.value}`,
    });
    const headerAndFooter = document.querySelector('#footer-template footer');
    headerAndFooter.classList.add('hidden');
  } catch (error) {
    console.error('oops, something went wrong');
    console.error(error);
  }
});
</script>

Vuetify footer:

<template>
  <div id="footer-template">
    <footer>
      <p style="font-size: 10px;">Copyright {{ currentYear }} &copy; | My Business (Pty) Ltd</p>
    </footer>
    <div
      class="d-none"
      :id="puppeterId"
    >
      <footer
        style="
        width: 100%;
        margin: 0 auto;
        padding: 0 22px;
        display: flex;
        justify-content: space-between;"
      >
        <div id="copyright-svg-wrapper" style="margin-top: 6px;" />
        <p
          style="
         font-family: sans-serif;
         box-sizing: border-box !important;
         color: #003a63;
         font-size: 7px;"
        >
          <span class="pageNumber" />/<span class="totalPages" style="font-weight: bold;" />
        </p>
      </footer>
    </div>
  </div>
</template>

<script setup>
import convertHtmlToImage from '@/convertHtmlToImage';
import { computed, onMounted, toRef } from 'vue';

const props = defineProps({
  puppeterId: {
    required: true,
    type: String,
  },
});
const currentYear = computed(() => new Date().getFullYear());

const localId = toRef(props, 'puppeterId');

onMounted(async () => {
  try {
    await convertHtmlToImage({
      sourceSelector: '#footer-template footer',
      targetSelector: `#${localId.value} #copyright-svg-wrapper`,
    });
    const headerandFooter = document.querySelector('#footer-template footer');
    headerandFooter.classList.add('d-none');
  } catch (error) {
    console.error('oops, somthing went wrong');
    console.error(error);
  }
});

</script>

Webpack Configuration

I have folder structure like below

temp
  |- package.json
  |- package-lock.json
  |- webpack.config.js
  |- /src
    |- /components
        |- /button1.js
        |- /button2.js
    |- /id_selectors.js
    |- /index.js
  |- /templates
    |- index.js
  |- /dist
    |- final.js
  |- /node_modules

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <br>
        <br>
        <br>
        <button id="button-1">Button 1</button>
        <br>
        <br>
        <br>
        <button id="button-2" onclick="btn2Clicked()">Button 2</button>
        <script type="module" src="../dist/final.js"></script>
    </body>
</html>

id_selectors.js

const btn1 = document.querySelector("#button-1");

button1.js

import "../id_selectors.js";

btn1.addEventListener('click', () => {
    console.log('Button 1 clicked');
});

button2.js

const btn2Clicked= function()  {
        console.log('Button 2 clicked');
    }

index.js

import './components/button1.js';
import './components/button2.js';

webpack.config.js

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: 'final.js',
        path: __dirname + '/dist',
    },
};

Problem is that btn2Clicked() in index.html is not working as it’s giving “ReferenceError”.

Someone please help me to properly configure webpack.config.js & index.js to make available 3 files (id_selectors.js, button1.js & button2.js) globally (i.e., browser window level) into index.html.

Also I don’t want to modify id_selectors.js, button1.js & button2.js.

Note: I’m using Webpack 5.98.0

Thanks.

P.Roy.

How to kick the old session from websocket

async def connect(self):

    self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]
    pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
    self.redis = redis.Redis(connection_pool=pool)

    logger.info("channel_name:{} / group_name {}".format(self.channel_name,self.room_group_name))
    await self.channel_layer.group_add(
        self.room_group_name,
        self.channel_name
    )
    await self.accept()
    
    for key in self.redis.keys():
        if self.redis.type(key).decode() == "zset":
            print("key:",key)
            print("len:",len(self.redis.zrange(key,0,-1)))

async def disconnect(self, close_code):
    logger.info("somehow disconnect")
    await self.channel_layer.group_discard(
        self.room_group_name,
        self.channel_name
    )

I have this script for websockt connection.

then

I am directly checking the record in redis to get the current members of chatroom.

If a user log-out and call disconnect , session is disappeared.

However If a user didn’t call the disconnect function, session will be stored in redis table forver.

How can I remove the old session or set the timeout??

How to make the first scroll exactly 10px

I am a beginner learning coding, and I decided to create a small project, where a div is initially in the full screen, but when scrolled, it goes like sticky header, however, if the scroll is long (i.e the swipe is big), then the content below that div also scrolls up which I don’t want.. so any idea how to limit only and only the first scroll (the one which is when scroll = 0) to be only 10 px so it does not create a problem, or if there are any other solutions, please tell

Code: “`

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sticky Header Example</title>
    <style>
        body {
            margin: 0;
            font-family: Arial, sans-serif;
        }
        #logo {
            background: lightgray;
            text-align: center;
            font-size: 7rem;
            height: 95vh;
            padding-top: 50vh;
            position: relative;
            transition: all 0.3s ease;
        }
        .content {
            height: 2000px;
            background-color: lightblue;
        }
    </style>
</head>
<body>
    <div id="logo">Logo</div>
    <div class="content" id="games">Content below the logo</div>

    <script>
        let isAtTop = true;

        function checkIfAtTop() {
            return document.documentElement.scrollTop === 0;
        }

        window.onscroll = function () {
            let logo = document.getElementById("logo");
            let screenWidth = window.innerWidth;
            
            if (checkIfAtTop()) {
                // Limit the scroll for the first time to only 10px.
                if (document.documentElement.scrollTop > 10) {
                    document.documentElement.scrollTop = 10;
                }

                logo.style.fontSize = screenWidth < 480 ? "1rem" : screenWidth < 768 ? "4rem" : "7rem";
                logo.style.textAlign = "center";
                logo.style.height = screenWidth < 480 ? "55vh" : screenWidth < 768 ? "75vh" : "95vh";
                logo.style.paddingTop =
                    window.innerHeight * 0.5 - parseFloat(getComputedStyle(document.documentElement).fontSize) * (screenWidth < 768 ? 3 : 5.5) + "px";
                logo.style.paddingLeft = "5px";
                
                document.getElementById("games").innerHTML = `<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></br>`;
                
            } else {
                logo.style.fontSize = screenWidth < 480 ? "1rem" : screenWidth < 768 ? "2rem" : "4.5rem";
                logo.style.textAlign = "left";
                logo.style.height = screenWidth < 480 ? "1.5rem" : screenWidth < 768 ? "3rem" : "6rem"; 
                logo.style.padding = "12px 18px";
                logo.style.justifyContent = "left";
                logo.style.position = "fixed";

                setTimeout(function() { 
                    document.getElementById("games").innerHTML = `<a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>
                    <a class="tile" href="Reaction/reaction.html"></a>`; 
                }, 1500);
            }
        };
    </script>
</body>
</html>
```

Flatpickr on django template not working on mobile device

I have interesting problem.
Have this template:

{# date picker #}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css"/>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/bg.js"></script>
<link rel="stylesheet" type="text/css" href="{% static "custom/date_picker.css" %}"/>

<script>
document.addEventListener("DOMContentLoaded", function () {
// Ensure Flatpickr's localization is loaded before modifying
if (flatpickr.l10ns && flatpickr.l10ns.bg) {
    flatpickr.l10ns.bg.rangeSeparator = " до ";
} else {
    console.warn("Bulgarian locale not found, continuing without modifying rangeSeparator.");
}

const dateTimePickers = ["#fromInput", "#toInput"];

dateTimePickers.forEach(selector => {
    flatpickr(selector, {
        enableTime: true,
        time_24hr: true,
        locale: "bg",
        dateFormat: "H:i ч. на d M Y г.",
        enableSeconds: false,  // Ensure seconds are not required
        disableMobile: true  // Forces Flatpickr UI on mobile
    });
});

</script>

Then I have this two inputs:

            <div style="margin-top: 15px" id="fromDiv">
                <label for="fromTime">От</label>
                <input type="text" id="fromInput" name="fromTime"
                       placeholder="Избери дата и час" style="margin: auto">
            </div>

            <div style="margin-top: 15px" id="toDiv">
                <label for="dateTimeInput">До</label>
                <input type="text" id="toInput" name="toTime"
                       placeholder="Избери дата и час" style="margin: auto">
            </div>

Everything works perfectly on desktop browser, but when is used on mobile device, inputs change, want seconds, but in choice pop up it’s not possible to be selected seconds.

Examples on desktop browser:

pop-up and input on desktop device

how looks input and choice pop-up on desktop browser

Examples on mobile:

pop-up choice on mobile browser

pop-up choice on mobile browser
and date-time input on mobile browser.. how they look

date-time input with seconds on mobile browser

My question is how to make mobile browser input and pop-up same as browser one?
Try a lot of things, but nothing works…

Now on mobile device do not work, and can not proceed, because on mobile browser wants seconds, but client can not choose one. Also i want pop-up and input to looks the same on web and mobile browser.

Remove Height from CSS Container

I am trying to configure a timer on my website using Javascript & CSS:

var h3 = document.getElementsByTagName("h3");
h3[0].innerHTML = "Countdown Timer With JS";

var sec = 1800,
  countDiv = document.getElementById("timer"),
  secpass,
  countDown = setInterval(function () {
      'use strict';

      secpass();
  }, 1000);

function secpass() {
  'use strict';

  var min     = Math.floor(sec / 60),
      remSec  = sec % 60;

  if (remSec < 10) {

      remSec = '0' + remSec;

  }
  if (min < 10) {

      min = '0' + min;

  }
  countDiv.innerHTML = min + ":" + remSec;

  if (sec > 0) {

      sec = sec - 1;

  } else {

      clearInterval(countDown);

      countDiv.innerHTML = 'countdown done';

  }
}
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    width: 100%;
    font: normal bold 16px/normal tahoma;
}

article {
    width: 300px;
    text-align: center;
    background-color: #68b04d;
    border-radius: 10px;
    margin: 50px auto 20px;
    padding: 5px;
    overflow: hidden;
    box-shadow: 3px 3px 10px #ccc;
}

article h3 {
    padding: 10px;
    color: #fff;
}
article .count {
    padding: 5px;
}
article #timer{
    padding: 5px;
    color: crimson;
    background-color: aliceblue;
    border-radius: 2px;
}
<!-- Creat Countdown Timer -->
<article class="clock" id="model3">
  <h3></h3>

  <div class="count">
    <div id="timer"></div>
  </div>
</article>

Working model is at https://codepen.io/falak786/pen/oddYYd

What I DO NOT want is the title which currently reads as follows in JS code:

h3[0].innerHTML = "Countdown Timer With JS";

So I change it to

h3[0].innerHTML = "";

Still, the problem is that HEIGHT is NOT going away. It is remaining fixed as shown by blue marker:
enter image description here

I also tried changing the <h3> tag setting in my CSS file, and also changing the <h3> tagname itself in the above code to a random <hz> tagname, but still the height is staying there with no text.

What can I do to remove this height?

Can’t import Data from CSV File into supabase (sveltekit app)

In my app I’ve got a page dedicated to CSV Imports. I can upload any CSV, and it’ll then map out the headers taken from the csv file, and give the user to option to place it in a particular table, and then select a column from that table.

My tables (which exist in supabase) are:

lawfirm,
lawyerscontactprofiles,
products,
website.

Every time I attempt to import data from the CSV file, the lawfirm table receives all of the entries – but the other three tables only receive one.

I’m presuming it has something to do with the fact that the “lawfirmname” column, which is foreign key in the other three tables, has something to do with this.

I’ve spent the last couple of days on finding a solution, and have no luck yet.

I can see that the information is passed into the array with no issue but then the object will only contain 1 value (in the three other tables)

+page.svelte

<script>
  import { parse } from "csv-parse";
  let file;
  let headers = [];
  let data = [];
  let columnMappings = [];

  const tableColumns = {
    lawfirm: [
      "lawfirmname",
      "clientstatus",
      "websiteurl",
      "address1",
      "address2",
      "city",
      "stateregion",
      "postalcode",
      "country",
      "phonenumber",
      "emailaddress",
      "description",
      "numberofemployees",
    ],
    lawyerscontactprofiles: [
      "firstname",
      "lastname",
      "email",
      "phone",
      "profilepicture",
      "position",
      "accountemail",
      "accountphone",
      "addressline1",
      "suburb",
      "postcode",
      "state",
      "country",
      "website",
      "lawfirmname",
    ],
    products: [
      "websitedevelopment",
      "websitehosting",
      "websitemanagement",
      "newsletters",
      "searchengineoptimisation",
      "socialmediamanagement",
      "websiteperformance",
      "advertising",
      "lawfirmname",
    ],
    websites: ["url", "dnsinfo", "theme", "email", "lawfirmname"]
  };

  function handleFileChange(event) {
    file = event.target.files[0];
    console.log("File selected:", file);
  }

  async function handleFileUpload() {
    if (!file) {
      alert("Please select a file to upload.");
      return;
    }

    const reader = new FileReader();
    reader.onload = async (event) => {
      const csvData = event.target.result;

      parse(
        csvData,
        {
          columns: true,
          skip_empty_lines: true,
        },
        (err, output) => {
          if (err) {
            console.error("Error parsing CSV:", err);
            return;
          }

          headers = Object.keys(output[0]);
          data = output;

          columnMappings = headers.map((header) => ({
            header,
            table: "",
            column: "",
          }));

          console.log("Headers:", headers);
          console.log("Data:", data);
          console.log("Column Mappings:", columnMappings);
        },
      );
    };

    reader.readAsText(file);
  }

  async function handleDataInsert() {
    const formattedData = {
      lawfirm: [],
      lawyerscontactprofiles: [],
      products: [],
      websites: [],
    };

    // Step 1: Process each row and propagate lawfirmname where necessary
    data.forEach((row, rowIndex) => {
      console.log(`Processing row ${rowIndex}:`, row); // Debugging row content

      let lawfirmname = "";

      const lawfirmObj = {};
      const lawyerscontactprofilesObj = {};
      const productsObj = {};
      const websitesObj = {};

      columnMappings.forEach(({ header, table, column }) => {
        const value = row[header] ? row[header].trim() : "";
        console.log(`Mapping column: ${header} -> table: ${table}, column: ${column}, value: ${value}`); // Debugging column mapping

        // Step 2: Check and process each table
        if (table === "lawfirm") {
          if (column === "lawfirmname") {
            let lawfirmNameHeader = columnMappings.find(
              (mapping) => mapping.table === "lawfirm" && mapping.column === "lawfirmname"
            )?.header;
            if (lawfirmNameHeader) {
              lawfirmname = row[lawfirmNameHeader]?.trim() || "";
            }
          }
          lawfirmObj[column] = value;
        } else if (table === "lawyerscontactprofiles") {
          lawyerscontactprofilesObj[column] = value;
        } else if (table === "products") {
          productsObj[column] = value;
        } else if (table === "websites") {
          websitesObj[column] = value;
        }
      });

      // Step 3: Propagate the lawfirmname to all related tables if it's available
      if (lawfirmname) {
        console.log(`Propagating lawfirmname: ${lawfirmname}`);
        // Ensure that lawfirmname is filled in the other tables
        if (!lawyerscontactprofilesObj.lawfirmname) {
          lawyerscontactprofilesObj.lawfirmname = lawfirmname;
        }
        if (!productsObj.lawfirmname) {
          productsObj.lawfirmname = lawfirmname;
        }
        if (!websitesObj.lawfirmname) {
          websitesObj.lawfirmname = lawfirmname;
        }
      }

      // Step 4: Push the data into the formattedData object for each table
      if (Object.keys(lawfirmObj).length && lawfirmname) {
        console.log("Adding lawfirm object to formatted data:", lawfirmObj);
        formattedData.lawfirm.push(lawfirmObj);
      }
      if (Object.keys(lawyerscontactprofilesObj).length) {
        console.log("Adding lawyerscontactprofiles object to formatted data:", lawyerscontactprofilesObj);
        formattedData.lawyerscontactprofiles.push(lawyerscontactprofilesObj);
      }
      if (Object.keys(productsObj).length) {
        console.log("Adding products object to formatted data:", productsObj);
        formattedData.products.push(productsObj);
      }
      if (Object.keys(websitesObj).length) {
        console.log("Adding websites object to formatted data:", websitesObj);
        formattedData.websites.push(websitesObj);
      }
    });

    console.log("Formatted Data:", formattedData);

    // Step 5: Remove duplicates for the data being sent
    formattedData.lawfirm = removeDuplicates(formattedData.lawfirm, "lawfirmname");
    formattedData.lawyerscontactprofiles = removeDuplicates(formattedData.lawyerscontactprofiles, "email");
    formattedData.products = removeDuplicates(formattedData.products, "lawfirmname");
    formattedData.websites = removeDuplicates(formattedData.websites, "url");

    const formData = new FormData();
    formData.append("data", JSON.stringify(formattedData));

    try {

      function getCookie(name) {
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) return parts.pop().split(';').shift();
      }

      // Get the access token from the cookie
      const accessToken = getCookie('supabase-auth-token');

      const response = await fetch("/upload", {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${accessToken}`,
        },
        body: formData,
      });

      if (!response.ok) {
        const errorText = await response.text();
        console.error("HTTP error! status:", response.status, "Response text:", errorText);
        return;
      }

      const contentType = response.headers.get("content-type");
      if (!contentType || !contentType.includes("application/json")) {
        const errorText = await response.text();
        console.error("Error: Non-JSON response:", errorText);
        return;
      }

      const result = await response.json();
      if (result.success) {
        console.log(result.message);
      } else {
        console.error(result.error);
      }
    } catch (error) {
      console.error("Error uploading data:", error);
    }
  }

  function removeDuplicates(data, uniqueColumn) {
    const seen = new Set();
    return data.filter((item) => {
      const value = item[uniqueColumn];
      if (seen.has(value)) {
        return false;
      }
      seen.add(value);
      return true;
    });
  }
</script>

<div class="homeBanner">
  <h1 class="leftAlign">Upload CSV</h1>
  <div class="searchAndAdd">
    <input type="file" accept=".csv" on:change={handleFileChange} />
    <button on:click={handleFileUpload}>Import CSV</button>
  </div>
</div>

{#if headers.length}
  <div class="mappingSection">
    {#each columnMappings as mapping, index}
      <div class="mappingRow">
        <label for="table-{index}">{mapping.header}</label>
        <select id="table-{index}" bind:value={mapping.table}>
          <option value="">Select table</option>
          {#each Object.keys(tableColumns) as table}
            <option value={table}>{table}</option>
          {/each}
        </select>
        {#if mapping.table}
          <select id="column-{index}" bind:value={mapping.column}>
            <option value="">Select column</option>
            {#each tableColumns[mapping.table] as column}
              <option value={column}>{column}</option>
          {/each}
        </select>
        {/if}
      </div>
    {/each}
    <button class="insertButton" on:click={handleDataInsert}>Insert Data</button>
  </div>
{/if}

Surprisingly the Chrome Dev console allows me to mutate a private field

I believe I’ve encountered a bug in Chrome DevTools where it allows me to mutate a private field of an object globally, bypassing the intended encapsulation of private fields in JavaScript.

Here’s the code I used to reproduce the issue:

class Person {
    #name = 'George';

   getName(){
    return this.#name;
  }
}


let george = new Person();
george.#name = 'Test';

console.log(george.#name); // Test
console.log(george.getName()); // Test

it unexpectedly allows me to mutate the private field #name. This behavior does not occur in Firefox, which correctly enforces the privacy of the field and throws an error.

This behavior in Chrome DevTools violates the intended encapsulation of private fields in JavaScript. I suspect this is a bug in Chrome’s handling of private fields during runtime evaluation in the DevTools console. I recommend investigating and fixing this issue to ensure compliance with the JavaScript specification.

Trying to find a ui or gui that I can call the functions from a loaded module

I have this program that uses ducktape api for scripting and I wanted to know if there are any modules that I can load through this function, require(id) ex: const mymodule = require(‘mymodule/lib.dll’); // Loads Scripts/modules/mymodule/lib.dll
mymodule.init(); // Prints “Loaded mymodule” That would allow me to create a user interface? is: Reference and or use functions from that DLL to create some sort of gui overlay. I am essentially trying to look for something that is compatible with ducktape and wanted to see if anyone had any suggestions.

Or better yet if I want to do is even possible.