Can we have Multiple Interceptor for a single Http method in Nestjs?

Is it possible to have multiple interceptor for a single HTTP method.
for instance we a have a file upload method, where the express fileInterceptor handles.
And I have generalized response structure defined in a interceptor. so i wanted to use both of these interceptor for a single HTTP method.

Since I am new to Nestjs framework I am not familiar with the concept so wanted some insight on the same.

Why Promise chains register all the callbacks when declared?

A chain of then()-s register callbacks with the OS, instead of deferring the registration until the callback is needed.

I am learning about Promises in Javascript. This is an example code:

let promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve('First Result'), 1000);
});

promise
  .then(result => {
    console.log(result); // 'First Result'
    return 'Second Result';
  })
  .then(result => {
    console.log(result); // 'Second Result'
    return 'Third Result';
  })
  .catch(error => {
    console.error(error.message); // 'Something went wrong!'
  });

This code runs in little more than 1 second. It means that callbacks for the timers were registered with the OS immediately, and the Promise object only ran them if there were no errors. Why is it like this? Why register a callback, that might not even run? I imagine that promises are some kind of linked lists internally, so the first one could notify the next when it’s ready. If setTimeout() would be fetch() that would waste bandwidth, am I right?

Module not found: Error: Can’t resolve ‘morris.js’ in “folder name”

Sorry I’m new to reactjs. I’m making a chart using Morrish.js
i am using Morris.js for my reactjs project.
However, when building, it gives an error like this

ERROR in ./src/component/chart/sprint_chart.tsx
Module not found: Error: Can't resolve 'morris.js' in '/Users/cuongnm1/Documents/IH/insighthub/webapp/src/component/chart'
 @ ./src/component/chart/sprint_chart.tsx 3:0-36 8:4-15
 @ ./src/component/chart/broad_chart.tsx
 @ ./src/index.tsx
 @ multi ./src/index.tsx

This is my code

import React, {useEffect} from 'react';
import 'morris.js/morris.css';
import * as Morris from 'morris.js';

const CustomChart: React.FC = () => {
    useEffect(() => {
        // Khởi tạo Morris.js chỉ sau khi component đã được mount
        Morris.Area({
            element: 'area-chart',
            data: [
                {y: '2014', a: 150, b: 150},
                {y: '2015', a: 135, b: 120},
                {y: '2015', a: 135, b: 140},
                {y: '2016', a: 120, b: 125},
                {y: '2017', a: 105, b: 110},
                {y: '2018', a: 90, b: 105},
                {y: '2019', a: 75, b: 60},
                {y: '2020', a: 60, b: 45},
                {y: '2021', a: 45, b: 35},
                {y: '2022', a: 30, b: 25},
                {y: '2023', a: 15, b: 10},
                {y: '2024', a: 0, b: 10},
            ],
            xkey: 'y',
            ykeys: ['a', 'b'],
            labels: ['Total Income', 'Total Outcome'],
            hideHover: 'auto',
            behaveLikeLine: true,
            resize: true,
            pointFillColors: ['#1B7837', '#800026'],
            lineColors: ['#5AAE61', '#800026'],
            fillOpacity: 0.2,
        });
    }, []); // Chỉ chạy một lần sau khi component mount

    return (
        <div>
            <h3 className='text-primary text-center'>Sprint Chart</h3>
            <div className='row'>
                <div className='col-sm-6 text-center'>
                    <label className='label label-success'>Area Chart</label>
                    <div id='area-chart' style={{minHeight: '450px'}}/>
                </div>
            </div>
        </div>
    );
};

export default CustomChart;

also when pointing to ‘morris.js’ in the import. it will also give error

is not a module.
ESLint: Unable to resolve path to module 'morris.js'.(import/no-unresolved)

I tried creating a morris.js.d.ts file and adding this code. but still not

declare module 'morris.js';

in tanstck table how to change accessorKey value based on row value

