TypeScript no warning for (array | undefined).forEach

I’m running into a problem that TypeScript should solve for me, but it doesn’t. I have a value which is sometimes an array and sometimes null/undefined. I want to call forEach on this value, but I need to make sure that every time I call it, I’m using optional chaining to prevent errors. But TypeScript isn’t warning me when I leave out the optional chaining. I’ve tried many different ways of declaring this type, none of which have worked. I have a 10,000 line file that I’m trying to make run smoothly, and don’t want to have to keep hand-combing through to catch these problems.

maybeArray.forEach(...) -> maybeArray?.forEach(...)

Is there any way to get TypeScript to warn me when I leave off the optional chaining?

I’m using TypeScript 5.3.3 with Node.js in Visual Studio Code.

enter image description here

Here’s the simplest version:

const maybeArray: number[] | undefined = undefined;
maybeArray.forEach(val=>val++); // no TypeScript warning, but there should be.
// note that on the above line, mousing over maybeArray shows "const maybeArray: number[]".

I’ve also tried

type MaybeArray = number[] | undefined;

const maybeArray: MaybeArray = undefined;
maybeArray.forEach(val=>val++); // no TypeScript warning, but there should be.

And I’ve also tried

type MaybeArray = number[] | undefined;

const maybeArray = undefined;
(maybeArray as MaybeArray).forEach(val=>val++); // no TypeScript warning, but there should be.

And even

type MyObject = {
  maybeArray?: number[],
};

const myObject:MyObject = {};
(myObject.maybeArray).forEach(val=>val++); // no TypeScript warning, but there should be.

I thought I could get a useful result by using false instead of undefined, but false doesn’t work with optional chaining.

type MaybeArray = number[] | false;

const maybeArray = false;
(maybeArray as MaybeArray)?.forEach(val=>val++); // correct TypeScript warning because optional chaining doesn't work on FALSE.

tscongif:

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "noImplicitAny": false,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true,
    "target": "es6",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "typeRoots": ["./src/types","./node_modules/@types"],
    "strictNullChecks": false,
    "strict": false,
    "noEmitOnError": false,
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}

Eval() is not working in LWC Javascript, although it is working fine in LWC playground

I tried running this code in the LWC playground and it runs fine for me

When I try to run the same code inside a method in LWC component in salesforce (JavaScript), it’s throwing an error.

import {
  LightningElement
} from 'lwc';

export default class InputText extends LightningElement {

  handleCommit(event) {
    var value = event.target.value
    console.log("Value: " + value);

    let validationRule = 'A.length > 5';
    console.log("Validation Rule: " + validationRule);

    let n = validationRule.replace('A', 'value');
    console.log("N: " + n);

    let x = eval(n);
    console.log("X: " + x);

  }
}
<lightning-input type="text" label="Enter some text" oncommit={handleCommit}></lightning-input>

!ERROR

LWC Javascript Error

Why this error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined

I am trying to write a jest unit test for a react/typescript component but I keep getting the error

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.

I definitely did not import/export incorrectly. Does anyone know why I am getting this error?

My unit test file

import * as React from "react";
import { render } from "@testing-library/react";
import { DefaultTitleRenderer } from "./default-title-renderer"; // component that is failing
import { ApolloProvider } from "@test/frameworks-react-apollo";
import { createApolloClientMock } from "@test/utilities-test-apollo";
const mockClient = createApolloClientMock();

jest.mock("@test/components-1", () => ({
  use1Context: jest.fn(),
}));

jest.mock("@test/frameworks-react-apollo", () => ({
  useQuery: jest.fn(),
}));

describe("DefaultTitleRenderer", () => {
  it("renders the header title", () => {
    const { getByTestId } = render(
      <ApolloProvider client={mockClient}>
        <DefaultTitleRenderer />
      </ApolloProvider>
    );
    const pageHeader = getByTestId("example");
    expect(pageHeader).toBeInTheDocument();
  });
});

My DefaultTitleRenderer component

import * as React from "react";
import {
  StyledText,
  Button,
  Tooltip,
} from "@test/components-fluent-ui";
import { exampleQuery } from "@test/data-resolvers-example";
import { useQuery } from "@test/frameworks-react-apollo";


export const DefaultTitleRenderer : React.FunctionComponent<{}> = () => {
  const styles = styles();
  return (
    <div
      data-tid="example"
      className={styles.defaultHeader}
    >
      <HeaderTitle />
    </div>
  );
};

