Can’t render a PDF page on node-canva – NodeJS, pdfjs-dist

I’m trying to use this lib to render a PDF page at certain dimensions, but I can’t manage to make it work, could you tell me what I do wrong ?

Modules I use:

“canvas”: “Automattic/node-canvas#master”
=>Because of incompatibility problems with node 22, I also tried with “^3.1.0” and node 20 but the issue is still here.

“pdfjs-dist”: “^5.1.91”

My code is the following:

import pdfjs from "pdfjs-dist/legacy/build/pdf.mjs";
import Canvas from "canvas";

...code

const pdf = await pdfjs.getDocument(new Uint8Array(file_.file)).promise;
const page = await pdf.getPage(1);

const viewport = page.getViewport({
  scale: thumbnailWidth / page.getViewport({ scale: 1 }).width,
});

const canvas = Canvas.createCanvas(
  Math.floor(viewport.width),
  Math.floor(viewport.height)
);
const context = canvas.getContext("2d") as any;

await page.render({
      canvasContext: context,
      viewport,
    }).promise;

...code

And I get this output on the last instruction:

err: {
"type": "TypeError",
"message": "Image or Canvas expected",
"stack":
gestion-documentaire:dev:           TypeError: Image or Canvas expected
    at drawImageAtIntegerCoords (_project_location_/node_modules/pdfjs-dist/legacy/build/gestion-documentaire:dev: 
   at CanvasGraphics.paintInlineImageXObject (_project_location_/node_modules/pdfjs-distgestion-documentaire:dev: 4:5)
    at CanvasGraphics.paintImageXObject (_project_location_/node_modules/pdfjs-dist/legacgestion-documentaire:dev: 
  at CanvasGraphics.executeOperatorList (_project_location_/node_modules/pdfjs-dist/leggestion-documentaire:dev: )
  at InternalRenderTask._next (_project_location_/node_modules/pdfjs-dist/legacy/build/gestion-documentaire:dev: 
  at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
}

I do the canvas.getContext(“2d”) as any; workaround because if I don’t, I get this error (translated from french by my own) on the await page.render… instruction:

Type 'CanvasRenderingContext2D' don't have following properties of the 'CanvasRenderingContext2D' type: isPointInStroke, createConicGradient, filter, imageSmoothingQuality and 10 others.ts(2740)
api.d.ts(420, 5): The awaited type comes from the 'canvasContext' property, which is declared on the 'RenderParameters' type.

Thank you.

An error occurred while rendering Collection: Invalid version. Must be a string. Got type “undefined” [closed]

throw new TypeError(‘argument handler must be a function’)
^

TypeError: argument handler must be a function
at Route. [as post] (C:Desktopbackendsearchnode_modulesrouterlibroute.js:228:15)
at Router. [as post] (C:Desktopbackendsearchnode_modulesrouterindex.js:448:19)
at Object. (C:DesktopbackendsearchRouterssearchRouter.js:5:8)
at Module._compile (node:internal/modules/cjs/loader:1554:14)
at Object..js (node:internal/modules/cjs/loader:1706:10)
at Module.load (node:internal/modules/cjs/loader:1289:32)
at Function._load (node:internal/modules/cjs/loader:1108:12)
at TracingChannel.traceSync (node:diagnostics_channel:322:14)
at wrapModuleLoad (node:internal/modules/cjs/loader:220:24)
at Module.require (node:internal/modules/cjs/loader:1311:12)

Node.js v22.14.0
[nodemon] app crashed – waiting for file changes before starting…

Can’t get JSON response from fetch request – getting “.json() is not a function” error [closed]

I am trying to post JSON to a Webhook and then parse the JSON the webhook sends back.

This is what I have for so far but I get the error:

resp.json is not a function

What is wrong?

const data = "{"Customer": "My Company"}";
const resp = fetch("https://my.apiserver.org", {
    method: "POST",
    body: JSON.stringify(data),
    headers: {
    "Content-type": "application/json; charset=UTF-8"
    }
});

const json = await resp.json();

How to sort a 2d array in Apps script (google sheet) base on a 1d array

I have a script that I have been using for some time, but I recently had a bug on a data spell and since then I have been unable to fix the problem.

I transpose arrays because they are normally horizontal.

function test() {
var objects = spreadsheet.getSheetByName("Feuille 121").getRange("A1:GG2").getValues()
var order = spreadsheet.getSheetByName("Feuille 121").getRange("A3:GG3").getValues().flat()

objects = Object.keys(objects[0]).map(function (c) { return objects.map(function (r) { return r[c]; }); });
order = Object.keys(order[0]).map(function (c) { return order.map(function (r) { return r[c]; }); });

// organise dans l'ordre des paramètre
let orderIndex = {}
order.forEach((value, index) => orderIndex[value] = index);

// Sort
objects.sort((a, b) => orderIndex[a[0]] - orderIndex[b[0]]); 

var length = objects.length

objects = Object.keys(objects[0]).map(function (c) { return objects.map(function (r) { return r[c]; }); });
console.log(objects)
spreadsheet.getSheetByName("Feuille 121").getRange(1,1,2,length).setValues(objects)

}

apache-echart how to skip null value like chart js

enter image description here

from this picture i want to remove or skip empty bar i try to change data to Null, Undifinded, ‘-‘, 0 but it not work

this is my data

var series = [
{
“name”: “Bar A”,
“type”: “bar”,
“stack”: “Bar A”,
“data”: [
1,
“-”
],
“itemStyle”: {
“color”: “#81C784”
},
“label”: {
“rotate”: 45,
“show”: true,
“position”: “inside”
}
},
{
“name”: “Bar B”,
“type”: “bar”,
“stack”: “Bar B”,
“data”: [
1,
“-”
],
“itemStyle”: {
“color”: “#81C784”
},
“label”: {
“rotate”: 45,
“show”: true,
“position”: “inside”
}
},
{
“name”: “Bar C”,
“type”: “bar”,
“stack”: “Bar C”,
“data”: [
“-“,
1
],
“itemStyle”: {
“color”: “#81C784”
},
“label”: {
“rotate”: 45,
“show”: true,
“position”: “inside”
}
},
{
“name”: “Bar D”,
“type”: “bar”,
“stack”: “Bar D”,
“data”: [
“-“,
1
],
“itemStyle”: {
“color”: “#81C784”
},
“label”: {
“rotate”: 45,
“show”: true,
“position”: “inside”
}
},
]

when using emotionjs, is it better to write all styles using it?

i’m developing a project using typeScript and have adopted emotionjs to simplify styling. however, i am wondering if the following code is efficient.

// 1. using emotionjs
import { css } from '@emotion/css';

const common = css` color: #ccc; `;

const $div = document.createElement('div');
$div.classList.add(common);

// 2. using inline-style
const $div = document.createElement('div');
$div.innerHtml = `<div style="color: #ccc;">text</div>`

as far as I understand, when styles are created using emotionjs, it modifies the CSSOM — in other words, a <style> tag is injected into the <head>, which inevitably triggers a CSSOM update.
on the other hand, setting styles using inline styles does not affect the CSSOM, but it does cause reflow and repaint.

if what I understand about the process is correct, does that mean relying solely on emotionjs for styling could lead to performance issues?

since emotionjs updates the CSSOM when applying styles, i thought excessive fragmentation(like in the code above)would result in too many injected class names, which could negatively impact runtime performance.

Why vuejs chart with data read by axios is empty?

In laravel 12 / vuejs “^3.5.13” app with “vue-chartjs”: “^5.3.2” and “chart.js”: “^4.4.8” I make chart with data read
from db :

 <template>
     <div>
         <Bar
             id="my-chart-id"
             :options="chartOptions"
             :data="chartData"
         />
     </div>
 </template>

 <script>
     import {useItemsChartStore} from "@/stores/reports/ItemsChartStore.js";

     import { Bar } from 'vue-chartjs'
     import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'

     ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)


     export default {
         name: "ItemReportTable.vue",
         data() {
             return {
                 ItemsChartStore: useItemsChartStore(),
                 chartData: {
                     labels: [ 'January', 'February', 'March' ],
                     datasets: [ { data: [40, 20, 12] } ]
                     // labels: [],
                     // datasets: [ {  } ]
                 },
                 colors: [
                     '#3b82f6',
                     '#7c3aed'
                 ],

                 chartOptions: {
                     indexAxis: 'y',
                     responsive: true,
                     scales: {
                         x: {
                             ticks: {
                                 callback: value => parseFloat(value).toFixed(2) + '%'
                             },
                             beginAtZero: true,
                             max: 100
                         }
                     },
                     plugins: {
                         legend: {
                             position: 'bottom'
                         },
                         title: {
                             display: true,
                             text: 'Error!'
                         },
                         tooltip: {
                             callbacks: {
                                 label: context => { // Is not claaded
                                     console.log('callbacks context::')
                                     console.log(context)

                                     const val = context.raw
                                     return `${context.dataset.label}: ${val.toFixed(2)}%`
                                 }
                             }
                         }
                     }
                 }
             }
         },
         components: { Bar },

         computed: {
             labelDistricts() {
                 return this.ItemsChartStore.labelDistricts;
             },
             datasetsVotersCount() {
                 return this.ItemsChartStore.datasetsVotersCount;
             },
         },


         watch: {
             datasetsVotersCount(newValue) {
                 console.log('watch this.datasetsVotersCount newValue::')
                 console.log(newValue)

                 this.chartData.labels  = this.labelDistricts
                 this.chartData.datasets  = this.datasetsVotersCount

                 console.log('this.datasetsVotersCount this.chartData.labels::')
                 console.log(this.chartData.labels)

                 console.log('this.datasetsVotersCount this.chartData.datasets::')
                 console.log(this.chartData.datasets)

             }
         },

         methods: {
         },

         mounted() {
             this.ItemsChartStore.fetchItemsChart(this.$route.params.eventId);
         }
     }
 </script>

Where in mount I read data from db with axios async request and in watch datasetsVotersCount event I see that data are read.
I set valid values to chartData array and check it has valid data in vue-dev-tools. But I still default 'January', 'February', 'March' values in the chart. If I leave no data in the chartData var, then my chart is empty and
i have undefined in legend area in the bottom.

How to make it working ?

Bigint issue in JS for long Number

I don’t want to convert the number 20250130134690296n, and I also don’t want to convert it to a string. I just want to keep the plain, actual number as 20250130134690294. Is there any way to achieve this?

let a =  Bigint(20250130134690294)

console.log(a)

result =  20250130134690296n

Converting Firebase Timestamp to JS Date with correct timezone

I have some data in Firestore with a Timestamp in my local timezone (Europe/Copenhagen) and because we are in summer that is UTC+2 right now. I also have some ints in the Firestore collection to save start/end hour and minute.

I am trying to convert them to a JavaScript Date and creating a event in a Google Calendar via googleapis like this:

exports.createCalendarOnTimesCreated = functions.firestore.onDocumentCreated("times/{timeId}", async (event) => {
    google.options({ auth: serviceAccount });

    const data = event.data != null ? event.data!.data() : null;

    if (!data) {
        return;
    }

    const eventTime = data.dateAndTime as Timestamp;
    const dateStart = eventTime.toDate();
    dateStart.setHours(data.timeStartHour);
    dateStart.setMinutes(data.timeStartMinutes);
    const dateEnd = eventTime.toDate();
    dateEnd.setHours(data.timeEndHour);
    dateEnd.setMinutes(data.timeEndMinutes);

    const eventData = {
        summary: "Test",
        start: {
            dateTime: dateStart.toISOString(),
            timeZone: 'Europe/Copenhagen',
        },
        end: {
            dateTime: dateEnd.toISOString(),
            timeZone: 'Europe/Copenhagen',
        },
    };

    // Create new event
    await calendar.events.insert({
        calendarId: calendarId,
        requestBody: eventData,
    });
});

Strangly if I create a document in the collection where dateAndTime is today the date in the Google Calendar event is correct, but if I create a document where dateAndTime is tomorrow or anytime in the future the date in the Google Calendar is always one day before the date in the document in Firestore.

What am I doing wrong here?

Thank you
Søren

Electron Playwright Test Hanging due to Flask Backend

I have an Electron app that first runs its backend and awaits its connection before opening the first window like:

/**
 * Connects to the Flask app, then creates the window
 */
let flaskProc = null;
const connectToFlask = () => {
    //...
    
    //run the venv and start the script
    flaskProc = require("child_process").spawn(command, args);

    flaskProc.stdout.on('data', function (data) {  
        const output = data.toString('utf8');
        console.log("FLASK RUNNING! data:", output);
        /* Wait until Flask server is running to create the window */
        if(output.includes("Serving Flask")){
            testFlaskConnection().then((value) => {
                if(value===true){
                    //emitting an event for Playwright tests
                    createWindow();
                }
            })
            .catch(err => console.error(err));
        }
    });
    //...
}

const testFlaskConnection = () => {
    if (flaskProc) {
        console.log("Attempting connection to Flask...");
        return fetch(`${SERVER_URL}/`,{ method: "GET" })
        .then((response) =>{
            //...
            return true;
        })
        //...
    }
}

app.whenReady().then(() => {
    connectToFlask();
});

and when the window is closed, the backend shuts down like:

const shutdownFlaskConnection = () => {
    if (flaskProc) {
        return fetch(`${SERVER_URL}/shutdown`, { method:"POST" })
        .then((response) => {
            /* If the response doesn't come back (error 404), Flask has probably
            already shut down before it could be sent */
            if (!response.ok && response.status!=404) {
                console.error("Flask shutdown request failed:", response.status);
                flaskProc.kill('SIGINT');   //kill Flask jic
                flaskProc=null;
                return;
            }
            /* Otherwise, Flask was shutdown */
            console.log("Flask shutdown request successful.");
            flaskProc=null;
        })
        .catch((error) => {
            console.error("Error with shutdown request:", error);
            flaskProc.kill('SIGINT');
            flaskProc = null;
        });
    }
}

//...

let isAppQuitting=false;    //flag for on close event
let win=null;
const createWindow = () => {
    //...
    win.on('close', (evt) => {
        if(!isAppQuitting){
            evt.preventDefault();   //pause shutdown to run one last request
            console.log("Attempting graceful exit of Flask...");
            shutdownFlaskConnection().then(() => {
                //close again, properly this time
                isAppQuitting=true; //reset flag to skip if block
                win.close();    //run the event handler again
            }).catch((err) => {
                console.error(err);
                isAppQuitting=true; //reset flag to skip if block
                win.close();    //run the event handler again
            });
        }
    });
}

/**
 * When all the windows close, quit the app
 */
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin'){
        app.quit();
    }
});
/**
 * When Electron is closed through the terminal, also kill Flask
 */
