How to correctly serialize java.util.HashSet in Node.js to match existing Java-serialized entries? [closed]

I am working on migrating a Java backend to Node.js, but I only have access to the database, not the original Java source code. One of the columns in the database appears to store serialized java.util.HashSet objects.

I am trying to generate the correct serialized format in Node.js so that new entries match the old ones, but the ones I generate look different from the existing records. Here’s an example of what I get vs. what the database contains:

Old entries (correct format): Properly serialized java.util.HashSet objects.

New entry (my output, incorrect): The structure appears different at the top.

enter image description here

export function serializeSpringBootHashSet(items: number[]): Buffer {
// Magic header for Java serialization
const magicHeader = Buffer.from([
    0xac, 0xed, // STREAM_MAGIC
    0x00, 0x05  // STREAM_VERSION
]);

// Java HashSet class descriptor with potential "°DÄ" appearance
const hashSetClassDesc = Buffer.from([
    0x73, 0x72, // 'sr' (serialized object)
    0x00, 0x13, // Class name length (19 bytes: "java.util.HashSet°D")
    0x6a, 0x61, 0x76, 0x61, 0x2e, 0x75, 0x74, 0x69, 0x6c, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x53, 0x65, 0x74,
    0xc2, 0xb0, // UTF-8 for '°'
    0x44,       // 'D'
    0x12, 0xc4, 0x1a, 0x03, 0x00, 0x00, // Class metadata
    0x78, 0x70 // End of object marker
]);


// Prepare items serialization (same as original)
const serializeItems = items.flatMap(item => {
    return [
        0x73, 0x72, // sr
        0x00, 0x0e, // class name length
        0x6a, 0x61, 0x76, 0x61, 0x2e, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x4c, 0x6f, 0x6e, 0x67,
        0x3b, 0x8b, 0xe4, 0x90, 0xcc, 0x8f, 0x23, 0xdf, 0x02, 0x00, 0x01, 0x4a, 0x00, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
        0x78, 0x72, 0x00, 0x10,
        0x6a, 0x61, 0x76, 0x61, 0x2e, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
        0x86, 0xac, 0x95, 0x1d, 0x0b, 0x94, 0xe0, 0x8b, 0x02, 0x00, 0x00, 0x78, 0x70,
        ...[
            (item >> 56) & 0xFF,
            (item >> 48) & 0xFF,
            (item >> 40) & 0xFF,
            (item >> 32) & 0xFF,
            (item >> 24) & 0xFF,
            (item >> 16) & 0xFF,
            (item >> 8) & 0xFF,
            item & 0xFF
        ]
    ];
});

// Construct the full serialized buffer
const contentBuffer = Buffer.from([
    ...magicHeader,
    ...hashSetClassDesc,
    0x77, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x3f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
    ...serializeItems,
    0x78, 0x70
]);

return contentBuffer;

}

What’s wrong?
The first part of my serialized data does not match the existing ones in the database.

I suspect there is an issue with how I construct the class descriptor (java.util.HashSet).

There may also be an issue with the way I serialize numbers.

Regex failing to validated an url

For a long time I have been using the regex as in this page in my app without any problems but today I tried this url :

https://my3dviewer.visiativ.com/#/publications/617864759

but it didn’t pass the validation using the said regex.

function isUrlValid(str) {
  const pattern = new RegExp(
    '^(https?:\/\/)?' + // protocol
    '((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|' + // domain name
    '((\d{1,3}\.){3}\d{1,3}))' + // OR IP (v4) address
    '(\:\d+)?(\/[-a-z\d%_.~+]*)*' + // port and path
    '(\?[;&a-z\d%_.~+=-]*)?' + // query string
    '(\#[-a-z\d_]*)?$', // fragment locator
    'i'
  );
  return pattern.test(str);
}

const result = isUrlValid('https://my3dviewer.visiativ.com/#/publications/617864759');
console.log('isUrlValid ? : ', result);

What I should change to make the validation test successful ?

Three.js won’t render the scene after clearing it

I haven’t found any post that describes exactly this issue but I’ve noticed it’s kinda hard to delete elements from the scene.

I’m making a house editor, it allows to draw a 2D house and then it generates a 3d version.

If I use the next line or scene.clear() to clear the scene, it won´t render anything else afterwards:

build(layers) {
        let height = 0;

       this.scene.remove.apply(this.scene, this.scene.children);

        layers.forEach(layer => {
            for (let y = 0; y < GRID_SIZE; y++) {
                for (let x = 0; x < GRID_SIZE; x++) {
                    if (layer.grid[y][x] != null) {
                        this.scene.add(layer.grid[y][x].get3DVersion(x, y, height));
                    }
                }
            }
            height += layer.getTotalHeight();
        });        
    }