DefaultTitleRenderer.displayName = "DefaultTitleRenderer";

const HeaderTitle: React.FunctionComponent = () => {
  const { data } = useQuery(exampleQuery, {
    partialRefetch: true,
    notifyOnNetworkStatusChange: true,
    fetchPolicy: "cache-and-network",
    nextFetchPolicy: "cache-first",
  });

  const styles = someStyles();
  // more code here but not relevant
  return (
    <React.Fragment>
      <Tooltip
        content={"Go Back"}
        data-tid="test"
        positioning="below"
        relationship="label"
        children={
          <Button
            icon={<ArrowStartIcon />}
            appearance="transparent"
            data-tid="test2"
            onClick={handleBackNavigation}
          ></Button>
        }
      />
      <StyledText
        weight="bold"
        data-tid="header"
        aria-hidden="true"
        className={styles.titleText}
      >
        {data}
      </StyledText>
    </React.Fragment>
  );
};

why is my if statement executing event even when false

const mobileWidth = matchMedia('(max-width: 600px)');
if(mobileWidth.matches == true){
$(".super-category-button").click(function(){
    $(this).next().css('display','block');
    $(this).next().animate({left:'0px'},500);
})
$(".category-back-button").click(function(){
    $(this).parent().parent().animate({left:'1000px'},500);
    $(this).parent().parent().delay(500).queue(function(next){
        $(this).removeAttr('style');
        next();
    })
})
$(".sub-category-button").click(function(){
    $(this).next().slideToggle();
    return false;
})}
mobileWidth.addEventListener('change', (widthChange) => {
    if(widthChange.matches == true){
        console.log('yes');
    $(".super-category-button").click(function(){
    $(this).next().css('display','block');
    $(this).next().animate({left:'0px'},500);
})
$(".category-back-button").click(function(){
    $(this).parent().parent().animate({left:'1000px'},500);
    $(this).parent().parent().delay(500).queue(function(next){
        $(this).removeAttr('style');
        next();
    })
})
$(".sub-category-button").click(function(){
    $(this).next().slideToggle();
    return false;
})  
    }
})

when i start the screen under 600 and move to over the click events still work, when it loads over 600 it doesn’t work as expected. i am struggling to find a solution to when the screen size changes for the if statement to actually work how its suppose to

How to build an electron application for different Windows versions?

I have a problem with my Electron app. I want it to be build for win7 platform, but couldn’t find any appropriate ways to do it.

I have built my app for win10 platform via github release. But there is no option to build it for win7. I’ve tried to use an electron-packager, and it somehow worked, I got an .exe file for win7, but then, when I was trying to install it, nothing happened.

Chrome Extension Take Screenshot of Specific Element

I am making a chrome extension that can take a screenshot of a specific element, however, I am not sure how to take a screenshot ONLY of that element because captureVisibleTab takes a picture of the whole tab.

I tried using getBoundingClientRect to crop the bigger screenshot to the page, however it is giving incorrect values and doesn’t work properly.
I also tried using html2canvas however I had trouble using the library in an extension.

Page Transitions In Vike / React

I was trying to add page transitions to the Vike React boilerplate using React Transition Group

function Content({ children, url }) {
  const divRef = useRef();
  return (
    <div id="page-container">
      <SwitchTransition>
        <CSSTransition key={url} nodeRef={divRef} classNames="fade" timeout={400}>
          <div
            id="page-content"
            style={{
              padding: 20,
              paddingBottom: 50,
              minHeight: "100vh",
            }}
            ref={divRef}
          >
            {children}
          </div>
        </CSSTransition>
      </SwitchTransition>
    </div>
  );
}

I also tried using my own page transition component, which doesn’t need a key like url:

function Transition({ children }) {
  const [cloned, setCloned] = useState(cloneElement(children));
  const divRef = useRef();
  const firstRun = useRef(true);
  useEffect(
    function () {
      if (firstRun.current) {
        firstRun.current = false;
        return;
      }
      divRef.current.style.opacity = 0;
      let timeout = window.setTimeout(function () {
        divRef.current.style.opacity = 1;
        setCloned(cloneElement(children));
      }, 400);
      return function () {
        window.clearTimeout(timeout);
      };
    },
    [children, setCloned]
  );
  return (
    <div style={{ transition: "opacity 400ms" }} ref={divRef}>
      {cloned}
    </div>
  );
}

