Pending promise stored as property in object array, do not know how to access to fulfill

I’m trying to fill an array of objects with specific property values and am using Promises with async/await with Javascript in a Node.JS environment. Here is the main part:

getPublicNotes(connectHeaders, baseurl, pubKey, noteKeyList).then((nkl) => {
    if (nkl.length > 0) {
        getSecurityAbEntry(connectHeaders, baseurl, nkl);
        for (let count = 0; count < nkl.length; count++) {
            let secGroupKey = getSecurityAbEntry(connectHeaders, baseurl, nkl[count]);
            nkl[count].writeAccessKey = secGroupKey;
        }
    } else {
        console.log("EMPTY: There are no Public Notes; nothing to process.");
    }
    /* for (let count2 = 0; count2 < nkl.length; count2++) {
        let notesSecGroup = setNoteSecurity(connectHeaders, baseurl, nkl[count2]); 
        console.log(notesSecGroup);
    } */
});

noteKeyList is an array of objects, initially empty.
getPublicNotes(...noteKeyList) is an async function that returns an array of objects within a Promise.
getSecurityAbEntry(...nkl[count]) is an async function that takes in a single object and returns a single writeAccessKey value within a Promise. At the end of the for loop, the noteKeyList array looks like this:

[
{
abEntryKey: 'abc124der',
noteKey: '098ert'
writeAccessKey: Promise { <pending> }
},
{
abEntryKey: 'def321red',
noteKey: '392tkf'
writeAccessKey: Promise { <pending> }

},
{
abEntryKey: 'ghi645green',
noteKey: '9384fds'
writeAccessKey: Promise { <pending> }
},
...
]

How do I use then() to access each objects’ writeAccessKey property?

The setNoteSecurity() is what I want to use next on each object in the array but don’t know how to dig into each object in the array to feed into this async function.

Suggestions?

PS: I can give you the contents of each async function but I figure I’ll start with this in case it’s the functions’ contents is not necessary.

/usr/bin/chromium-browser NOENT error arises when calling puppeteer.launch

I am working on a project with Nest.js with a feature to generate PDF document. I am using puppeteer library to generate the PDF by the API https://pptr.dev/api/puppeteer.page.pdf

It works well locally with the docker OS as Ubuntu. The chromium path I set is /usr/bin/chromium-browser.

However, when I deploy to production with docker OS as node:20.18, seems like the setting does not work as /usr/bin/chromium-browser NOENT error is found in the log.

The codes to initiate the puppeteer browser:

export class BrowserService implements OnModuleInit, OnModuleDestroy {
    private browser: puppeteerCore.Browser | Browser;

    async onModuleInit() {
        if (this.browser) return;
        const puppeteer = process.env.NODE_ENV === 'local' ? puppeteerFull : puppeteerCore;
        this.browser = await puppeteer.launch({
            executablePath: process.env.NODE_ENV === 'local' ? puppeteer.executablePath() : '/usr/bin/chromium-browser',
            headless: true,
            args: ['--no-sandbox', '--disable-setuid-sandbox'],
        });
    }

    getBrowser() {
        return this.browser;
    }
}

The nest application server log shows the NOENT error as below:

Error: Failed to launch the browser process! spawn /usr/bin/chromium-browser ENOENT
TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
at onClose (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:299:20)
at ChildProcess.<anonymous> (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:293:24)
at ChildProcess.emit (node:events:519:28)
at ChildProcess.emit (node:domain:488:12)
at ChildProcess._handle.onexit (node:internal/child_process:292:12)
at onErrorNT (node:internal/child_process:484:16)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
WARN received SIGTERM indicating exit request
INFO waiting for 01-node_00, 02-java_00 to die
WARN stopped: 02-java_00 (exit status 143)
WARN stopped: 01-node_00 (terminated by SIGTERM)

Anyone has idea how to fix this issue?

The difference on docker OS is the only reason I can think of. Appreciate if anyone can give me some guidance.

Run function on whichever element was clicked

Let’s say I have multiple buttons which each have a .btn-swatch class. When any of them is clicked, I want to act on the one that was clicked. So far, I can just figure out how to act on a specific element from the array.