app.on('quit', () => {
    if (flaskProc) {
        console.log("Quitting: Sending SIGINT to Flask process...");
        flaskProc.kill('SIGINT');
    }
});

The latter part, I suspect, is the reason this error is happening.

The app works. The problem is that I want to add some tests with Playwright and this seems to be causing problems.

Just opening and closing the app works. Both of the tests below work:

const { test, _electron: electron } = require('@playwright/test')

test('launch app', async () => {
    //NOTE: The launch path is relative to the folder the script is running from
    const electronApp = await electron.launch({ args: ['apps/frontend/src/electron/main.js'] })
    // close app
    await electronApp.close()

});
const { test, _electron: electron } = require('@playwright/test')

let electronApp = null;
test.beforeAll(async () => {
    //NOTE: The launch path is relative to the folder the script is running from
    electronApp = await electron.launch({ args: ['apps/frontend/src/electron/main.js'] });
});

test.afterAll(async () => {
    // close app
    await electronApp.close();
})


test('launch app', async () => {
    console.log("filler");
});

But the moment I try to interact with the app, the test will run until it’s timed out, even after all actions have been completed.

test('launch app', async () => {
    // Get the first window that the app opens, wait if necessary.
    const window = await electronApp.firstWindow();
    // Print the title
    console.log(await window.title());
    // close app
    await electronApp.close();
});