They both work well in different contexts, but here they both gave me a weird error when I navigate from the dynamic route (/star-wars) in the boilerplate to a static route:

Uncaught TypeError: (intermediate value)() is undefined
    Page +Page.jsx:6
    React 11
    workLoop scheduler.development.js:266
    flushWork scheduler.development.js:239
    performWorkUntilDeadline scheduler.development.js:533
    ...

So I have two questions:

  1. What does (intermediate value)() is undefined mean and where should I start to debug this?
  2. The React docs say about cloneElement:

Using cloneElement is uncommon and can lead to fragile code. See common alternatives.

But React Transition Group uses it, and I think Framer Motion’s AnimatePresence uses it as well. So is there a better way to achieve some kind of page transition or view transition (where you freeze a component in place until it animates away)?

Troubleshooting CORS Issues with OpenAI API on a Website Served Over Ngrok

I am currently facing a persistent Cross-Origin Resource Sharing (CORS) issue that is preventing users from successfully using the OpenAI API on my website. My setup involves a website served over a secure HTTPS connection (https://www.bookgenerator.xyz), which interacts with a backend server exposed to the internet through Ngrok, substituting the localhost environment. This backend server is designed to handle requests to the OpenAI API.

However, the functionality works flawlessly only when accessed from my Mac’s Chrome browser; it fails across all other devices and browsers, including Safari on Mac and Chrome on different machines. Users attempting to use the OpenAI API through the website encounter a “preflight response not successful” error, which indicates that the CORS preflight checks are failing.

Here are the specific details and steps I have taken:

  1. Frontend Setup: The frontend is a simple HTML page that collects user input and sends it to the backend via JavaScript’s Fetch API. The requests are directed to the Ngrok URL of my local server.

  2. Backend Setup: My backend is an Express.js application running on Node.js. It uses the cors middleware to handle CORS issues. The server is designed to relay the requests it receives to the OpenAI API and return the responses back to the frontend.

  3. Ngrok Configuration: I use Ngrok to create a tunnel to my localhost, which provides me with a public HTTPS URL. I have verified that the Ngrok tunnel is functional and correctly configured to forward requests to my local server.

  4. CORS Middleware: In my Express.js setup, I have the CORS middleware in place. I have tried both the simple app.use(cors()); setup and more detailed configurations specifying the origin, methods, and headers. Despite this, the preflight requests seem to be unsuccessful.

  5. Successful Local Testing: When testing locally on my Mac using Chrome, the application works without any CORS issues. The requests to the OpenAI API are successful, and the expected functionality is achieved.

  6. Failure on Other Devices/Browsers: When accessing the website from other devices and browsers, the preflight request fails, indicating that the CORS headers are not being recognized or are missing from the response.

  7. Error Messages: The console error indicates that the preflight request has been blocked due to the lack of the Access-Control-Allow-Origin header in the preflight response. Additionally, a net::ERR_FAILED message is observed, which could suggest network-related problems or issues with the Ngrok service itself.

I am looking for assistance in resolving these CORS issues so that all users can interact with the OpenAI API through my website, regardless of their device or browser. The solution needs to ensure that the CORS preflight checks are passed and that the API can be accessed as intended in a secure and reliable manner.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI Book Writer</title>
    <link rel="icon" type="image/x-icon" href="aibookgenerator.ico">

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.4.0/jspdf.umd.min.js"></script>
</head>
<body class="bg-gray-100 font-sans leading-normal tracking-normal">
    <main class="container mx-auto max-w-4xl p-8 bg-white rounded-lg shadow-xl mt-6"> <!-- Adjusted max-width here -->
        <h1 class="text-4xl text-center text-gray-800 font-bold mb-6">AI Book Writer</h1>
        <p class="text-center text-gray-600 mb-10">Download PDF Upon Completion</p>
        <div class="space-y-4">
            <div class="number-inputs-form flex items-center">
                <label for="chapter-input" class="text-sm font-medium text-gray-700 mr-2">Number of Chapters: </label>
                <input type="number" class="form-input w-1/7 border-2 border-black rounded-md" id="chapter-input" min="1" max="1">
            </div>
            <div class="number-inputs-form flex items-center">
                <label for="subchapter-input" class="text-sm font-medium text-gray-700 mr-2">Number of Subchapters per Chapter: </label>
                <input type="number" class="form-input w-1/7 border-2 border-black rounded-md" id="subchapter-input" min="1" max="3">
            </div>
            <div class="number-inputs-form flex items-center">
                <label for="paragraph-input" class="text-sm font-medium text-gray-700 mr-2">Number of Paragraphs per Subchapter: </label>
                <input type="number" class="form-input w-1/7 border-2 border-black rounded-md" id="paragraph-input" min="1" max="7">
            </div>
            
            <form id="topic-form" class="mt-8">
                <input type="text" id="topic-input" placeholder="Enter A Topic (Examples: Concord Jet, Quantum Computing)" class="form-input mt-1 block w-full border-2 border-black rounded-md py-3">
                <button type="submit" class="mt-4 w-full bg-blue-500 text-white py-2 px-4 rounded hover:bg-blue-700">Generate Book</button>
            </form>
        </div>
        
        
        <div id="loading-message" class="hidden text-center mt-4"></div>
    
        <!-- New upgrade button (initially hidden) -->
        <button id="upgrade-button" class="hidden mt-4 w-full bg-red-500 text-white py-2 px-4 rounded hover:bg-red-700" onclick="https://www.bookgeneratorupgrade.xyz';">
            Get Free Trial for Unlimited Full Book Generation
        </button>

        <div id="book-content" class="mt-4"></div>
    </main>
<script>
    let tocEntries = []; 

    document.getElementById('topic-form').addEventListener('submit', async (e) => {
        e.preventDefault();
        const topic = document.getElementById('topic-input').value;
        let var_i = parseInt(document.getElementById('chapter-input').value);
        let var_j = parseInt(document.getElementById('subchapter-input').value);
        let var_k = parseInt(document.getElementById('paragraph-input').value);

        // Set default values if inputs are empty or invalid
        var_i = (!var_i || var_i < 1 || var_i > 5) ? 1 : var_i;
        var_j = (!var_j || var_j < 1 || var_j > 4) ? 3 : var_j;
        var_k = (!var_k || var_k < 1 || var_k > 8) ? 7 : var_k;

        document.getElementById('book-content').innerHTML = ''; // Clear previous content
        showLoadingMessage(); // Start the loading message
        await generateBookContent(topic, var_i, var_j, var_k); // Pass the user-defined values to the function
        clearInterval(loadingInterval); // Stop the loading message
        document.getElementById('loading-message').style.display = 'none'; // Hide loading message
        document.getElementById('upgrade-button').style.display = 'block';  // Display the upgrade button
    });






    const generateBookContent = async (topic, var_i, var_j, var_k) => {
        let lastChapterTitle = ""; // Initialize variable for the last chapter title.
        let lastSubchapterTitle = ""; // Initialize variable for the last subchapter title.
        let tocEntries = []; 

        for (let i = 1; i <= 1; i++) {
            const chapterPrompt = `Generate a unique chapter title for the topic: ${topic}, distinct from the last title: ${lastChapterTitle}, and keep title less than 4 words. Also don't include double quotes around title.`;
            const chapterTitleMessage = [{ role: 'user', content: chapterPrompt }];
            const chapterTitleRaw = await sendToBackend(chapterTitleMessage); // Send only the current message
            const extractedChapterTitle = extractGeneratedText(chapterTitleRaw, chapterPrompt);
            const chapterTitle = extractedChapterTitle.startsWith('Chapter') ? extractedChapterTitle : `Chapter ${i}: ${extractedChapterTitle}`;
            displayChapter(chapterTitle);
            lastChapterTitle = chapterTitle; // Update the last chapter title

            for (let j = 1; j <= var_j; j++) {
                const subchapterPrompt = `Generate a unique subchapter title for ${chapterTitle} and keep title less than 6 words. Book is about ${topic}. Do not include ${i}:${j} so example, do not include anything like "1.2 Growing" and do not include any double quotes in this subchapter title` ;
                const subchapterTitleMessage = [{ role: 'user', content: subchapterPrompt }];
                const subchapterTitleRaw = await sendToBackend(subchapterTitleMessage); // Send only the current message
                const extractedSubchapterTitle = extractGeneratedText(subchapterTitleRaw, subchapterPrompt);
                const subchapterTitle = `${extractedSubchapterTitle.startsWith('Subchapter') ? extractedSubchapterTitle : `${extractedSubchapterTitle}`}`;
                displaySubchapter(subchapterTitle);
                lastSubchapterTitle = subchapterTitle; // Update the last subchapter title
                tocEntries.push({ title: subchapterTitle, type: 'subchapter', chapter: i, subchapter: j });


                let previousParagraph = '';

                for (let k = 1; k <= var_k; k++) {
                    let paragraphPrompt;
                    if (i === 1 && j === 1 && k === 1) {
                        // Specific prompt when both j and k are 1
                        paragraphPrompt = `Write a single, concise paragraph for the opening text of this book about ${topic} starting in subchapter about ${subchapterTitle}, Include Real historical examples or interesting true story examples if relevant."`;
                    } else {
                        // General prompt for other cases
                        paragraphPrompt = `Write a single, concise paragraph (number ${k}) for ${subchapterTitle}, following the previous content without repeating or introducing new subtopics. Include Real historical examples or interesting true story examples if relevant. The book is about ${topic}. Focus on continuing the discussion seamlessly: "${previousParagraph}"`;
                    }
                    const paragraphMessages = [{ role: 'user', content: paragraphPrompt }];
                    const paragraphHistory = paragraphMessages.concat({ role: 'system', content: previousParagraph }); // Only remember the previous paragraph
                    const paragraphResponse = await sendToBackend(paragraphHistory);
                    const paragraph = extractGeneratedText(paragraphResponse, paragraphPrompt); // Function to extract the generated text
                    if (paragraph) {
                        // displayParagraph(paragraph);
                        displayParagraph(`${paragraph}`);
                        previousParagraph = paragraph; // Set the last paragraph for the next iteration
                    } else {
                        // Handle the case where paragraph content is not generated properly
                        console.error('Failed to generate paragraph content.');
                    }
                }
            }
        }
        const subscriptionNote = "nnnTo access the remaining chapters, please upgrade.";
        displayParagraph(subscriptionNote, 'bold-red-text'); // Display the final note with bold red styling

    };

    let loadingInterval; // Declare this outside so you can clear it later

    function showLoadingMessage() {
        const loadingElement = document.getElementById('loading-message');
        loadingElement.style.display = 'block';
        loadingElement.style.color = '#00D100'; // Make the text color green
        let dotCount = 0;
        loadingElement.innerText = 'Generating Book';

        loadingInterval = setInterval(() => {
            dotCount = (dotCount + 1) % 4; // Reset after 3 dots
            loadingElement.innerText = 'Generating Book' + '.'.repeat(dotCount);
        }, 500); // Update every 500 milliseconds
    }


    function extractGeneratedText(response, prompt) {
        // Check if the response contains the prompt text
        if (response.includes(prompt)) {
            // Extract and return the text after the prompt
            return response.split(prompt)[1].trim();
        } else {
            // The response does not contain the prompt, return the whole response or handle accordingly
            return response;
        }
    }

    const sendToBackend = async (messages) => {
        const response = await fetch('https://c258-50-218-62-78.ngrok-free.app/chat', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ messages })
        });
        const data = await response.json();
        return data.completion;
    };

    

    const displayChapter = (title) => {
        const element = document.createElement('h2');
        element.innerText = title;
        element.className = 'text-2xl font-bold text-gray-800 mt-6 mb-4'; // Larger and bolder text
        document.getElementById('book-content').appendChild(element);
    };


    const displaySubchapter = (title) => {
        const element = document.createElement('h3');
        element.innerText = title;
        element.className = 'text-xl font-semibold text-gray-700 mt-4 mb-2'; // Prominent but smaller than chapter titles
        document.getElementById('book-content').appendChild(element);
    };


    const displayParagraph = (text, className = '') => {
        const paragraphElement = document.createElement('p');
        paragraphElement.innerText = text;
        if (className) {
            paragraphElement.className = className; // Add the class if provided
        }
        document.getElementById('book-content').appendChild(paragraphElement);

        const breakElement = document.createElement('br'); // Create a new line break element
        document.getElementById('book-content').appendChild(breakElement); // Append the line break for extra spacing
    };

    // ... (rest of your code, no changes until the download button event listener) ...
    document.getElementById('upgrade-button').addEventListener('click', function() {
        // Handle the click event, e.g., redirect to the upgrade page or show a message
        window.location.href = 'https://www.bookgeneratorupgrade.xyz'; // Redirect to the exact upgrade page (change the URL as needed)
    });



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