const swatchBtn = document.getElementsByClassName('btn-swatch');

swatchBtn.item(1).addEventListener("click", function (e) {
  const swatchColor = e.target.getAttribute('data-color');
  const selectedEl = document.querySelector('[data-selected]');
  selectedEl.classList.add(swatchColor);
});

Browser-based “one dimensional” pan/zoom for large image

I would like to display a very large PNG image (height about 1 million pixels, width only a few hundred pixels) in the browser in such a way that users can pan and zoom it. The image would be too much to handle for the browser. So I want to cut it into smaller tiles. Basically like OpenStreetMap, Apple/Google Maps etc. do.

The special thing here is that the image must only be zoomed and scrolled along the Y-axis. The X-axis should always remain the same, i.e. its scaling must not change and it must not be panned. (The image is will be “compressed” vertically when zooming out.)

I don’t necessarily want to reinvent the wheel (i.e. roll my own implementation with a canvas element and JavaScript) and wonder if there is a ready-made solution for this problem somewhere. With Leaflet and OpenSeadragon I have not found any option to restrict zoom and pan to one axis.

Why is window not defined in NextJs 14 useEffect? [duplicate]

I’m having a hard time not seeing this simply as a NextJS bug and want to hear what others think.

Let’s assume that “myFunction” is a third party script loaded in at the top level app/layout file. I’ve checked in browser console that indeed it loads in correctly.

If I place window?.myFunction in as a dependency to this useEffect, we get a “window is not defined” error. Why? I understand that NextJS “pre renders” on server side, despite this being a client file. According to that logic, useEffect really should be ignored on the server side in the first place, AND even if it wasn’t ignored, shouldn’t window?. be checking that the object exists in the first place anyways and at the very least not error out?

Further confusion: the “setIsClient” is kind of ridiculous, but I have placed a debugger statement on the conditional inside of the useEffect, and on the 2nd time it fires, when the “isClient” variable is “true”, window is still undefined. I would assume that by the time we’re on the client side, and our setIsClient has finished firing, window should be defined by then…

"use client";
import { useEffect, useState } from "react";

export default function MyPage() {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    // Set the isClient flag to true once the component is mounted
    setIsClient(true);
  }, []);

  useEffect(() => {
    if (isClient && typeof window !== "undefined" && window?.myFunction) {
      window.myFunction(
        "track",
        12345,
      );
    }
  }, [isClient]);

Appreciate any help. Using NextJS 14.2.15

Vercel Auto redirect error after deployment

so i have this application made with next js 14 that i deployed on vercel but i’m facing a problem that i can’t understand from where it comes , the build went well and everything works greate without any error when i use vercel random generated websites but once i enter to the same project using my custom domain once i start scrolling at first i’m hiding the navbar and i’m having a section where the data is retrieved from mysql server i don’t now exactly which one is responsable about that but once i scroll a little bit the page is redirected automatically to the page /Dashboard that i don’t have at all on my project .

i tried building the app locally and it works fine , i also tried to use it on the phone with the same website and it works fine too , but when i try on my laptop it doesn’t work properly error.
the good is simple and i don’t know if its the reason i think its releated to the custom domain or some settings on the vercel deployment options , if any one had the same problem before please help me.

How do I wait for data from network request, before returning JSX in a functional component? (React) [duplicate]

I need to display JSX that depends on data from a network request. In my first attempt, the return statement was hit before the network request resolved

