It is possible in Oracle Apex 24.2 to build something to download/export a table that has SDO_GEOMETRY in shapefile format?

I have tables in Oracle that contain spatial data using the SDO_GEOMETRY data type. I would like to create a button inside APEX that allows users to download a zipped shapefile export of this data. The shapefile should include all the standard files such as .shp, .shx, .dbf, and so on. Is there a way to implement this functionality directly within Oracle APEX?

I tried to manually convert the SDO_GEOMETRY data to shapefile format, but I ran into issues with encoding and generating the correct .dbf, .shx, and .shp files. Due to these complexities, I couldn’t create a proper shapefile export.

What I am looking for is a way to generate a zipped shapefile directly from within Oracle APEX, including all necessary files (.shp, .shx, .dbf, etc.), so users can download and use it easily.

Foreground Shape Doesn’t Fully Cover Background – Black Pixels Visible Through Foreground in Overlapping Elements

I’m working on a layout where two circular div elements overlap exactly — one acting as a black background and the other as a gray foreground — using absolute positioning inside a container. Here’s a simplified version of the code:

<div class="container">
   <div id="background" class="shape"></div>
   <div id="foreground" class="shape"></div>
</div>

And the relevant CSS:

.shape {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    
    backface-visibility: hidden;
    transform: translateZ(0);
    shape-rendering: geometricPrecision;
}

#background {
    background: black;
}

#foreground {
    background: gray;
}

Despite having the foreground element placed on top of the background, some black pixels from the background remain visible around the edges, almost like an aliasing or blending artifact. I tried to address this by adding:

backface-visibility: hidden;
transform: translateZ(0);
shape-rendering: geometricPrecision;

…but these properties did not resolve the issue.
Why are the black pixels still visible, and how can I ensure that the foreground shape fully and cleanly covers the background without those edge artifacts?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
    <style>
        
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;

            background-color: gray;
        }
        
        .container {
            position: relative;
            display: inline-block;
            
            width: 400px;
            height: 300px; 
        }
        
        .shape {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            
            backface-visibility: hidden;
            transform: translateZ(0);
            shape-rendering: geometricPrecision;
        }

        #background {
            background: black;
        }
        
        #foreground {
            background: gray;
        }
        
    </style>

</head>
<body>
    
    <div class="container">
        <div id="background" class="shape"></div>
        <div id="foreground" class="shape"></div>
    </div>
    
</body>
</html>

I am looking for help to solve the issue, not looking for hacks or kind of playing with scale of foreground shape to cover more area than background.

Issue:

enter image description here

Send message to background when popup closes / loses focus

My Chrome extension popup consists of a library of YouTube videos. Each has a “fullscreen” button that when clicked opens a new tab with the YouTube video in fullscreen. This (expectedly) causes the extension popup to close.

For analytics, I want to keep track of when each video gets launched in fullscreen, but my fetch in the onClick handler is failing because the popup closes.

How can I send a message to the background script so that the background can perform the fetch instead of the popup?

Problems with positioning angles when resizing and flipping shapes in HTML5 Canvas

I am developing a web image editor that uses HTML5 Canvas. One of the key features is resizing shapes. To handle sizes correctly, I implemented a ‘flip’ logic that prevents negative width or height. This happens when the user drags a corner to the opposite side, and the sizes newW or newH become negative; in this case, I invert their sign and change the active corner (activeCorner).

The problem arises when, after such a ‘flip’, especially for certain combinations of angles (for example, when moving from bottom-right to bottom-left when flipping along the X-axis, or from bottom-left to top-left when flipping along the Y-axis), the figure shifts sharply or is positioned incorrectly. This leads to jerky size changes. I suspect that the problem lies in the inaccurate recalculation of newX and newY after the size inversion and active angle change.

In addition, I noticed that with rapid repeated ‘flipping’ (when I quickly jerk the corner back and forth, crossing the opposite side), the figure gradually ‘slips’ away from its original position, accumulating errors in the coordinates.