Here is my index.js backend.


import express from "express";
import bodyParser from "body-parser";
import cors from "cors";
import path from 'path';
import { fileURLToPath } from 'url';
import openaiPackage from 'openai';

const { Configuration, OpenAIApi } = openaiPackage;
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const configuration = new Configuration({
    organization: "XXXXXX",
    apiKey: "XXXXXXXXX", // censored for privacy 
});
const openai = new OpenAIApi(configuration);

const app = express();
const PORT = process.env.PORT || 3000;

// Use cors middleware to handle CORS requests
app.use(cors());

app.use(bodyParser.json());

app.post("/chat", async (req, res) => {
    const { messages } = req.body;
    
    try {
        const completion = await openai.createChatCompletion({ 
            model: "gpt-3.5-turbo",
            messages: messages
        });
        res.json({completion: completion.data.choices[0].message.content});
    } catch (error) {
        console.error("Error processing the OpenAI API request:", error);
        res.status(500).json({ error: "Error processing your request" });
    }
});

app.get('/home.html', (req, res) => {
    res.sendFile(path.join(__dirname, 'home.html'));
});

// Handle root URL ("/")
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'home.html'));
});

app.listen(PORT, () => {
    console.log(`Server listening at http://localhost:${PORT}`);
});




getting Cannot read properties of undefined (reading ‘_id’) error