Opens the app, prints the title, and then closes the app, as it should, but then the test just keeps running. It then times out, fails, and I have to stop the test runner manually.
The error message I get looks like:

Running 1 test using 1 worker

  ✘  1 appslibse2e_testsmain.spec.js:15:1 › launch app (30.0s)
Index Page


  1) appslibse2e_testsmain.spec.js:15:1 › launch app ───────────────────────────────────────
    Test timeout of 30000ms exceeded.

  1 failed
    appslibse2e_testsmain.spec.js:15:1 › launch app ────────────────────────────────────────
Terminate batch job (Y/N)? y

I know that this problem is due to the Flask app because if I replace my main.js with the one from the Electron Quick Start Guide, it runs perfectly. The following message is what that prints to the terminal:

Running 1 test using 1 worker

  ✓  1 appslibse2e_testsmain.spec.js:15:1 › launch app (242ms)
Index Page

  1 passed (1.6s)

I have tried emitting a message for Playwright to pick up or a console.log() message, but neither work. It’s difficult searching for answers since this is such a specific problem.

Any help would be appreciated. Thank you for your time.

HTML input form not working correctly on some devices but works on others

The input field in my app works normally with any value, except “!” and “2” specifically.
However, when i send the link to my friends to test it it works for some but not for others. Here is the result:
1.Brave Browser — Works
2.Microsoft Edge — Doesn’t work
3.Google Chrome — Works
Here is the project: https://github.com/DanhTheAlyaSimp/Visuo
If it is a browser problem how to make sure a program works on all browsers?