Below is a code snippet responsible for the logic of resizing and flipping the shape. The variables mouseStartX, mouseStartY store the initial mouse coordinates, originalX, originalY, originalWidth, originalHeight store the initial parameters of the shape, and pos stores the current mouse coordinates relative to the canvas. selectedShape.rotation indicates the rotation of the shape (in degrees).

        if (isResizing && (event.buttons & 1)) {
            const rotation = selectedShape.rotation;
            const dx = pos.x - mouseStartX;
            const dy = pos.y - mouseStartY;

            let newX = originalX;
            let newY = originalY;
            let newW = originalWidth;
            let newH = originalHeight;

            const cos = Math.cos(-rotation * Math.PI / 180);
            const sin = Math.sin(-rotation * Math.PI / 180);

            const localDx = dx * cos - dy * sin;
            const localDy = dx * sin + dy * cos;

            let flipX = false, flipY = false;

            if (activeCorner === 'top-left') {
                newW = originalWidth - localDx;
                newH = originalHeight - localDy;

                if (newW < 0) {
                    flipX = true;
                    newW = -newW;
                }
                if (newH < 0) {
                    flipY = true;
                    newH = -newH;
                }

                if (flipX && flipY) {
                    newX = originalX + originalWidth;
                    newY = originalY + originalHeight;
                    activeCorner = 'bottom-right';
                }
                else if (flipX) {
                    newX = originalX + originalWidth;
                    newY = originalY + localDy;
                    activeCorner = 'top-right';
                }
                else if (flipY) {
                    newX = originalX + localDx;
                    newY = originalY + originalHeight;
                    activeCorner = 'bottom-left';
                }
                else {
                    newX = originalX + localDx;
                    newY = originalY + localDy;
                }
            }
            else if (activeCorner === 'top-right') {
                newW = originalWidth + localDx;
                newH = originalHeight - localDy;

                if (newW < 0) {
                    flipX = true;
                    newW = -newW;
                }
                if (newH < 0) {
                    flipY = true;
                    newH = -newH;
                }

                if (flipX && flipY) {
                    newX = originalX - (newW - originalWidth);
                    newY = originalY + originalHeight;
                    activeCorner = 'bottom-left';
                }
                else if (flipX) {
                    newX = originalX - (newW - originalWidth);
                    newY = originalY + localDy;
                    activeCorner = 'top-left';
                }
                else if (flipY) {
                    newX = originalX;
                    newY = originalY + originalHeight;
                    activeCorner = 'bottom-right';
                }
                else {
                    newX = originalX;
                    newY = originalY + localDy;
                }
            }
            else if (activeCorner === 'bottom-left') {
                newW = originalWidth - localDx;
                newH = originalHeight + localDy;

                if (newW < 0) {
                    flipX = true;
                    newW = -newW;
                }
                if (newH < 0) {
                    flipY = true;
                    newH = -newH;
                }

                if (flipX && flipY) {
                    newX = originalX + originalWidth;
                    newY = originalY - (newH - originalHeight);
                    activeCorner = 'top-right';
                }
                else if (flipX) {
                    newX = originalX + originalWidth;
                    newY = originalY;
                    activeCorner = 'bottom-right';
                }
                else if (flipY) {
                    newX = originalX + localDx;
                    newY = originalY - (newH - originalHeight);
                    activeCorner = 'top-left';
                }
                else {
                    newX = originalX + localDx;
                    newY = originalY;
                }
            }
            else if (activeCorner === 'bottom-right') {
                newW = originalWidth  + localDx;
                newH = originalHeight + localDy;

                if (newW < 0) {
                    flipX = true;
                    newW = -newW;
                }
                if (newH < 0) {
                    flipY = true;
                    newH = -newH;
                }

                if (flipX && flipY) {
                    newX = originalX - (newW - originalWidth);
                    newY = originalY - (newH - originalHeight);
                    activeCorner = 'top-left';
                }
                else if (flipX) {
                    newX = originalX - (newW - originalWidth);
                    newY = originalY;
                    activeCorner = 'bottom-left';
                }
                else if (flipY) {
                    newX = originalX;
                    newY = originalY - (newH - originalHeight);
                    activeCorner = 'top-right';
                }
                else {
                    newX = originalX;
                    newY = originalY;
                }
            }

            selectedShape.x = newX;
            selectedShape.y = newY;
            selectedShape.width = newW;
            selectedShape.height = newH;

            if (flipX || flipY) {
                mouseStartX = pos.x;
                mouseStartY = pos.y;
                originalX = newX;
                originalY = newY;
                originalWidth  = newW;
                originalHeight = newH;
            }

            redrawAll();
            updateRectAnglePropertyPanel();
            return;
        }