I am getting this error again and again even trying different methods it is not getting fixed
auth.js

const Errorhandler = require("../utils/errorhandler");
const catchAsyncErrors = require("./catchasyncerror");
const jwt = require("jsonwebtoken");
const User = require("../model/usermodel");

exports.isAuthenticatedUser = catchAsyncErrors(async (req, res, next) => {
  const { token } = req.cookies;

  if (!token) {
    return next(new Errorhandler("Please Login to access this resource", 401));
  }

  try {
    const decodedData = jwt.verify(token, process.env.JWT_SECRET);

    req.user = await User.findById(decodedData.id);

    // Assuming "user_id" is the name of the cookie
    const userId = req.cookies.user_id;
    const name= req.user.name;

    // Set the user ID in req.user._id
    req.user._id = userId;
    req.user.name=name;

    next();
  } catch (error) {
    return next(new Errorhandler("Invalid token. Please login again.", 401));
  }
});

exports.authorizeRoles = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return next(
        new Errorhandler(
          `Role: ${req.user.role} is not allowed to access this resource `,
          403
        )
      );
    }

    next();
  };
};

productcontroller.js

exports.createProductReview = catchasyncerror(async (req, res, next) => {
    const { rating, comment, productId } = req.body;
  
    const review = {
      user: req.user._id,
      name: req.user.name,
      rating: Number(rating),
      comment,
    };
  
    const product = await Product.findById(productId);
  
    const isReviewed = product.reviews.find(
      (rev) => rev.user.toString() === req.user._id.toString()
    );
  
    if (isReviewed) {
      product.reviews.forEach((rev) => {
        if (rev.user.toString() === req.user._id.toString())
          (rev.rating = rating), (rev.comment = comment);
      });
    } else {
      product.reviews.push(review);
      product.numOfReviews = product.reviews.length;
    }
  
    let avg = 0;
  
    product.reviews.forEach((rev) => {
      avg += rev.rating;
    });
  
    product.ratings = avg / product.reviews.length;
  
    await product.save({ validateBeforeSave: false });
  
    res.status(200).json({
      success: true,
    });
  });
  

