problem to add the external script in my js file by CSP

Refused to load the script ‘https://cdn.jsdelivr.net/npm/[email protected]/dist/tesseract.min.js’ because it violates the following Content Security Policy directive: “script-src ‘self’ ‘wasm-unsafe-eval’ ‘inline-speculation-rules’ http://localhost:* http://127.0.0.1:* chrome-extension://3aa17153-bad6-4578-a0d8-fc68e2278d10/”. Note that ‘script-src-elem’ was not explicitly set, so ‘script-src’ is used as a fallback.

is it possible to output the full callstack in nodejs [duplicate]

I am capture the node error info like this:

process.on("uncaughtException", (error, origin) => {
  logger.error("uncaughtException", error, origin);
});

this works fine but I have a issue, the error output like this:

│ [2025-03-26T10:52:17.267] [ERROR] default - uncaughtException Error: connect ECONNREFUSED 10.109.79.31:8000                                                                     │
│     at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1555:16) {                                                                                                         │
│   errno: -111,                                                                                                                                                                  │
│   code: 'ECONNREFUSED',                                                                                                                                                         │
│   syscall: 'connect',                                                                                                                                                           │
│   address: '10.109.79.31',                                                                                                                                                      │
│   port: 8000                                                                                                                                                                    │
│ } uncaughtException

is it possible to output the full call stack? from this error I know there contains an error, but I could not know where is going on or the error come from without full callstack info.

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?