However, if I empty the scene like this, it continues rendering the scene but it won’t remove all the elements that were deleted in the grid properlty, I have to call build(layers) several times for all of them to be gone:

 this.scene.children.forEach((child) => {
             if (child.isMesh && child !== this.plane) {
                 this.scene.remove(child);
                 child.geometry.dispose(); 
                 child.material.dispose(); 
             }
         });

This is all my Three.js related code:

class HouseBuilder {
    constructor() {
        const section = document.getElementById("threeSection");

        this.scene = new THREE.Scene();
        this.camera = new THREE.PerspectiveCamera(30, 400 / 300, 0.1, 5000);
        this.camera.position.set(25, 25, 50);
        this.camera.lookAt(0, 0, 2.5);

        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setSize(400, 300);
        section.appendChild(this.renderer.domElement);

        const ambientLight = new THREE.AmbientLight(0x404040);
        const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        this.scene.add(ambientLight);
        directionalLight.position.set(5, 10, 5);
        this.scene.add(directionalLight);

        this.addFloor();
        this.animate();
    }

    addFloor() {
        const geometry = new THREE.PlaneGeometry(GRID_SIZE + 5, GRID_SIZE + 5);
        const material = new THREE.MeshStandardMaterial({ color: 0x228b22, side: THREE.DoubleSide });
        this.plane = new THREE.Mesh(geometry, material);
        this.plane.rotation.x = -Math.PI / 2;
        this.scene.add(this.plane);
    }

    animate() {
        requestAnimationFrame(() => this.animate());
        this.renderer.render(this.scene, this.camera);
    }

    build(layers) {
        let height = 0;

        // this.scene.children.forEach((child) => {
        //     if (child.isMesh && child !== this.plane) {
        //         this.scene.remove(child);
        //         child.geometry.dispose(); 
        //         child.material.dispose(); 
        //     }
        // });

       this.scene.remove.apply(this.scene, this.scene.children);

        layers.forEach(layer => {
            for (let y = 0; y < GRID_SIZE; y++) {
                for (let x = 0; x < GRID_SIZE; x++) {
                    if (layer.grid[y][x] != null) {
                        this.scene.add(layer.grid[y][x].get3DVersion(x, y, height));
                    }
                }
            }
            height += layer.getTotalHeight();
        });        
    }
}

get an automatic quote slider to slide

I’m a complete beginner in Javascript and I’m trying to integrate a slider for a website without a plugin, where the background is fixed and only text quotes slide in and out automatically.

I have used Javascript code as a basis, which I have found several times at W3Schools and where the automatic change works perfectly. The only thing I would have liked to add is the slide function. However, I have no idea how to integrate it. Can someone perhaps help me? Here is my link to Codepen: Codepen

HTML:

`<div class="referenzen">
   <div class="mySlides">
    <div class="carousel-caption">
      <h3>„Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut laaliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.“</h3><br>
      <p>Martha Musterfrau</p>
    </div>
  </div>

  <div class="mySlides">
    <div class="carousel-caption">
      <h3>„ Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit aiam nonumy eirmod tempor invidunt ut, sed diam voluptua. At vero eos “</h3><br>
      <p>Max Mustermann</p>
    </div>
  </div>

  <div class="mySlides">
    <div class="carousel-caption">
      <h3>„et accusam et justo duo dolores et ea rebum. Stet clita kasd guberg ipsum dolor sit aiam nonumy eirmren, no sea takimata sanctus est Lorem ipsum dolor sit amet.“</h3><br>
      <p>Martina Musterfrau</p>
    </div>
  </div>
</div>
  <br>

  <div class="slideNav" style="text-align:center">
    <a class="prev" onclick="plusSlides(-1)">&#10094;</a>
    <span class="dot" onclick="currentSlide(1)"></span>
    <span class="dot" onclick="currentSlide(2)"></span>
    <span class="dot" onclick="currentSlide(3)"></span>
    <a class="next" onclick="plusSlides(1)">&#10095;</a>
  </div>`

CSS