What I’ve tried:
Switched to Google Chrome and it works. However it still doesn’t work on Edge, which means it’s browser dependent.

For a float number a.bc without underflow and overflow, does a.bc.toString() always ==”a.bc”? May it return something like “a.bc00000000000000000001”?

For example, I know 0.12 is not exactly equals to 12/100 in decimal because it needs to be rounded to some value. However, I’m not asking about mathematical problem , but about Javascript spec that string converting without other calculations.

My question is, if someone gives you a float number that without underflow and overflow (eg:from http response or hardcoded value):

const obj={
    "val":a.bc;
};

,does Javascript spec ensures that obj.val.toString() always return “a.bc”?

Would there be any cases that obj[“val”].a.bc.toString() return something like “a.bc00000000000000000001” (actual value of the float value that rounded)?

Is there a way to conditionally compile something in Typescript based on a compile-time expression?

With the many frameworks that that we have that allow us to build apps using web frontend technologies in many cases you might want to create an app/frontend that communicates to the backend in a different way depending on whether it’s being served as a website, or being ‘served’ by Tauri, or Electron backend, or whatever else. Is there a way I can do something like:

async function sendToBackend()
{
#ifdef IS_WEBPAGE_BUILD
     await fetch("/backend_service");
#else
     await invoke("myBackendFunctionInTauri", "args_or_whatever");
#endif
}

That will end up one or the other based on a compile-time variable or flag I can set? Typescript is purely a compile-time transpiler so it should be good at this.