I suspect that the problem lies in the inaccurate recalculation of newX and newY after inverting the dimensions and changing the active angle.

So far, the shape is a rectangle without rotation.

How can I correctly adjust the newX and newY coordinates (and possibly the logic for changing activeCorner) in the ‘flip’ conditions for a rotated rectangle so that its positioning and resizing remain smooth and accurate, without jumps and accumulation of errors during multiple flips?

If you need additional code, please ask. I am also open to completely changing the resizing logic if you suggest it.

Jest changes JSON while importing?

I’m testing document generation forms using Jest. Each test case uses the same JSON mock that contains an array of two items. When I run the test for a single form, the order of items in the array is correct: [ItemA, ItemB]

However, when I run tests for multiple forms the array appears in a different order: [ItemB, ItemA]

The mock is a static .json file imported like this:

import mockData from '../../path/to/mock.json';

Even when I log mock immediately after import, the order is already incorrect.

Some specs:

  • jest 27.x
  • env jsdom
  • jest.config.js includes only babel-jest in the transform field and does not specify any custom loader for JSON files, also babel-jest doesnt touch JSON files

Why does the order of elements in the array change depending on how many test cases I run?

What can I do to guarantee that the array is always loaded in the correct order?

React Search Page Not Fetching Blogs from Render-Hosted Express + MongoDB Backend

I’ve deployed a MERN stack news portal to Render:

Frontend: https://news-portal-f.onrender.com

Backend: https://news-portal-jzcd.onrender.com

The backend uses Express and connects to MongoDB Atlas, and exposes an endpoint /blogs that should return all blog entries. On the frontend, I have a SearchResults component that fetches the data, filters it based on a search query, and displays the matching results.

However, my search results page is stuck at “Loading…” or sometimes prints “No results found” — even though the backend works fine when I hit it directly via Postman.

What I’ve Tried:
Accessing https://news-portal-jzcd.onrender.com/blogs manually in browser → returns JSON ✔️

Checked CORS setup on backend: origin is correctly set to frontend domain ✔️

Console logs in backend show no requests hitting /blogs from frontend ❌

Tried both using process.env.REACT_APP_BACKEND_URL and hardcoded backend URL

No major frontend error logs, but request sometimes just hangs or fails silently

  origin: "https://news-portal-f.onrender.com"
}));

app.get("/blogs", async (req, res) => {
  const blogs = await Blog.find();
  res.json({ blog: blogs });
});
  const backendUrl = process.env.REACT_APP_BACKEND_URL || "https://news-portal-jzcd.onrender.com";

  fetch(`${backendUrl}/blogs`)
    .then(res => res.json())
    .then(data => {
      setBlogs(data.blog);
      setLoading(false);
    })
    .catch(err => {
      console.error("Error fetching blogs:", err);
      setLoading(false);
    });
}, []);

My Questions:
Is there a known issue with Render that blocks frontend-to-backend requests across subdomains?

Do I need to prefix /blogs with /api or structure routes differently?

Could this be an async deployment issue (Render’s cold start)? Do I need retries or pre-warmers?

Any other tips to debug why frontend is not hitting backend despite proper CORS and correct URL?

React frontend not connecting to Express backend deployed on Render – CORS issue or endpoint mismatch?

I’m building a news portal with a React frontend and an Express backend. Both are deployed on Render:

Frontend: https://news-portal-f.onrender.com

Backend: https://news-portal-jzcd.onrender.com

I’m trying to send a POST request from a form in React to /add-blog endpoint in Express. But the request doesn’t seem to reach the backend.

import axios from "axios";
import { useState } from "react";

function AddBlog() {
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("");

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await axios.post("https://news-portal-jzcd.onrender.com/add-blog", {
        title,
        content,
      });
      alert("Blog added!");
    } catch (err) {
      console.error("Error:", err);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input value={title} onChange={(e) => setTitle(e.target.value)} />
      <textarea value={content} onChange={(e) => setContent(e.target.value)} />
      <button type="submit">Submit</button>
    </form>
  );
}
const express = require("express");
const cors = require("cors");
const app = express();

app.use(cors({
  origin: "https://news-portal-f.onrender.com"
}));
app.use(express.json());