{ accessorKey: "userId", header: ({ column }) => ( <DataTableColumnHeader column={column} title="User Id" /> ), cell: ({ row }) => ( <label>{row?.original?.subRetailerId ?? row?.original?.retailerId}</label> ), },

How to change accessorKey from userId to userId2 when retailerId exists

I am working on sorting it giving me accessorKey or id if exists so i want chnage accessorKey value from userId to userId2 when retailerId exists else it should be userId

Error in page load due to php echo on link [closed]

<tbody>
  <?php $bn = mysqli_query($link,"select * from registration order by id desc"); while ($fbn=mysqli_fetch_assoc($bn)){$i++;?>
  <tr>
    <td><?php echo $i++;?></td>
    <td><?php echo $fbn['name'];?></td>
    <td><?php echo $fbn['grp'];?></td>
    <td>
      <div class="flex align-items-center list-user-action">
        <?php $a = $fbn['class_name'];?>
        <a href="#"  data-toggle="modal" data-target="#view" onclick="ViewClasses('<?php echo $fbn[name];?>','<?php echo $fbn[grp];?>','<?php echo $fbn[tranx_id];?>')" class="btn btn-primary">Edit</a>
      </div>
    </td>
  </tr>
  <?php } ?>
</tbody>

I tried to figure out where the error was coming from but I discovered it’s from the onclick. I did some modification around the code but it didn’t work.

Creating spin wheel with 0% probability of specific sectors

I have created a spin wheel using html, css, jquery. The problem i am facing with the below code is that the pointer lands on some other sector and alerts something else. For example, if it lands on “Movie Tickets” it will alert “Free Spin”. I assume this is a css issue with pointer. Also i am trying to make 0% probability of pointer landing on “iPhone 15” and “AED 3000”

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spin Wheel</title>
    <style>
        body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f4f4f4;
    font-family: Arial;
}

.wheel-container {
    position: relative;
}

#spin-wheel {
    width: 500px;
    height: 500px;
    position: relative;
    border-radius: 50%;
    overflow: hidden;
    border: 2px solid #000;
}