productmodel.js

const mongoose=require("mongoose");

const productSchema=new mongoose.Schema({
    name:{
    type:String,
    required:[true,"please enter product name"]
        },
    description:{
        type:String,
        required:[true,"please enter product description"]

    },
    price:{
        type:Number,
        required:[true,"please enter product description"],
        maxLength:[6,"please enter under limit"]
    
    },
    ratings:{
        type:String,
        default:0
    },
    images:[
     {
        publicId:{
            type:String,
            required:true
        },
        imageurl:{
            type:String,
            required:true
        }
     }
    ],
    category:{
        type:String,
        required:[true,"please enter product category"],
        maxLength:[6,"please enter under limit"]

    },
    productStock:{
        type:Number,
        required:[true,"please enter product stock"],
        maxLength:[3,"please dont exceed product stock under 1000"]

    },
    numberofReviews:{
        type:Number,
        default:0
    },
    reviews:[
        {
            // user: {
            //     type: mongoose.Schema.ObjectId,
            //     ref: "User",
            //     required: true,
            //   },
            name:{
                type:String,
                required:[true,"name should be there"]
            },
            rating:{
                type:Number,
                required:true
            },
            Comment:{
                type:String,
                required:true
            }
        }
    ],
    // user: {
    //     type: mongoose.Schema.ObjectId,
    //     ref: "User",
    //     required: true,
    //   },
    createdAt:{
        type:Date,
        default:Date.now
    }



})