app.post("/add-blog", (req, res) => {
  console.log(req.body); // Doesn't get logged
  res.json({ message: "Blog added" });
});

What I’ve Checked So Far:
CORS is set up with the correct frontend origin.

POST request URL in React is correct.

Backend logs show no request reaching /add-blog.

No obvious error in browser console (but request might hang or fail silently).

Network tab in Chrome shows the request is pending or fails with 404.

My Questions:
Is there anything I’m missing in the way React or Express is deployed on Render?

Could this be a route mismatch or something to do with how Render handles server URLs?

Is /add-blog correctly configured or should I prefix it with /api or something else?

How to make Zod behave like interface and class forced to implement said interface

I am trying to achieve the following behavior.

export const NotificationDataSchema = z.object({
    type: z.string(),
    data: z.object({}),
});

export const LikesMilestoneSchema = NotificationDataSchema.extend({
    type: z.literal('LikesMilestone'),
    data: z.object({
        count: z.number(),
    });
});

export const NewFollowerSchema = NotificationDataSchema.extend({
    type: z.literal('NewFollower'),
    // data: z.object({
    //     age: z.number(),
    // })
});

And I want NewFollowerSchema to show Error because it doesn’t define data similar to how interface and classes interact, is that possible?

My end goal is to create:

export const NotificationData = z.union([
    LikesMilestoneSchema,
    NewFollowerSchema,
]);

export const NotificationSchema = z.object({
    id: z.string(),
    isRead: z.boolean(),
    date: z.date(),
    data: NotificationData
});

So I could send it as a merged list to the frontend where it will be parsed.
But can Zod enforce a subschema to define all fields?

Event Loop behaves differently with blocking code

This is not a duplicate of another question, as I’ve searched here and did not find an answer.

I’m learning about the Node.js event loop and tried the following code, which behaves differently depending on how long the event loop is blocked.

My code:

const fs = require('node:fs/promises');

// Schedule a timeout
setTimeout(() => {
  console.log("set timeout callback is called!");
}, 10);

function consumeCpu(limit) {
  console.log(`waiting a while (limit is ${limit})`);
  let sum = 1;
  for (let i = 0; i < limit; i++) {
    sum += i;
  }
}

let cycles = Number(process.argv[2]);

// Wait a while (blocking CPU)
consumeCpu(cycles);

// Run an async I/O action which will fail
(async () => {
  try {
    // This file does not exist, so an error will be thrown
    let data = await fs.readFile('/tmp/123.txt');
  } catch (err) {
    console.log("err is: " + err);
  }
})();

// Wait a while again (blocking CPU)
consumeCpu(cycles);

console.log("end of script");

// Let event loop start processing

Running the code

1. With a small blocking delay:

node test.js 100

output:

waiting a while (limit is 100)
waiting a while (limit is 100)
end of script
err is: Error: ENOENT: no such file or directory, open '/tmp/123.txt'
set timeout callback is called!

Here, the promise rejection is handled before the timeout callback runs, as expected.

2. With a large blocking delay

node test.js 1000000000

output:

waiting a while (limit is 1000000000)
waiting a while (limit is 1000000000)
end of script
set timeout callback is called!
err is: Error: ENOENT: no such file or directory, open '/tmp/123.txt'

In this case, the timeout callback runs before the promise rejection is handled.

Node.js version

I’m using Node.js v22.12.0.

Question

Why does Node.js behave differently depending on how long the main code blocks the event loop?
My understanding is that promises create microtasks, which should always have priority over macrotasks like those scheduled with setTimeout. Why does blocking the event loop with the consumeCpu function call make a difference?

OAuth Popup Flow Design — Handling Full Redirects Without window.opener or Reliable window.closed

My question is related to the design of one implementation so I hope that I will find the appropriate one here!

I’m implementing OAuth2 login in a web application using a popup window strategy. The flow works as follows:

  1. A button in the main window opens a popup to the OAuth provider’s authorize URL.
  2. The user logs in or grants access.
  3. The provider redirects back to a URL I control (e.g., /oauth-callback), where I process the authorization code and respond with a small HTML/JS page.
  4. This page sends the result back to the main window.

What works:
When the user is already logged in, the popup doesn’t perform a full-page redirect, and I can use window.opener.postMessage(…) to return the result.