const showSubscriptions = () => {
  const [methods, setMethods] = useState([]);
  let subscriptionsRef = React.useRef({})

  useEffect(() => {
    const getCommunicatorMethods = async () => {
      const { data } = await axios.get(
        "/api/get_communicator_methods",
      );

      const routingKeys = await axios.get("api/get_routing_keys")
      let routingKeysString = JSON.stringify(routingKeys.data)
      let detections = routingKeysString.includes('Detection')
      let zones = routingKeysString.includes('Zone')
      let sensors = routingKeysString.includes('Sensor')
      let notifications = routingKeysString.includes('Notification')
      let system_configurations = routingKeysString.includes('SystemConfiguration')
      let alerts = routingKeysString.includes('Alert')

      subscriptionsRef.current = { 'subscribe_to_sensors': sensors, 'subscribe_to_zones': zones, 'subscribe_to_alerts': alerts, 'subscribe_to_notifications': notifications, 'subscribe_to_detections': detections, 'subuscribe_to_system_configurations': system_configurations }

      console.log(subscriptionsRef.current)
      setMethods([...Object.values(data)]);
    };

    console.log(subscriptionsRef.current) //[methods[0][0]]
    getCommunicatorMethods();
  }, []);

  return methods
    .filter((x) => x[0].includes("subscribe"))
    .map((method) => (
      <div key={method[0]}>
        <span>{method[0].replaceAll("_", " ")}</span>
        <Switch value={subscriptionsRef.current[method[0]]} onChange={handleChange(method[0])} />
      </div>
    ));
};

Then I tried making the fn async so I can wait on the network request (I also had to get rid of the useEffect() so that await is at the top-level within the async function):

const showSubscriptions = () => {
  const [methods, setMethods] = useState([]);
  let subscriptionsRef = React.useRef({})

  const getCommunicatorMethods = async () => {
    const { data } = await axios.get(
      "/api/get_communicator_methods",
    );

    const routingKeys = await axios.get("api/get_routing_keys")
    let routingKeysString = JSON.stringify(routingKeys.data)
    let detections = routingKeysString.includes('Detection')
    let zones = routingKeysString.includes('Zone')
    let sensors = routingKeysString.includes('Sensor')
    let notifications = routingKeysString.includes('Notification')
    let system_configurations = routingKeysString.includes('SystemConfiguration')
    let alerts = routingKeysString.includes('Alert')

    subscriptionsRef.current = { 'subscribe_to_sensors': sensors, 'subscribe_to_zones': zones, 'subscribe_to_alerts': alerts, 'subscribe_to_notifications': notifications, 'subscribe_to_detections': detections, 'subuscribe_to_system_configurations': system_configurations }

    setMethods([...Object.values(data)]);
  };

  console.log(subscriptionsRef.current) //[methods[0][0]]
  getCommunicatorMethods();

  return methods
    .filter((x) => x[0].includes("subscribe"))
    .map((method) => (
      <div key={method[0]}>
        {/* {subscriptionsRef.current[method[0]]} */}
        <span>{method[0].replaceAll("_", " ")}</span>
        <Switch value={subscriptionsRef.current[method[0]]} onChange={handleChange(method[0])} />
      </div>
    ));
};

The problem is that when I do this, I get the following error (as it seems React doesn’t allow returning JSX from an async component)

Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

Flask cannot be found js file although static path is given

I use a setup.py in my project:

from setuptools import find_packages, setup

with open("modules/requirements.txt", "r", encoding="utf-8") as file:
    requirements = file.read().splitlines()

setup(
    name="test-app",
    version="0.1",
    description="A test app",
    packages=find_packages(where="modules"),
    package_dir={"": "modules"},
    license="MIT",
    install_requires=requirements,
    include_package_data=True
)

MANIFEST.in:

recursive-include modules *

My test route with Blueprint (I registered the Blueprint in my main.py)

current_path: str = os.path.dirname(os.path.abspath(__file__))

test = Blueprint(
   name="test", 
   import_name=__name__,
   template_folder=os.path.join(current_path, "static", "templates"),
   static_folder=os.path.join(current_path, "static")
)

The loading of the template is working without any errors:

@test.route("/test", methods=["GET", "POST"])
def test():
    return render_template("test.html")

If I now specify the path of the JavaScript file in my test.html, I get this error:
GET http://127.0.0.1:5000/static/js/app.js net::ERR_ABORTED 404 (NOT FOUND)

My test.html code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>...</title>
</head>
<body>
    <div class="container">
        <!-- ... -->
    </div>
    <script src="{{ url_for('test.static', filename='js/app.js') }}"></script>
</body>
</html>

Customizable Color Picker

I’m building a web app, and I’m wanting to put in a color picker. However, I want to limit the color options to a limited set of colors. Specifically, I’ll be identifying what hex colors most closely match up to available DMC embroidery thread, and I want the color picker to only show those colors. I’ve searched for configurable color pickers, but so far all the ones I’ve found don’t allow you to limit the available colors. Does anyone know of a color picker that allows for that kind of configuration?