`.referenzen{
height: 500px;
width: 100%;
background-image: url("https://lektorat-mira.de/wp-content/uploads/2021/12/AdobeStock_175286368-scaled.jpeg");
background-size: contain;
background-position: right bottom;
background-repeat: no-repeat;
line-height: 250%;
}

.dot, .slideNav a{
    height: 10px;
    width: 10px;
    float: left;
    display: block;
    margin: 0 10px;
    cursor: pointer;
}

.slideNav{
    width: 200px;
    margin: auto;
margin-bottom: 50px;
}

.dot{
    background-color: #008b93;
    opacity: 15%;
    border-radius: 10px;
}

.dot.aktiv{ background-color: #008b93; 
    opacity: 100%;}

@media( min-width: 1000px ) {
.carousel-caption{ 
display: block;
    position: absolute;
text-align: center;
font-family: Baskerville, "Palatino Linotype", Palatino, "Century Schoolbook L", "Times New Roman", "serif";
color: #008b93;
font-size: 30px;
padding: 100px 300px 0 300px;
}
}

@media( max-width: 1000px ) {
.carousel-caption{ 
display: block;
    position: absolute;
text-align: center;
font-family: Baskerville, "Palatino Linotype", Palatino, "Century Schoolbook L", "Times New Roman", "serif";
color: #008b93;
font-size: 30px;
padding: 100px 50px 0 50px;
    overflow: hidden;
    transition: bottom 500ms ease-in;
}
}`

JS

`var slideIndex = 1;
showSlides(slideIndex);

var timer;

function plusSlides(n) {
showSlides(slideIndex += n);
}

function currentSlide(n) {
showSlides(slideIndex = n);
}

function showSlides(n) {
if (timer) {
clearTimeout(timer);
}

var x;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("dot");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (x = 0; x < slides.length; x++) {
slides[x].style.display = "none";
}
for (x = 0; x < dots.length; x++) {
dots[x].className = dots[x].className.replace(" aktiv", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " aktiv";
timer = setTimeout( function(){ plusSlides(1); }, 5000 );
}`

How to enable tab switch in Golden Layout

Im using golden layout with some containers in it, in my app there is an edit mode that permise the user to edit and resize the containers, when the user finish to modify he click “end edit” and the containers cannot be moved or resized, but if two container are part of the same space in edit mode you can switch tab to change what container you want to see, but when The Edit mode finish the tab cannot change