What does not work (pipedrive only currently, salesforce works okay):
If the user is not logged in, the popup performs a full-page redirect (across domains), which results in:

window.opener === null (can’t use postMessage)

popup.closed === true in the main window (even if the window is still open and visible)

Some workarounds that I found:

I switched to using BroadcastChannel from the callback page, like this:

const channel = new BroadcastChannel('oauth-channel');
channel.postMessage({ type: 'oauth-success', data: ... });

The problem now with BroadcastChannel, I have no reliable way of detecting whether the user manually closed the popup (clicked “X”) — because:

I can’t use popup.closed (it’s true even when the popup is still alive)

So the main question here is:

What is the recommended design pattern for handling OAuth login via popup that satisfies:

  1. Full support for OAuth2 redirects (even full-page cross-origin)

  2. A way to distinguish between success, failure, and if user closed the popup.

Thank you in advance 🙂

Is this a bug in Javascript, NodeJS and/or deno? [duplicate]

JavaScript, generally, allows executing a simple expression, even though it has no side effects and is generally pretty useless. For example, the following are valid JavaScript files:

42

and

'abc'

What I mean by that is that if I put one of these in a file and execute it via:

node file.js

of

deno run file.js

I get no errors (and, of course, no output).

However, if I put the following expression in a JavaScript file, I get an error when attempting to execute the file via either of the above 2 methods:

function*(line) {
  yield 42;
  return;
}

NodeJS says “SyntaxError: Function statements require a function name”
deno says “The module’s source code could not be parsed: Expected ident at…”

However, this will parse and execute without error:

let f = function*(line) {
  yield 42;
  return;
}

Here, there is no identifier required in the function statement – an anonymous function is created and assigned to the variable f. So, why was an identifier required before?

Before you answer, consider the JavaScript code below, which is where I came across this problem:

let f = function*(line) {
  yield 42;
  return;
}

console.log(f.toString());

The code parses and executes without error. However, it outputs this:

function*(line) {
  yield 42;
  return;
}

which, as you can see above, is considered invalid JavaScript. So, I’ve created a perfectly valid function, but JavaScript’s buildin toString() method returned invalid JavaScript code!

So, e.g., if I try to minimize it using uglify-js, gives me an error. And, of course, I couldn’t execute it since it’s invalid JavaScript code.

How to work with dot-notation keys in a bracket notation function? [duplicate]

I am being provided with key names (by a validator) that are strings using dot notation. For example, the validation spec of the key AccountID may look like this (for different departments):

ValidationRules =
[
     {
         KeyName: "Transfer.Legal.Dept",
         Required: true
         MinLength: 3,
         MaxLength: 3,
         ValidRegex: `^.{3}$`,
     }
    ,
    {
         KeyName: "Transfer.Accounts.Dept",
         MinLength: 4,
         MaxLength: 10,
         ValidRegex: `^\d{4,10}$`,,
    }
]

The form data being submitted would have a shape similar to this:

FormData =
 {
      Tranfser: {
         Legal: {Dept: "Disbursements", Amount: 50, Direction: "Out"},
         Accounts: {Dept: "Fees", Amount: 50, Direction: "In" }
      },
      Provider: "General Pay",
      SomeRandomStuff: {Rand1: "j6b", Rand2: "pm13"}
 }

Looping through the validation spec, the task is to check each property in the form data against the validation criteria by keyname. So Transfer.Legal.Dept is required and must be present in FormData.

My thinking started like this:

 for (let i = 0; i < ValidationRules.length; i++) {
    
   const KeyNameArray = ValidationRules[i].KeyName.split('.');
   // ["Transfer", "Legal", "Dept"]

     if (ValidationRules[i].Required) {
       // Check if Dept property (key+value) is in FormData.Transfer.Legal
       KeyNameArray[KeyNameArray.length-1] in FormData[KeyNameArray.length-2]
       
       /* The above should check if last item in KeyNameArray i.e. Dept is in FormData.Transfer.Legal 
        * But it doesn't check any other levels e.g. if Legal is in FormData.Transfer
       */
    
       // Now check if FormData.Transfer.Legal.Dept != null and has a value
       /* See ideas below */

   
     }
    }