.wheel {
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background-image: conic-gradient(#E7652A 0 45deg, #ffffff 45deg 90deg, #E7652A 90deg 135deg, #ffffff 135deg 180deg, #E7652A 180deg 225deg, #ffffff 225deg 270deg, #E7652A 270deg 315deg, #ffffff 315deg 360deg);
    transform: rotate(0deg);
    transition: transform 4s cubic-bezier(0.33, 1, 0.68, 1);
}


.pointer {
    position: absolute;
    top: 20px;
    left: 50%;
    width: 50px;
    height: 50px;
    background-color: #000;
    clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
    transform: translate(-50%, -50%) rotate(180deg);
    z-index: 10;
}

button {
    display: block;
    margin-top: 20px;
    padding: 10px 20px;
    font-size: 16px;
    cursor: pointer;
}
.sector-text {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 300px;
    text-align: center;
    transform-origin: 0 0;
    color: #000;
    font-size: 13px;
}
    </style>
</head>
<body>
    <div class="wheel-container">
        <div id="spin-wheel">
            <div class="wheel">
                <div class="sector-text" style="transform: rotate(22.5deg);">iPhone 15</div>
                <div class="sector-text" style="transform: rotate(67.5deg);">AED 3000</div>
                <div class="sector-text" style="transform: rotate(112.5deg);">Airpods 3rd Gen</div>
                <div class="sector-text" style="transform: rotate(157.5deg);">Gift Voucher</div>
                <div class="sector-text" style="transform: rotate(202.5deg);">Dinner for 2</div>
                <div class="sector-text" style="transform: rotate(247.5deg);">Business Lunch</div>
                <div class="sector-text" style="transform: rotate(292.5deg);">Movie Tickets</div>
                <div class="sector-text" style="transform: rotate(337.5deg);">Free Spin</div>
            </div>
            <div class="pointer"></div>
        </div>
        <button id="spin-button">Spin</button>
    </div>

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
    $(document).ready(function() {
        const spinButton = $('#spin-button');
        const wheel = $('.wheel');
    
        spinButton.click(function() {
            let randomDegree = getRandomDegree();
            let totalDegree = 360 * 10 + randomDegree;
    
            wheel.css('transform', `rotate(${totalDegree}deg)`);
    
            setTimeout(function() {
                let sector = getSector(randomDegree);
                alert(`You landed on sector ${sector}`);
            }, 4000); // 4 seconds for the spin animation to complete
        });
    
        function getRandomDegree() {
            let random = Math.random() * 100;
    
            if (random <= 1) {
                return getDegreeForSector(1);
            } else if (random <= 2) {
                return getDegreeForSector(2);
            } else if (random <= 3) {
                return getDegreeForSector(3);
            } else if (random <= 12.25) {
                return getDegreeForSector(4);
            } else if (random <= 25.5) {
                return getDegreeForSector(5);
            } else if (random <= 37.75) {
                return getDegreeForSector(6);
            } else if (random <= 50) {
                return getDegreeForSector(7);
            } else {
                return getDegreeForSector(8);
            }
        }
    
        function getDegreeForSector(sector) {
            switch (sector) {
                case 1: return Math.random() * 45;
                case 2: return 45 + Math.random() * 45;
                case 3: return 90 + Math.random() * 45;
                case 4: return 135 + Math.random() * 45;
                case 5: return 180 + Math.random() * 45;
                case 6: return 225 + Math.random() * 45;
                case 7: return 270 + Math.random() * 45;
                case 8: return 315 + Math.random() * 45;
            }
        }
    
        function getSector(degree) {
            degree = degree % 360;
    
            if (degree <= 45) {
                return "iPhone 15";
            } else if (degree <= 90) {
                return "AED 3000";
            } else if (degree <= 135) {
                return "Airpods 3rd Gen";
            } else if (degree <= 180) {
                return "Gift Voucher";
            } else if (degree <= 225) {
                return "Dinner for 2";
            } else if (degree <= 270) {
                return "Business Lunch";
            } else if (degree <= 315) {
                return "Movie Tickets";
            } else {
                return "Free Spin";
            }
        }
    });
    </script>
</body>
</html>

Three.js bevel breaks on extruded geometry

I’m trying to bevel a shape extruded along a path with three.js. I have been successful at beveling and extruding separately but not both at once.

does anyone knows why the bevel parameter breaks when extruding a geometry along a path and eventually how to fix it?

You can see it in action commenting in/out line 29 of this fiddle:

https://jsfiddle.net/9012ab3z/1/

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.z = 50;

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

var light = new THREE.PointLight(0xffffff, 2, 100);
light.position.z = 10;
scene.add(light);

// Create a 2D triangular shape
// The Shape() class has methods for drawing a 2D shape
var triangleShape = new THREE.Shape();
triangleShape.moveTo(-2, -2);
triangleShape.lineTo(0, 2);
triangleShape.lineTo(2, -2);
triangleShape.lineTo(-2, -2);

var line = new THREE.CatmullRomCurve3([
   new THREE.Vector3(0, 0, 0),
   new THREE.Vector3(0, 5, 0)
]);
// Create a new geometry by extruding the triangleShape
// The option: 'amount' is how far to extrude, 'bevelEnabled: false' prevents beveling
var extrudedGeometry = new THREE.ExtrudeGeometry(triangleShape, {
amount: 5,
extrudePath: line, // comment this parameter out to see bevel working
bevelEnabled: true,
bevelSegments: 30
  });

// Geometry doesn't do much on its own, we need to create a Mesh from it
var extrudedMesh = new THREE.Mesh(extrudedGeometry, new THREE.MeshPhongMaterial({color: 0xff0000}));
scene.add(extrudedMesh);

// render loop
var render = function () {
  requestAnimationFrame( render );

  renderer.render(scene, camera);
};

// Rotate the mesh based on mouse position
document.body.onmousemove = function(e){
    extrudedMesh.rotation.z = e.pageX / 100;
    extrudedMesh.rotation.x = e.pageY / 100;
}

// Click to toggle wireframe mode
document.body.onclick = function(e){
    extrudedMesh.material.wireframe = !extrudedMesh.material.wireframe;
}

render(); // initiate render loop

REACT Update the table after adding a record

I’m just starting to master React, I need help, I can’t figure out how to redraw the table after adding a new password in the modal window. Please help me figure it out
Container.jsx

import { useState, useRef } from 'react';
import PassTable from './../PassTable/PassTable';
import Button from './../Button/Button';
import Modal from './../Modal/Modal';
import PasswordForm from './../PasswordForm/PasswordForm';
import './Container.css';

export default function Container() {
    const [modalOpen, setModalOpen] = useState(false);
    const fetchTableRef = useRef(null);

    const handleModalClose = () => {
        setModalOpen(false);
    };

    const handleModalOpen = () => {
        setModalOpen(true);
    };

    const refreshTable = () => {
        if (fetchTableRef.current) {
            fetchTableRef.current();
        }
    };

    return (
        <div className="container">
            <h1>Менеджер паролей на React</h1>
            <PassTable ref={refreshTable} />
            <Button onClick={handleModalOpen} id='addRecordBtn'>Добавить новый</Button>
            <Modal open={modalOpen} onClose={handleModalClose}>
                <PasswordForm closeModal={handleModalClose} fetchTable={refreshTable} />
            </Modal>
        </div>
    );
}

PasswordForm.jsx

import { useState } from 'react';
import passwordService from './../services/passwordService';
import './PasswordForm.css';

export default function PasswordForm({ closeModal, refreshData }) {
    const [name, setName] = useState('');
    const [password, setPassword] = useState('');
    const [type, setType] = useState('site');
    const [showPassword, setShowPassword] = useState(false);

    const handleSubmit = async (event) => {
        event.preventDefault();

        if (type === 'email' && !validateEmail(name)) {
            alert('Неверный формат электронной почты');
            return;
        }

        try {
            await passwordService.createPassword({ name, password, type, createdAt: new Date().toISOString() });
            setName(''); 
            setPassword('');
            setType('site');
            closeModal();
            refreshData();
        } catch (error) {
            alert(`Ошибка: ${error.message}`);
        }
    };

    function validateEmail(email) {
        const re = /^[^s@]+@[^s@]+.[^s@]+$/;
        return re.test(email);
    }

    return (
        <form onSubmit={handleSubmit}>
            <span className="close-btn" onClick={() => setModal(false)}>&times;</span>
            <h2>Добавить новый пароль</h2>
            <label htmlFor="name">Наименование:</label>
            <input
                type="text"
                id="name"
                name="name"
                value={name}
                onChange={(event) => setName(event.target.value)}
                required
            />

            <label htmlFor="password">Пароль:</label>
            <div className="password-field">
                <input
                    type={showPassword ? 'text' : 'password'}
                    id="password"
                    name="password"
                    value={password}
                    onChange={(event) => setPassword(event.target.value)}
                    required
                    minLength="8"
                />
                <button
                    type="button"
                    onClick={() => setShowPassword(prev => !prev)}
                    className="toggle-password-btn"
                >
                    {showPassword ? 'Скрыть' : 'Показать'}
                </button>
            </div>

            <label>Тип записи:</label>
            <ul>
                    <input
                        type="radio"
                        id="typeSite"
                        name="type"
                        value="site"
                        checked={type === 'site'}
                        onChange={() => setType('site')}
                    />
                    <label htmlFor="typeSite">Сайт</label>
                    </ul><ul>
                    <input
                        type="radio"
                        id="typeEmail"
                        name="type"
                        value="email"
                        checked={type === 'email'}
                        onChange={() => setType('email')}
                    />
                    <label htmlFor="typeEmail">Электронная почта</label>
            </ul>

            <button type="submit">Сохранить</button>
            <button type="button" onClick={closeModal}>Отмена</button>
        </form>
    );
}


PassTable.jsx

import { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import useInput from '../hooks/useInput';
import passwordService from '../services/passwordService';
import './PassTable.css';

const PassTable = forwardRef(({ refreshData, ...props }, ref) => {
    const input = useInput();
    const [loading, setLoading] = useState(false);
    const [passwords, setPasswords] = useState([]);
    const [visiblePasswords, setVisiblePasswords] = useState({});

    const fetchData = async () => {
        setLoading(true);
        try {
            const passwordList = await passwordService.getAll();
            setPasswords(passwordList);
        } catch (error) {
            console.error('Ошибка при получении паролей:', error);
        } finally {
            setLoading(false);
        }
    };

    useEffect(() => {
        fetchData();
    }, []);

    useImperativeHandle(ref, () => fetchData);

    const handlePasswordClick = (id) => {
        setVisiblePasswords(prev => ({
            ...prev,
            [id]: !prev[id]
        }));
    };

    const handleDelete = async (id) => {
        try {
            await passwordService.deletePassword(id);
            setPasswords(prevPasswords => prevPasswords.filter(password => password.id !== id));
        } catch (error) {
            alert(`Ошибка: ${error.message}`);
        }
    };

    return (
        <>
            {loading ? <p>Загрузка...</p> : (
                <>
                    <input type="text" id="search" placeholder='Поиск...' {...input} />
                    <table {...props}>
                        <thead>
                            <tr>
                                <th></th>
                                <th>Наименование</th>
                                <th>Пароль</th>
                                <th>Время обновления</th>
                            </tr>
                        </thead>
                        <tbody>
                            {passwords
                                .filter(password => password.name.toLowerCase().includes(input.value.toLowerCase()))
                                .map(password => (
                                    <tr key={password.id}>
                                        <td>
                                            <span className='delete-btn' onClick={() => handleDelete(password.id)}>
                                                &times;
                                            </span>
                                        </td>
                                        <td>{password.name}</td>
                                        <td className='password-cell' onClick={() => handlePasswordClick(password.id)}>
                                            {visiblePasswords[password.id] ? password.password : '********'}
                                        </td>
                                        <td>{new Date(password.createdAt).toLocaleString()}</td>
                                    </tr>
                                ))}
                        </tbody>
                    </table>
                </>
            )}
        </>
    );
});

export default PassTable;



The blanks have already been written in the code, you need to direct them in the right direction

Using Python & Flask, how do I pass environment variables to a JavaScript file?

I have a web application that is coded with Python and uses Flask as the web framework. This app additionally has a JavaScript file that needs to perform an API call using an API key, for geocoding. I have a .env file with the environment variable, and am using dotenv for the Python file. How do I access the environment variable in the JavaScript file while maintaining security?

I have tried doing this by loading the variable to Python, then passing it to the HTML template using Jinja2, then passing that to the JavaScript file but this ends up exposing the API key in the HTML. Using process.env.APIKEY does not work for this, since I am not running the app using Node. I would like to perform this using best practices for security.

How to set elements and their values in local storage using a class selector , querySelectorAll?

  • I am trying to make a to do list and right now when I press on the add task button 2 inputs and 1 select element are being created and displayed on the page.I save the content and display it and its just the nodelist string

Now I know querySelectorAll gives a nodeList and local storage only stores strings.

  • How can I make the nodeList appear as the HTML elements and their values instead of the nodelist string?
  • My broken code:
//Implementing local storage
document.addEventListener("DOMContentLoaded",function() {
//Save sct1taskTable into localStorage
sct1SaveToLocalStorageBtn.addEventListener("click",() => {
        const taskTableContent = document.querySelectorAll(".task-table-child");
        localStorage.setItem("taskTableContentKey",taskTableContent);
        alert("Content saved :D");

})
//Retrieve sct1taskTable into localStorage
sct1LoadFromLocalStorageBtn.addEventListener("click",() => {
        const loadedTaskTableContent = localStorage.getItem("taskTableContentKey");
        sct1taskTable.innerHTML = loadedTaskTableContent;
        alert("Content loaded :D")
})
});

How can I display `n` lines in JavaScript without loading the entire file?

You have a multi-select file upload, and the goal is to display each file’s content in chunks of n lines, rather than loading the entire file at once, to prevent browser slowdowns or crashes.

<input class="form-control" type="file" id="formFileMultiple" name="uploadLogFile" multiple onchange="uploadFiles(event)" required>
<pre id='output'></pre>

Please let me know if there are better approaches to solve this problem. Thanks in advance!

My approach : I am getting the files in loop , loading whole file using file loader and displaying the data.

const uploadLogFiles = async (event) => {
    var resData = ''
    const fileLen = event.target.files.length

    // Convert the FileList into an array and iterate
    let files = Array.from(event.target.files).map(file => {
        // Define a new file reader
        let reader = new FileReader();
        // Create a new promise
        return new Promise(resolve => {
            reader.fileName = file.name
            reader.onload = function (evt) {
                resultData = `<label class="form-label">File Name - ${evt.target.fileName}</label>
                                         <pre style='max-height: 10em;'>${evt.target.result}</pre>`
                resolve(resultData);
            };
            // Read the file as a text
            reader.readAsText(file);

        });
    });
    // At this point you'll have an array of results
    let res = await Promise.all(files);
    for(var l=0; l<res.length; l++){
        resData +=res[l]
    }
    $('#output').html(resData)

}

**Expected Output : **

File Name - file1 
file data .....
File Name - file2 
file data .....
File Name - file3
file data .....

Remove quote of object key to avoid mongodb error of missing atomic operator

I do get the error Update document requires atomic operators and I think the problem is this part of my code:

const update: any = {}
const addToSet: any = {}

addToSet['parameters.temperature'] = {
    id: nanoid(10),
    value: 37,
}
// There are more calculations and assignments to the `addToSet` and `update` object

update.$addToSet = addToSet
console.log(update)

This returns:

{
    '$addToSet': {
        'parameters.temperature': { id: 'y9NSG4Dsb5', value: 37 }
    }
}

I think the quotes for $addToSet are wrong. How can I remove them?

Exception: Service Spreadsheets timed out while accessing document with id : error message while collecting data from another spreadsheet

While I am running manually a script to automatically send emails based on data in other tabs, I am getting this message very regularly, and it seem it happens between the 2 console.log in the code below.

I tried to add “SpreadsheetApp.flush()” as recommended in other threads.

Can you please help?

Here is the code :

function Email(linenumber) {
  // Fonction qui email la donnée de la ligne linenumber de l'onglet d'Email

  var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();


  // Obtenir les informations depuis l'onglet "Email" sur le travail à mener
  var emailSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email");
  var emailData = emailSheet.getDataRange().getValues();

  // Récupère le header de l'onglet Email
  headsEmailData = emailData[0];

  // Récupère les indexs des colonnes de l'onglet Email
  var idxObjectEmail = headsEmailData.indexOf("objectEmail");
  var idxSheetUrl = headsEmailData.indexOf("sheetUrl");
  var idxTablesEmail = headsEmailData.indexOf("tablesEmail");
  var idxAttachmentsEmail = headsEmailData.indexOf("attachmentsEmail");
  var idxAttachmentsType = headsEmailData.indexOf("attachmentsType");
  var idxBodyEmail = headsEmailData.indexOf("bodyEmail");
  var idxRecipientsEmail = headsEmailData.indexOf("recipientsEmail");
  var idxNoreplyEmail = headsEmailData.indexOf("noreplyEmail");
  var idxLastEmailDate = headsEmailData.indexOf("lastEmailDate");
  var idxLastEmailLength = headsEmailData.indexOf("lastEmailLength");
  var idxStartHour = headsEmailData.indexOf("startHour");
  var idxEndHour = headsEmailData.indexOf("endHour");
  var idxReplyTo = headsEmailData.indexOf("replyTo");



  // Parcourir la ligne linenumber ligne dans l'onglet "Email"
  var objectEmail = emailData[linenumber][idxObjectEmail];
  var sheetUrl = emailData[linenumber][idxSheetUrl];
  var attachmentsType = emailData[linenumber][idxAttachmentsType];
  var bodyEmail = emailData[linenumber][idxBodyEmail];
  var recipientsEmail = emailData[linenumber][idxRecipientsEmail];
  var noreplyEmail = emailData[linenumber][idxNoreplyEmail];
  var attachmentsEmail = emailData[linenumber][idxAttachmentsEmail].split(",");
  var tablesEmail = emailData[linenumber][idxTablesEmail].split(",");
  var replyTo = emailData[linenumber][idxReplyTo];

  // Extraire l'ID de la Google Sheet à partir du lien
  var sourceSpreadsheetId = extractSpreadsheetId(sheetUrl);
  var sourceSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetId);

  // Initialize email body
  var bodyEmail = bodyEmail + "<br>";

  
  //Ajout de emailOptions : Une variable emailOptions est créée pour stocker les options de l'email, avec htmlBody initialisé. Condition if pour noreplyEmail : Si noreplyEmail est égal à "TRUE" (indépendamment de la casse), noReply est ajouté à emailOptions. Appel de GmailApp.sendEmail : La fonction est appelée avec emailOptions comme argument.

  var emailOptions = { htmlBody: bodyEmail, attachments: [] };

  // Mise en place du no reply
  if (noreplyEmail.toString().toUpperCase() === "TRUE") {
    emailOptions.noReply = true;
  }

  if (replyTo) {
    emailOptions.replyTo = replyTo;
  }

  // ajout des PJ
  if (attachmentsEmail!=''){
    for (var j = 0; j < attachmentsEmail.length; j++) {
    var fileSheetName = attachmentsEmail[j].trim();
    var fileSheet = sourceSpreadsheet.getSheetByName(fileSheetName);

    // Vérifie la présence de l'onglet source
    if(fileSheet==null){
    SpreadsheetApp.getUi().alert("Un onglet de attachmentsEmail n'est pas présent dans le fichier source : "+fileSheet, SpreadsheetApp.getUi().ButtonSet.OK);
    return;
    }
    else {
        //Vérifie la présence de l'onglet
        var sheetTemp = sourceSpreadsheet.getSheetByName(fileSheetName+"_temp");
        if (!sheetTemp) {
          sheetTemp=sourceSpreadsheet.insertSheet(fileSheetName+"_temp");        
        }
console.log(fileSheetName+" vérification de la présence de l'onglet");
        SpreadsheetApp.flush();
        var totalRows = fileSheet.getLastRow();
        SpreadsheetApp.flush();
        var totalCols = fileSheet.getLastColumn();
        SpreadsheetApp.flush();
        var sourceRange = fileSheet.getRange(1,1,totalRows,totalCols);
        SpreadsheetApp.flush();
console.log(fileSheetName+" range récupéré");
        var targetRange = sheetTemp.getRange(1,1);
        sourceRange.copyTo(targetRange);
        sourceRange.copyTo(targetRange,SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS,false);
        sourceRange.copyTo(targetRange,SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
        SpreadsheetApp.flush();
        var url = "https://docs.google.com/spreadsheets/d/"+sourceSpreadsheetId+"/export"+"?format=xlsx"+"&gid="+sheetTemp.getSheetId();                                      
        var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
        var blob = UrlFetchApp.fetch(url, params).getBlob().setName(fileSheetName+".xlsx");
        emailOptions.at​​tachments.push(blob);
        sourceSpreadsheet.deleteSheet(sheetTemp);
    }
    }
  }


  GmailApp.sendEmail(recipientsEmail, objectEmail, "", emailOptions);

  }
}

I’m trying to access another spreadsheet to collect data, then to send it by email.
In the process of accessing the other doc, I get this unexpected message error as in the title : Exception: Service Spreadsheets timed out while accessing document with id