function initializeGoldenLayout() {
    try {
        console.log("Starting GoldenLayout initialization...");

        // Configurazione del layout
        const config = {
            settings: {
                showPopoutIcon: false,
                showMaximiseIcon: false,
                showCloseIcon: false,
                selectionEnabled: true
            },
            dimensions: {
                borderWidth: 5,
                minItemHeight: 100,
                minItemWidth: 100
            },
            content: [{
                type: 'row',
                content: [{
                    type: 'column',
                    content: [
                        {
                            type: 'row',
                            height: 40,
                            content: [
                                createComponentConfig(panelConfigs.videoList),
                                createComponentConfig(panelConfigs.miniatures),
                                createComponentConfig(panelConfigs.stats)
                            ]
                        },
                        {
                            type: 'row',
                            height: 60,
                            content: [
                                createComponentConfig(panelConfigs.fullscreen),
                                createComponentConfig(panelConfigs.events)
                            ]
                        }
                    ]
                }]
            }]
        };

        const container = document.getElementById('layout-container');
        if (!container) {
            console.error('Container not found for GoldenLayout');
            fallbackToSimpleLayout();
            return;
        }

        // Distruggi l'istanza precedente se esiste
        if (glLayout) {
            try {
                glLayout.destroy();
                glLayout = null;
                console.log("Destroyed existing GoldenLayout instance");
            } catch (e) {
                console.warn("Error destroying previous GoldenLayout:", e);
            }
        }

        glLayout = new GoldenLayout(config, container);

        // Registrazione dei componenti - IMPORTANTE: deve avvenire prima di init()
        registerGoldenLayoutComponents();

        // Evento emesso quando il layout è pronto
        glLayout.on('initialised', function () {
            console.log('GoldenLayout inizializzato con successo');
            layoutInitState.glInitialized = true;

            // Ritardo per permettere a GoldenLayout di renderizzare completamente
            setTimeout(function () {
                initializeGridStack();
                checkAndInitialize(); // Verificare lo stato dopo l'inizializzazione
            }, 300);

            isPageLoaded = true;
        });

        // Inizializza il layout
        console.log("Calling glLayout.init()...");
        try {
            glLayout.init();
            console.log("GoldenLayout initialization completed successfully");
        } catch (e) {
            console.error("Error during glLayout.init():", e);
            throw e;
        }

        // Gestione del ridimensionamento con debounce
        const resizeDebounce = debounce(function () {
            if (glLayout && layoutInitState.glInitialized) {
                try {
                    glLayout.updateSize();
                } catch (error) {
                    console.error('Errore durante updateSize:', error);
                }
            }
        }, 100);

        window.addEventListener('resize', resizeDebounce);
    } catch (error) {
        console.error('Errore nell'inizializzazione di GoldenLayout:', error);
        fallbackToSimpleLayout();
    }
}

function registerGoldenLayoutComponents() {
    if (!glLayout) {
        console.error("Cannot register components: glLayout is null");
        return false;
    }

    try {
        console.log("Registering GoldenLayout components...");

        // Componente lista video
        glLayout.registerComponent('videoList', function (container, state) {
            console.log("Creating videoList component");
            const element = $('#videoList-template').clone().removeAttr('id');
            container.getElement().html(element);

            // Aggiorna il titolo con la traduzione corrente
            container.setTitle(dictionary['menuListaVideo'][currentLanguage] || 'Canali');
        });

        // Componente miniature video
        glLayout.registerComponent('miniatures', function (container, state) {
            console.log("Creating miniatures component");
            const element = $('#miniatures-template').clone().removeAttr('id');
            container.getElement().html(element);

            // Aggiorna il titolo con la traduzione corrente
            container.setTitle(dictionary['menuMiniature'][currentLanguage] || 'Live');

            container.on('open', function () {
                console.log('miniatures container opened');
                isGridReinitializing = true;

                setTimeout(function () {
                    try {
                        initializeGridStack();

                        // Controlla se dobbiamo ripristinare i video
                        if (grid && grid.engine && grid.engine.nodes.length === 0) {
                            const currentLayoutName = getCurrentLayoutName();
                            const miniatures = layouts[currentLayoutName]?.miniatures;

                            if (miniatures && Object.keys(miniatures).length > 0) {
                                console.log("Grid is empty but layout has miniatures, restoring...");
                                restoreVideoMiniatures(miniatures);
                            }
                        }
                    } catch (e) {
                        console.error("Error initializing grid after container open:", e);
                    } finally {
                        setTimeout(() => {
                            isGridReinitializing = false;
                        }, 500);
                    }
                }, 300);
            });

            // eventi di resize
            let resizeTimeout;
            container.on('resize', function () {
                if (grid) {
                    isGridReinitializing = true;

                    // Cancella eventuali timeout precedenti
                    clearTimeout(resizeTimeout);

                    // Imposta un nuovo timeout
                    resizeTimeout = setTimeout(() => {
                        try {
                            updateGridSize();
                        } finally {
                            isGridReinitializing = false;
                        }
                    }, 300);
                }
            });
        });

        // Componente statistiche/trascrizioni
        glLayout.registerComponent('stats', function (container, state) {
            console.log("Creating stats component");
            const element = $('#stats-template').clone().removeAttr('id');
            container.getElement().html(element);

            // Aggiorna il titolo con la traduzione corrente
            container.setTitle(dictionary['metadata'][currentLanguage] || 'Trascrizioni');

            container.on('open', function () {
                console.log('stats opened');
                changeMetadataLanguage($('#selezionaLingua').val());
            });
        });

        // Componente video a schermo intero
        glLayout.registerComponent('fullscreen', function (container, state) {
            console.log("Creating fullscreen component");
            const element = $('#fullscreen-template').clone().removeAttr('id');
            container.getElement().html(element);

            // Aggiorna il titolo con la traduzione corrente
            container.setTitle(dictionary['videoPlayer'][currentLanguage] || 'Video Player');

            container.on('open', function () {
                console.log('fullscreen opened');
            });
        });

        // Componente eventi
        glLayout.registerComponent('events', function (container, state) {
            console.log("Creating events component");
            const element = $('#events-template').clone().removeAttr('id');
            container.getElement().html(element);

            // Aggiorna il titolo con la traduzione corrente
            container.setTitle(dictionary['eventi'][currentLanguage] || 'Eventi');

            container.on('open', function () {
                console.log('events opened');
            });
        });

        isComponentsRegistered = true;
        console.log("GoldenLayout components registered successfully");
        return true;
    } catch (error) {
        console.error('Errore nella registrazione dei componenti:', error);
        return false;
    }
}

Chrome/Edge crashing with error code: STATUS_BREAKPOINT. Only happens when debugging a specific “for of” loop

I’m having an issue with some code I’m trying to debug in Chrome/Edge. I think it’s probably a bug, as it isn’t happening with Firefox. I’ve managed to create a small test file that is causing others to experience the same issue. The code will run fine without debugging, it only crashes when you step through it. Weirdly, it only happens when I use a “for of” loop. A standard for loop, or the array’s forEach function work fine.

My version of Chrome is: 134.0.6998.178 (Official Build) (64-bit)

enter image description here

This is the code causing the crash:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chrome Crash Test</title>
</head>
<body>
    <script>
        class Test {
            constructor() {
                // When this code is ran without debugging, it will work fine and print out two objects and a message.
                // When it is ran with the debugger attached, it will crash the browser with error code "STATUS_BREAKPOINT" once you press Step Over
            
                debugger;
                
                // when debugger is over this line, press F10 and it will crash the browser if the "for of" loop is left in
                const items = [{
                    canDrop: function () {
                        console.log(this);
                    }
                }];
                
                // if the for of loop is used, it will crash
                for (const item of items) {
                    const myFunc = () => item.canDrop.call(this);
                    myFunc();
                }

                // if the for loop is used instead, it will not crash
                for (let i = 0; i < items.length; i++) {
                    const item = items[i];
                    const myFunc = () => item.canDrop.call(this);
                    myFunc();
                }
                
                console.log('The code has ran');
            }
        }

        var test = new Test();
    </script>
</body>
</html>

The JS in inline for ease of testing in a single file. You can either copy the HTML into a .html or just open the debugger to test.

Can anyone see anything inherently wrong with what I’ve done? Or is it likely a bug in the browser?

JS send ping async and report

i am trying to ping a group of ip addresses whether it is up or down . For the purpose i am using 3rd party NODE-PING (npm i ping) library. i have a group of ip blocks as it is below.

const hosts = [
    {
        type: 'office',
        block: '192.1.2',
    },
    {
        type: 'station',
        block: '192.1.3',
    }
]

and i have got another list which includes last part of ip address as below again.

const controlList = [
    {
        type: 'camera',
        end: '100'
    },

    {
        type: 'printer',
        end: '98'
    }
]

when i use async await syntax in for loops pings wait lots of time for each to process. but whenever i turn to .then() notation it responses faster.

(async function sendPing(hosts,controlList){
    for (const host of hosts) {
        for (const clist of controlList) {

            ping.promise.probe(host.block + '.' + clist.end).then(function(res){
                console.log(res.inputHost, res.alive);
            })
        }
    }
})(hosts,controlList);

i am trying to run code faster as it runs with .then notation.

Clearing text and checkboxes on spawned PDF page

I have a PDF document that I’ve created which has a large number of text and check boxes on what will start out as a single page.

My ultimate aim is to be able to click a button and have the same page spawned, but with all the text boxes cleared of any text, and all the checkboxes unclicked. It should not affect the other page(s).

I have tried:

Attempt 1

Creating a template page with cleared textboxes / checkboxes. I could then add the following Javascript to a ‘new page’ object, before then hiding the template page so it was always blank:

var newPage = this.spawnPageFromTemplate({ 
    cTemplate: this.getNthTemplate(0), 
    bRename: true,  
    bOverlay: false
});

For some reason this doesn’t create all the textboxes on the new page, so I had to abandon this approach.

Attempt 2

Keeping the first page as the template page and keeping it unhidden.
When using the same code above, this now ensures that all text boxes are created for some reason.

However, when the user populates the first page and then spawns another, it will copy whatever text / checkboxes that they put into the first page.
I therefore need to add code that removes all of the text boxes / clicked checkboxes, but ONLY for the newly created page (not any others).

I tried the following code, but I am well out of my depth here.

var newPage = this.spawnPageFromTemplate({ 
    cTemplate: this.getNthTemplate(0),  
    bRename: true,  
    bOverlay: false
});

// Get the page's field names and reset based on the prefix
var aNameParts = event.targetName.split(".");
var strPrefix = aNameParts[0] + "." + aNameParts[1];
this.resetForm(strPrefix);

It doesn’t work…

Does anyone have any ideas as to how I could get this to work?

Thanks in advance,

Phil

Hooking into / providing a callback for vite production builds?

When vite builds bundles for production it postfixes a random identifier to the end of the bundle name.

When we publish bundles to npm that use the main property package.json to indicate the bundle file ( So that the UNPKG CDN can be used) we have to update this property each time we want to publish.

Does vite have a way to hook into the build with a callback function that that can be run to update the main property with the new bundle file name?

It’s possible to just make the bundle name fixed, but that has some drawbacks as discussed here.

In this example, am I using NextJS’s extension to WebAPI’s fetch or the standard WebAPI fetch?

In this example, am I using NextJS’s (14.2.24) server-side extension to WebAPI’s fetch or the standard WebAPI fetch, specifically relating to the use of the cache property? Am I referring to NextJS’s cache or the browser’s http cache?

// actions.ts

"use_server"

export const callApi = async (
  endpoint: string,
  method: Method = Method.GET,
  body?: any
) => {
  const url = `${process.env.API_BASE_URL}${process.env.API_LIB}${endpoint}`;
  let token = cookies().get("session")?.value;

  let response = await fetch(url, {
    method: method,
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
    body: body && JSON.stringify(body),
    cache: 'no-store'
  })

  // ... continues
}

export async function addEmployeesToGroup(ids: string[]) {
  const add = await api(`/add-employees`, Method.POST, {
    employees: ids,
  });
  // ... continues
  return add;
}

// client component (extract)

export default function AddEmployees() {
  const add = async () => {
    const employeeIds = ["7pUs0hAW6Y", "LpQqi4mhbH"]; // for example
    const response = await addEmployeesToGroup(employeeIds);
    // ... continues
  };
  return <button onClick={add}>Add employees</button>;
}

How to Implement historyApiFallback Rewrites in Vite?

I’m migrating a project from Webpack to Vite and trying to replicate this Webpack devServer configuration:

historyApiFallback: {
    rewrites: [
        {
            from: new RegExp('^' + appConfigs.managerContextPath + '.*$'),
            to: appConfigs.contextPath + 'manager.html'
        },
        {
            from: new RegExp('^' + appConfigs.contextPath + '.*$'),
            to: appConfigs.contextPath + 'index.html'
        }
    ]
}

I attempted the following Vite configuration:

export default defineConfig({
    root: path.resolve(__dirname, 'src'),
    base: '/',
    plugins: [
        react(),
    ],
    // appType: 'custom', // This ensures we're not handling HTML automatically
    build: {
        sourcemap: true,
        outDir: resolve(__dirname, 'bundles'),
        rollupOptions: {
            input: {
                app: resolve(__dirname, 'src/app.html'),
                arm: resolve(__dirname, 'src/arm.html'),
            }
        }
    },
});

With this, I can open /app and /arm, but navigating to /app/login results in a “No webpage found” error.
What I Need:
I want Vite to behave like Webpack’s historyApiFallback, ensuring:

/app loads app.html,
/arm loads arm.html,

Any subroutes like /app/login should still serve app.html

Any subroutes like /arm/settings should serve arm.html.

My Research:

I’ve looked into Vite’s server options, specifically server.middlewareMode, but I’m not sure how to properly rewrite requests for different contexts.
Has anyone done something similar in Vite? How can I configure Vite’s dev server to handle this kind of routing logic??

I tried using a plugin for fallback, but when I do that, it just opens the raw HTML file and completely ignores my React app like it doesn’t hydrate or run the JS bundle. So the plugin approach doesn’t work for what I need, i’m looking for a proper solution that works with the actual built react app in production
And here’s a runnable example:

https://stackblitz.com/edit/stackblitz-webcontainer-api-starter-d6nv6g9e?file=README.md

discussion on vite github https://github.com/vitejs/vite/discussions/1968

Google reCPATCHA validation fails

A few days ago I implemented Google’s recpatcha into my website. It worked perfectly fine.

Today I started working then I though to myself: “Hmm lets try the contact form (where i use the cpatcha) if it still works.

Then I got this error in my console:
Hiba: SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

There is no syntax error in the code. All of this worked a few days ago and since then I didn’t touch it.

I tried these steps:

1: I fully reverted today’s work with git. (didnt work)

2: I though i maybe got blacklisted in the recpatcha or something. So I made a new account with new keys, etc… (didnt work)

What can be the problem? Google’s reCAPTCHA is down?

How to build a static website with NextJs

I’m having an issue while trying to build a static website created with Next.js. The out folder is not being generated.

I think the problem is related to the SSR part of Next.js. Although it’s a small website, I am using dynamic routes, which are SSR-based. To resolve this, I tried creating a server-side component and passing the params to the actual client-side component that I wanted to render.

Here’s the current structure:

In the [id] folder, I have a file called page.tsx with the following code:

import { projects } from '@/data/projects';
import ProjectPage from './ProjectPage';

export const generateStaticParams = async () =>
  projects.map((project) => ({
    id: project.id,
  }));

const fetchProjectData = async (id: string) => {
  const project = projects.find((p) => p.id === id);
  return project ?? null;
};

const Project = async ({ params }: { params: { id: string } }) => {
  const project = await fetchProjectData(params.id);

  if (!project) {
    return (
      <div className='w-full h-[100vh] flex justify-center items-center text-5xl font-bold'>
        Project{' '}
        <span style={{ color: 'var(--primary)', margin: '0 10px' }}>not</span>{' '}
        found
      </div>
    );
  }

  return <ProjectPage project={project} />;
};

export default Project;

In the same folder, I also have another file called ProjectPage.tsx, which is a client-side component:

'use client';

const ProjectPage = ({ project }: ProjectPageProps) => {
    ...
};

I added output: ‘export’, in the next.config.ts file.

However, after running npx next build, I received the following output:

$ npx next build
  ▲ Next.js 14.2.26

   Creating an optimized production build ...
 ✓ Compiled successfully
 ✓ Linting and checking validity of types    
 ✓ Collecting page data    
 ✓ Generating static pages (11/11)
 ✓ Collecting build traces    
 ✓ Finalizing page optimization

Route (app)                              Size     First Load JS
┌ ○ /                                    29.3 kB         168 kB
├ ○ /_not-found                          875 B            88 kB
├ ○ /contact                             4.49 kB        99.9 kB
├ ○ /projects                            548 B          94.5 kB
└ ● /projects/[id]                       3.32 kB         143 kB
    ├ /projects/1
    ├ /projects/2
    ├ /projects/3
    └ /projects/4
+ First Load JS shared by all            87.2 kB
  ├ chunks/117-057d17d2e788cd74.js       31.6 kB
  ├ chunks/fd9d1056-f1963c9e20a75983.js  53.7 kB
+ First Load JS shared by all            87.2 kB
  ├ chunks/117-057d17d2e788cd74.js       31.6 kB
+ First Load JS shared by all            87.2 kB
+ First Load JS shared by all            87.2 kB
  ├ chunks/117-057d17d2e788cd74.js       31.6 kB
  ├ chunks/fd9d1056-f1963c9e20a75983.js  53.7 kB
  └ other shared chunks (total)          1.9 kB
+ First Load JS shared by all            87.2 kB
  ├ chunks/117-057d17d2e788cd74.js       31.6 kB
  ├ chunks/fd9d1056-f1963c9e20a75983.js  53.7 kB
+ First Load JS shared by all            87.2 kB
+ First Load JS shared by all            87.2 kB
+ First Load JS shared by all            87.2 kB
  ├ chunks/117-057d17d2e788cd74.js       31.6 kB
+ First Load JS shared by all            87.2 kB
+ First Load JS shared by all            87.2 kB
  ├ chunks/117-057d17d2e788cd74.js       31.6 kB
  ├ chunks/fd9d1056-f1963c9e20a75983.js  53.7 kB
  └ other shared chunks (total)          1.9 kB


○  (Static)  prerendered as static content
●  (SSG)     prerendered as static HTML (uses getStaticProps)

Has anyone encountered a similar issue with Next.js?

Generate a PDF with Table of Contents from HTML using Paged.js

I have read the documentation.

I have tried the sample code.

The command I used to generate the pdf is pagedjs-cli index.html -o index.pdf

The code is:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.18">
<title>Salah</title>
<style>
/* Page Margins */
@page {
    size: A4;
    font-size: 18px;
}

/* Verso (left) page-specific */
@page :left {
    margin-left: 0.79in;
    margin-right: 0.59in;

    @bottom-left {
        /* content: "Page " counter(page) " of " counter(pages); */
        content: counter(page);
        text-align: left;
        margin-left: .1in; /* abs(margin-left - margin-right) / 2 */
    }
}

/* Recto (right) page-specific */
@page :right {
    margin-left: 0.59in;
    margin-right: 0.79in;

    @bottom-right {
        /* content: "Page " counter(page) " of " counter(pages); */
        content: counter(page);
        text-align: right;
        margin-right: .1in; /* abs(margin-left - margin-right) / 2 */
    }
}

.sect1 {
    page-break-after: always;
}

/* Use it using [.pagebreak] */

.pagebreak {
    page-break-before: always;
}

@page clean {
    @bottom-right {
        content: none;
    }

    @bottom-left {
        content: none;
    }
}

/* Use it using pass:pass:[<div class="counter-reset"></div>] */
.counter-reset {
    counter-reset: page 1;
    /* counter-increment: page 1; */
}

/* Use it using pass:[<div class="blank-page"></div>] */
.blank-page {
    page-break-before: always;
    page: clean;
    display: none;
}

/* Add this to your counter-reset class */
.counter-reset {
    counter-reset: page 1;
}
</style>
</head>
<body class="book">
<div id="header">
<h1>Salah</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div id="my-toc-content"></div>
</div>
</div>
<div class="sect1">
<h2 id="_what_to_say_after_the_takbir">What to say after the Takbir</h2>
<div class="sectionbody">

</div>
</div>
<div class="sect1">
<h2 id="_invocation_in_bowing_and_prostrations">Invocation in Bowing and Prostrations</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_this_is_the_third">This is the third</h3>
<script>
function createToc(config) {
  const content = config.content;
  const tocElement = config.tocElement;
  const titleElements = config.titleElements;

  let tocElementDiv = content.querySelector(tocElement);
  let tocUl = document.createElement("ul");
  tocUl.id = "list-toc-generated";
  tocElementDiv.appendChild(tocUl);

  // add class to all title elements
  let tocElementNbr = 0;
  for (var i = 0; i < titleElements.length; i++) {
    let titleHierarchy = i + 1;
    let titleElement = content.querySelectorAll(titleElements[i]);

    titleElement.forEach(function (element) {
      // add classes to the element
      element.classList.add("title-element");
      element.setAttribute("data-title-level", titleHierarchy);

      // add id if doesn't exist
      tocElementNbr++;
      idElement = element.id;
      if (idElement == "") {
        element.id = "title-element-" + tocElementNbr;
      }
      let newIdElement = element.id;
    });
  }

  // create toc list
  let tocElements = content.querySelectorAll(".title-element");

  for (var i = 0; i < tocElements.length; i++) {
    let tocElement = tocElements[i];

    let tocNewLi = document.createElement("li");

    // Add class for the hierarcy of toc
    tocNewLi.classList.add("toc-element");
    tocNewLi.classList.add(
      "toc-element-level-" + tocElement.dataset.titleLevel
    );

    // Keep class of title elements
    let classTocElement = tocElement.classList;
    for (var n = 0; n < classTocElement.length; n++) {
      if (classTocElement[n] != "title-element") {
        tocNewLi.classList.add(classTocElement[n]);
      }
    }

    // Create the element
    tocNewLi.innerHTML =
      '<a href="#' + tocElement.id + '">' + tocElement.innerHTML + "</a>";
    tocUl.appendChild(tocNewLi);
  }
}

class handlers extends Paged.Handler {
    constructor(chunker, polisher, caller) {
      super(chunker, polisher, caller);
    }

    beforeParsed(content) {
      createToc({
        content: content,
        tocElement: "#my-toc-content",
        titleElements: ["h2", "h3"],
      });
    }
  }
  Paged.registerHandlers(handlers);

</script>
</div>
</div>
</div>
</div>
</body>
</html>

It gives me the page numbers but does not give me the table of content. How can I create the table of content.

receiving [object object] instead of mongodb object id (react, typeScript)

I am trying to disply doucuments to the user, everything is working propertly exept the objectId of the mongodb doucument.
enter image description here
as you can see I can see it as [object object] instead of the actual id string.
I found out that I should use JSON.stringfy but that didnt work (it just put “” around the [object object]).
this is the components where I disply the doucuments:

function Show() 
{
    let groups = useLoaderData()
    let updated_groups = groups?.map((cardData: any, index: Key | null | undefined) => (
      <div key={index} className="card">
        <p>Id: {JSON.stringify(String(cardData._doc._id))}</p>
        <p>name: {JSON.stringify(cardData._doc.name)}</p>
        <p>groups: {JSON.stringify(cardData._doc.groups_part)}</p>
        <p>peoples: {JSON.stringify(cardData._doc.peoples_part)}</p>
        <p>parent: {JSON.stringify(cardData._doc.group_parent)}</p>
      </div>
    ))
  return (
    <div>
      {updated_groups}
    </div>
  );
}

this is my loader:

export async function loader()
{
    return groups_controller.controller_group_everyone()
}

controller_group_everyone() just does the mongodb find method and returns the doucuments as an array

I want to disply the mongo objectId as a string in the browser.

every google link I found about this issue says to use json,stringfy.
am I using it wrong or is there any other problem??

(I dont know if this helps but I am recieving this issue as well that is maybe related: “Uncaught Error: Hydration failed because the server rendered HTML didn’t match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:

  • A server/client branch if (typeof window !== 'undefined').
  • Variable input such as Date.now() or Math.random() which changes each time it’s called.
  • Date formatting in a user’s locale which doesn’t match the server.
  • External changing data without sending a snapshot of it along with the HTML.
  • Invalid HTML tag nesting.

It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.”)

Id: {JSON.stringify((cardData._doc._id).toString())}

returns: “[object Object]”

Id: {JSON.stringify((cardData._doc._id))}

return buffer ({“buffer”:{“0″:103,”1″:227,”2″:185,”3″:253,”4″:70,”5″:96,”6″:29,”7″:90,”8″:8,”9″:38,”10″:181,”11”:247}})

Id: {(cardData._doc._id).toString()}

returns: [object Object]