Trying to go straight to FormData[ValidationRules[i].KeyName] doesn’t work because it is looking for a single key of "Transfer.Legal.Dept" in FormData which doesn’t exist.

Maybe I could through KeyNameArray and build up a selector like such:

for (i=0; i < KeyNameArray.length; i++){
  /* How to build up the selector to end up with:
   * FormData["Transfer"]["Legal"]["Dept"]
  */ 
}

But I can’t seem to “build” the selector like above. Or maybe this whole approach is wrong. I saw something about an Array.reduce function which looked like it might work in this situation – would that be a better option?

Call function from Class onclick

I have this pagination script. It works fine, except that the onclick functions inside handlePagination() are undefined.
I also tried with this.handlePagination() but it didn’t make any difference.

How can I call a Class function onclick from within the Class?

Or can it be done in a better way using addEventListener()?

const pagination = document.querySelectorAll('.pagination-block');

class Pagination {
    constructor(pagination) {
        this.pagination = pagination;
        this.ul = this.pagination.querySelector('.pagination > ul');
        this.items = this.pagination.querySelectorAll('.post');
        this.handlePagination(6, 1);
    }

    generatePageNumber(totalPages, currentPage) {
        let pagination = [],
            pageNo = 1;

        while (pageNo <= totalPages) {
            let isFirstPage = pageNo <= 1,
                isLastPage = pageNo == totalPages,
                isMiddlePage = pageNo >= currentPage - 1 && pageNo <= currentPage + 1
            if (isFirstPage || isLastPage || isMiddlePage) {
                pagination.push(pageNo);
                pageNo++
            } else {
                pagination.push('...');
                pageNo = pageNo < currentPage ? currentPage - 1 : totalPages;
            }
        }
        return pagination;
    }

    updateCurrentPage(postPerPage, currentPage) {
        let prevRange = (currentPage - 1) * postPerPage,
            currentRange = currentPage * postPerPage;

        this.items.forEach((item, index) => {
            let isPageWithinRange = index >= prevRange && index < currentRange;
            item.classList.toggle('show', isPageWithinRange);
        })
    }

    handlePagination(postPerPage, currentPage) {
        /**
         * @param postPerPage int Numbers of items to show at the time.
         * @param currentPage int Page number to start on.
         */
        this.updateCurrentPage(postPerPage, currentPage);
        const totalPages = Math.ceil(this.items.length / postPerPage);
        let pageNumbers = this.generatePageNumber(totalPages, currentPage);

        this.ul.innerHTML = '';
        let li = '';
        li += `<li class="page-item page-prev ${currentPage <= 1 ? 'hidden' : ''}" onclick="handlePagination(${postPerPage}, ${currentPage - 1})"><span class="icon">&lt;</span></li>`;
        for (let pageNumber of pageNumbers) {
            li += `<li class="page-item ${currentPage == pageNumber ? ' active' : ''}" onclick="handlePagination(${postPerPage}, ${pageNumber})">${pageNumber}</li>`;
        }
        li += `<li class="page-item page-next ${currentPage >= totalPages ? 'hidden' : ''}" onclick="handlePagination(${postPerPage}, ${currentPage + 1})"><span class="icon">&gt;</span></li>`;
        this.ul.innerHTML = li;
    }
}

Array.from(pagination).forEach((paginate) => {
    const paginationEl = new Pagination(paginate);
});
* {
    box-sizing: border-box;
}