module.exports=mongoose.model("product",productSchema);

Please help me with this issue Thanks!!

i expected api run successfully on put req but it is giving error that it is not reading data from cookie

even after replacing req.user with req.auth its still not working

How can I automatically generate a html contents page and on-page links to the next and previous page with names?

I am writing an online non-fiction history book. To keep it simple, it is about ancient empires etc.
I have written the whole thing manually in html and css. I have a table of contents page with links to every page. On each page there is a link forward and back with the title of the respective page. These have all been done manually.
My problem is that reorganization or insertion or deletion is time-consuming and error-prone. Let’s say I have pages for Egypt, Greece, and Rome. I decide to insert Babylon between Egypt and Greece. I must modify the contents page and the links on Egypt and Greece. If I later rename Greece to Hellas, I must modify the the title everywhere again.

What I need is a system where I can name each page and drag and drop them in the order I want and everything will be generated automatically.

What is the best way for a SPA to retrieve a large json file

I’m developing a SPA using Angular and the app will be making a request to retrieve a large JSON file. The file is expected to grow beyond 2MB.

I’m curious… if I partition the JSON file into smaller pieces and make multiple async calls to retrieve them (and assemble the data in memory) will the download be faster?

I’ll be caching the data in local storage, but if the data isn’t there, the rendering of the page will be held up until the transfer is complete. I’m trying to minimize load time.

Dynamically Adding row with jQuery is not working with Select element

In my form I have an input and select fields. With the code below rows can get added dynamically on clicking Add row button. However after adding 2 select rows the jquery stopped working. I tried many approaches but failed to make it work. Also tried adding the dropdown list in ViewBag property and pass it in jquery but still no success.

Below is my code

View

@if (Model != null && Model.Count > 0)
            {


                
                for (int j=0;j < Model.Count;j++)
                {
                    <tr style="border:1px solid black">
                        <td>@Html.DropDownListFor(a => a[j].ProjectsList, ViewBag.Proj as SelectList, new { @class = "form-control" })</td>
                        <td>@Html.TextBoxFor(a => a[j].Task, new { @required = "required", @class = "form-control" })</td>
                        <td>@Html.DropDownListFor(a=> a[j].Status, ViewBag.EnumList as SelectList,new { @class = "form-control" })</td>
                        <td>@Html.TextBoxFor(a => a[j].UserId, new { @class = "id", @type = "hidden" })</td>
                        <td>@Html.TextBoxFor(a => a[j].Email, new { @class = "email", @type = "hidden" })</td>
                        <td>@Html.TextBoxFor(a => a[j].Date, new { @type = "hidden" })</td>
                        <td></td>
                        <td>
                            @if (j > 0)
                            {
                                //<a href="#" class="remove btn btn-warning" id="delete">Remove</a>
                                <button class="remove btn btn-warning" id="delete">Remove</button>
                            }
                        </td>
                    </tr>
                   
                }
            }

jQuery

$("#addNew").click(function (e) {
                e.preventDefault();
                var $tableBody = $("#dataTable");
                var $trLast = $tableBody.find("tr:last");
                var e = $(".email").val();
                var id = $(".id").val();
                var $trNew = $trLast.clone();

                debugger;
                var suffix = $trNew.find(':input:first').attr('name').match(/d+/);
                $trNew.find("td:last").html('<a href="#" class="remove btn btn-warning" id="delete">Remove</a>');
                $.each($trNew.find(':input'), function (i, val) {
                    // Replaced Name
                    var oldN = $(this).attr('name');
                    var newN = oldN.replace('[' + suffix + ']', '[' + (parseInt(suffix) + 1) + ']');
                    $(this).attr('name', newN);
                    //Replaced value
                    var type = $(this).attr('type');
                    if (type.toLowerCase() == "text") {
                        $("#id").attr('value', id);
                        $("#email").attr('value', e);
                    }

                    // If you have another Type then replace with default value
                    $(this).removeClass("input-validation-error");

                });
                $trLast.after($trNew);

                // Re-assign Validation
                var form = $("form")
                    .removeData("validator")
                    .removeData("unobtrusiveValidation");
                $.validator.unobtrusive.parse(form);
            });