Website getting stuck when scrolling. Using Locomotive Scroll Plugin

Our website (https://www.4media-group.com/) just started getting frozen when the page gets to the two Swiper carousels (Case Studies and Client We Believe in). I was thinking it might be something with how and when Locomotive Scroll and Swiper are initiated. But I can’t seem to figure out what to change. When the window resizes you are able to scroll past the carousels again as well as when you run scroll.update() in dev tool console. Does anyone know how I might be able to fix this?

https://www.4media-group.com/

Changing classname of “<div data-node-key". No way to get it working

New to JS. I’m trying to change the class of this:

<div data-node-key="holders" class="ant-tabs-tab">

To this:

<div data-node-key="holders" class="ant-tabs-tab ant-tabs-tab-active">

But nothing seems to work since all the tutorials are for query selecting of id’s or classes.
I think this code I worked out should do the trick, but I get an error saying:

Uncaught TypeError: Cannot read properties of null (reading 'classList') at window.onload

Here’s my code:

window.onload = function()
{
        const myElement = document.querySelector('[data-node-key="holders"]')
        console.log(myElement)

        myElement.classList.remove('ant-tabs-tab');
        myElement.classList.add('ant-tabs-tab ant-tabs-tab-active');

        console.log(myElement)
}

I’m injecting this code through a ‘custom JS’ Chrome extension to modify a website if that’s the problem? I can’t link you the webpage, because you need to be logged in to see anything, so I’ve attached a screenshot if that helps.

Screenshot of the HTML

Like I said, I’m new to JS, but I imagine the code gets executed before the page fully loads? Well, I’ve tried everything I could find and still can’t get it to work.

Tried using document.querySelector to select the element and classList.add to add the new class.

Signing and encrypting data sent to frontend

I’m planning on sending some sensitive data to the font-end in an encrypted form, storing it for a short time and then sending it back to the backend where it’s decrypted and used. For this I guess I would need to both encrypt and sign the data for extra security. There are a lot of ways out there to accomplish this, be it with using the combination of jsonwebtoken and crypto packages to encrypt the payload and then sign it with either jsonwebtoken or jose or just use jose to do both. Both have their advantages and disadvantages..

My current solution is built purely on jose:
Encrypt and signing

export const signAndEncryptObject = async (
    obj: object,
    key: Uint8Array
): Promise<string> => {
    const signedToken = await new jose.SignJWT(obj as JWTPayload)
        .setProtectedHeader({ alg: 'HS256' })
        .setIssuedAt()
        .setExpirationTime('1h')
        .sign(key);

    return await new jose.EncryptJWT({ jwt: signedToken })
        .setProtectedHeader({ alg: 'dir', enc: 'A256GCM' })
        .encrypt(key);
};

Decrypt and verification

export const verifyAndDecryptObject = async (
    token: string,
    key: Uint8Array
): Promise<object> => {
    const { payload } = await jose.jwtDecrypt(token, key);
    const signedToken = payload?.jwt as string;

    const { payload: verifiedPayload } = await jose.jwtVerify(signedToken, key);

    return verifiedPayload;
};

I’ve seen few people recommend this approach, but I’m not sure whether it’s a good one, creating a JWT to store it in an encrypted JWT seems kind of complex.

What would be the best practice to handle this situation? Are there any better ways to to do the signing and encryption?

zxing-js refuses to scan barcodes

I’ve tried everything, other libraries (free ones, boss won’t pay the mad money commercial ones want), but it just won’t scan ean 13 codes. Will scan qr codes all day long. Tried setting the optiond for ean_13_read and ean_reader all to no avail. Quagga and the rest fail in the same way too, but not a shock as they seem to be mostly based on zxing anyway. Can anyone give me a bit of sample code that works? I’m working in dotnet 4.8 mvc, although this is really just pure html/js really. Thanks (hopefully) in advance.

Jim

Here’s my code, obviously doing other bits too. I’m just really after a sample that works!

@model Pocos.MCD_Stores

@{
    ViewBag.Title = "DoVisit";
}
<label id="recordCountLabel">Records Loaded: 0</label>
<br />
<h2>Do Visit</h2>

<!-- Add buttons to start scanning and manually trigger a scan -->
<button id="startScanButton">Start Scanner</button>
<button id="scanNowButton" style="display: none;">Scan it now!</button>
<button id="resetButton">Reset</button>
<br />
<!-- Add a video element for the barcode scanner -->
<video id="barcode-scanner" width="600" height="400" style="border: 1px solid gray; display: block;"></video>
<br />
<label id="scannedBarcodeLabel">Scanned Barcode: None</label>
<br />
<label id="productDetailsLabel">Product Details: None</label>
<br />
<!-- Add the dropdown for products -->
<select id="productDropdown" style="width: 100%;">
    <option value="">Select a product</option>
</select>

<link href="https://cdn.jsdelivr.net/npm/select2@('@')4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/@('@')zxing/library@('@')0.18.6/umd/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@('@')4.1.0-rc.0/dist/js/select2.min.js"></script>

<script>
    let selectedDeviceId;
    const codeReader = new ZXing.BrowserMultiFormatReader();
    console.log('ZXing code reader initialized');

    document.getElementById('startScanButton').addEventListener('click', () => {
        codeReader.listVideoInputDevices()
            .then(videoInputDevices => {
                selectedDeviceId = videoInputDevices.deviceId;
                codeReader.decodeFromVideoDevice(selectedDeviceId, 'barcode-scanner', { formats: [ZXing.BarcodeFormat.EAN_13] }, (result, err) => {
                    if (result) {
                        console.log('Barcode detected:', result);
                        document.getElementById('scannedBarcodeLabel').innerText = `Scanned Barcode: ${result.text}`;
                        handleScannedBarcode(result.text);
                    }
                    if (err && !(err instanceof ZXing.NotFoundException)) {
                        console.error('Error:', err);
                    }
                });
                document.getElementById('scanNowButton').style.display = 'block';
            })
            .catch(err => console.error('Error listing video input devices:', err));
    });

    document.getElementById('scanNowButton').addEventListener('click', () => {
        codeReader.decodeOnceFromVideoDevice(selectedDeviceId, 'barcode-scanner', { formats: [ZXing.BarcodeFormat.EAN_13] })
            .then(result => {
                if (result) {
                    console.log('Barcode detected:', result);
                    document.getElementById('scannedBarcodeLabel').innerText = `Scanned Barcode: ${result.text}`;
                    handleScannedBarcode(result.text);
                }
            })
            .catch(err => {
                if (err && !(err instanceof ZXing.NotFoundException)) {
                    console.error('Error:', err);
                }
            });
    });

    document.getElementById('resetButton').addEventListener('click', () => {
        codeReader.reset();
        document.getElementById('scannedBarcodeLabel').innerText = 'Scanned Barcode: None';
        document.getElementById('productDetailsLabel').innerText = 'Product Details: None';
        document.getElementById('scanNowButton').style.display = 'none';
    });

    // Function to handle the scanned barcode
    function handleScannedBarcode(barcode) {
        const productDbRequest = indexedDB.open('ProductDatabase', 1);

        productDbRequest.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('products', 'readonly');
            const objectStore = transaction.objectStore('products');
            const getRequest = objectStore.get(barcode);

            getRequest.onsuccess = (event) => {
                const product = event.target.result;
                if (product) {
                    document.getElementById('productDetailsLabel').innerText = `Product Details: ${JSON.stringify(product)}`;
                    storeScannedProduct(product.Sku);
                } else {
                    document.getElementById('productDetailsLabel').innerText = `Product Details: Not found`;
                }
            };

            getRequest.onerror = (event) => {
                console.error('Error retrieving product:', event.target.error);
            };
        };

        productDbRequest.onerror = (event) => {
            console.error('Error opening ProductDatabase:', event.target.error);
        };
    }

    function customMatcher(params, data) {
        // If there are no search terms, return all of the data
        if ($.trim(params.term) === '') {
            return data;
        }

        // Make the search case-insensitive
        const term = params.term.toLowerCase();
        const text = data.text.toLowerCase();

        // Check if the term is found within the text
        if (text.indexOf(term) > -1) {
            return data;
        }

        // Return `null` if the term should not be displayed
        return null;
    }

    // Function to store the scanned product in the second IndexedDB
    function storeScannedProduct(sku) {
        const scannedDbRequest = indexedDB.open('scannedProductDatabase', 1);

        scannedDbRequest.onsuccess = (event) => {
            const db = event.target.result;
            const transaction = db.transaction('skuCounts', 'readwrite');
            const objectStore = transaction.objectStore('skuCounts');
            const getRequest = objectStore.get(sku);

            getRequest.onsuccess = (event) => {
                const record = event.target.result;
                if (record) {
                    record.Count += 1;
                    objectStore.put(record);
                } else {
                    objectStore.put({ Sku: sku, Count: 1 });
                }
            };

            getRequest.onerror = (event) => {
                console.error('Error retrieving scanned product:', event.target.error);
            };
        };

        scannedDbRequest.onerror = (event) => {
            console.error('Error opening scannedProductDatabase:', event.target.error);
        };
    }

    // Ensure the DOM is fully loaded before running the script
    document.addEventListener('DOMContentLoaded', (event) => {
        // Initialize the second IndexedDB
        initScannedProductDB()
            .then(db => {
                console.log('Second IndexedDB is ready to use.');
                // Retrieve the record count from localStorage and update the label
                const recordCount = localStorage.getItem('recordCount');
                if (recordCount) {
                    document.getElementById('recordCountLabel').innerText = `Records Loaded: ${recordCount}`;
                }
            })
            .catch(error => {
                console.error('Error initializing second IndexedDB:', error);
            });

        // Fetch products from IndexedDB and populate the dropdown
        fetchProductsFromIndexedDB().then(products => {
            products.sort((a, b) => {
                const descA = a.Desc !== "NULL" ? a.Desc.toLowerCase() : "";
                const descB = b.Desc !== "NULL" ? b.Desc.toLowerCase() : "";
                if (descA < descB) return -1;
                if (descA > descB) return 1;
                return 0;
            });

            const dropdown = $('#productDropdown');
            products.forEach(product => {
                const desc = product.Desc !== "NULL" ? product.Desc : "";
                const colour = product.Colour !== "NULL" ? product.Colour : "";
                const size = product.Size !== "NULL" ? product.Size : "";
                const option = new Option(`${desc} - ${colour} - ${size}`, product.Sku, false, false);
                dropdown.append(option);
            });
            dropdown.select2({
                placeholder: "Select a product",
                allowClear: true,
                matcher: customMatcher
            });
        }).catch(error => {
            console.error('Error fetching products:', error);
        });
    });

    // Function to initialize the second IndexedDB
    function initScannedProductDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open('scannedProductDatabase', 1);

            request.onupgradeneeded = (event) => {
                const db = event.target.result;
                const objectStore = db.createObjectStore('skuCounts', { keyPath: 'Sku' });
                objectStore.createIndex('Sku', 'Sku', { unique: true });
                objectStore.createIndex('Count', 'Count', { unique: false });
            };

            request.onsuccess = (event) => {
                console.log('Second IndexedDB initialized successfully.');
                resolve(event.target.result);
            };

            request.onerror = (event) => {
                reject(event.target.error);
            };
        });
    }

    // Function to fetch products from IndexedDB
    function fetchProductsFromIndexedDB() {
        return new Promise((resolve, reject) => {
            const request = indexedDB.open('ProductDatabase', 1);

            request.onsuccess = (event) => {
                const db = event.target.result;
                const transaction = db.transaction(['products'], 'readonly');
                const objectStore = transaction.objectStore('products');
                const products = [];

                objectStore.openCursor().onsuccess = (event) => {
                    const cursor = event.target.result;
                    if (cursor) {
                        products.push(cursor.value);
                        cursor.continue();
                    } else {
                        resolve(products);
                    }
                };

                objectStore.openCursor().onerror = (event) => {
                    reject(event.target.error);
                };
            };

            request.onerror = (event) => {
                reject(event.target.error);
            };
        });
    }
</script>