.body {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.posts {
    list-style: none;
    display: grid;
    grid-template-columns: auto auto auto;
    gap: 1rem;
}

.post {
    display: none;
}

.post.show {
    display: block;
}

.post h2 {
    margin: 1rem 0 .5rem;
}

.thumbnail {
    width: 23rem;
    height: 11.5rem;
    background-color: #efefef;
    border-radius: 1rem;
    cursor: pointer;
}

.pagination {
    background-color: #111;
    border-radius: .3rem;
}

.pagination ul {
    list-style: none;
    display: flex;
    justify-content: center;
    gap: .2rem;
}

.page-item {
    color: #fff;
    width: 3rem;
    height: 3rem;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    user-select: none;
    cursor: pointer;
}

.page-item .icon {
    display: inline-block;
}

.page-item:hover {
    background-color: #444;
}

.page-item.active {
    background-color: #444;
}

.page-item.hidden {
    display: none;
}
<div class="container pagination-block">
    <ul class="posts">
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 1</h2>
            <p>1.2M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 2</h2>
            <p>500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 3</h2>
            <p>1500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 4</h2>
            <p>10.000 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 5</h2>
            <p>500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 6</h2>
            <p>1M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 7</h2>
            <p>1.2M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 8</h2>
            <p>500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 9</h2>
            <p>1500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 10</h2>
            <p>10.000 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 11</h2>
            <p>500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 12</h2>
            <p>1M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 13</h2>
            <p>1.2M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 14</h2>
            <p>500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 15</h2>
            <p>1500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 16</h2>
            <p>10.000 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 17</h2>
            <p>500 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 18</h2>
            <p>1M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 19</h2>
            <p>1.2M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 20</h2>
            <p>300 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 21</h2>
            <p>100 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 22</h2>
            <p>10.000 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 23</h2>
            <p>767 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 24</h2>
            <p>1M. views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 25</h2>
            <p>12 views</p>
        </li>
        <li class="post">
            <div class="thumbnail"></div>
            <h2>Title of post 26</h2>
            <p>1M. views</p>
        </li>
    </ul>

    <nav class="pagination">
        <ul>
            <li class="page"><span class="icon">&lt;</span></li>
            <li class="page">1</li>
            <li class="page">...</li>
            <li class="page">2</li>
            <li class="page">3</li>
            <li class="page">4</li>
            <li class="page">...</li>
            <li class="page">5</li>
            <li class="page"><span class="icon">&gt;</span></li>
        </ul>
    </nav>
</div>

Node.js: While Loop Skips await and Causes Resource Exhaustion

I’ve run into an issue where the while loop in my program executes repeatedly before the Promise from once() resolves, effectively skipping the await. This causes the loop to run over and over, adding more and more event listeners until the V8 engine eventually crashes due to resource exhaustion.

The code itself is straightforward — I’m using a catchError helper to wrap the once() Promise instead of using traditional try/catch blocks.

Edit:
I think I’ve found the main issue. In my code, the module I’m using to log on throws an error repeatedly in a certain situation. Normally, this shouldn’t affect my code, since I’m only listening for the loggedOn event. However, it seems that this thrown error is somehow causing the once promise to be skipped or to behave unexpectedly.

This is the code:

import { EventEmitter } from "events";
import { once } from "events";

(async () => {
  const testEvent = new EventEmitter();
  let isConnected = false;
  while (!isConnected) {
    console.log("before await");
    const [error, result] = await catchError(once(testEvent, "loggedOn", { signal: AbortSignal.timeout(10 * 1000) }));
    console.log("after await");
    if (!error) break;
  }
})();

The CatchError Function

function catchError<T, E extends new (message?: string) => Error>(
  promise: Promise<T>,
  errorsToCatch?: E[],
): Promise<[undefined, T], [InstanceType<E>]> {
  return promise
    .then((data) => {
      return [undefined, data] as [undefined, T];
    })
    .catch((error) => {
      if (errorsToCatch === undefined) return [error];
      if (errorsToCatch.some((e) => error instanceof e)) return [error];
      throw error;
    });
}

Simultaneous requests to the same mongoDb document in nest.js application

I have a nest.js application which accepts base64 files in the body to save. Url contains an id of mongoDb document where the information about saved files is stored in files array.

The problem is that around ten save requests with the same id come in simultaneously (all requests in one millisecond):
Request time 2025-06-09T08:39:14.558Z
Request time 2025-06-09T08:39:14.563Z
Request time 2025-06-09T08:39:14.595Z
Request time 2025-06-09T08:39:14.595Z
Request time 2025-06-09T08:39:14.596Z

Ten simultaneous requests like this: “api/application/682c6f32dcc17ab3ac899b83/document/”. As a consequence not all file information is saved in mongoDb.

I have used a setTimeout (with import { randomInt } from ‘crypto’;) and looks like it works but I am sure it isn’t a best solution.

    public async uploadCreditDocuments(externalId: string, request: IUploadClientDocumentsRequest): Promise<IUploadClientDocumentsResponse> {
    const delay = (randomInt(0, 20)) * 1000;

    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(this._uploadCreditDocuments(externalId, request));
        }, delay);
    });
}

Please help me.