Puppeteer with browser context opens an extra window windows

For some reason, puppeteer seems to open two browser windows with this code. One with just one tab and it’s about:blank. The other one starts with about:blank and redirects to the actually goes to the URL specified.

System : Ubuntu 22.04,

Google Chrome for Testing 131.0.6778.87 (Official Build) (64-bit)

const puppeteer = require('puppeteer-extra')
const fs = require('fs');
const cookiesPath = "cookies.txt";
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
const { createCursor } = require("ghost-cursor")
puppeteer.use(StealthPlugin())

 ...

 cookies = JSON.parse(cookies)

  let args = []
  if(proxy) {
    args.push(`--proxy-server=${proxy}`)
  }

  puppeteer.launch({ headless: false, args: args }).then(async browser => {
    const context = await browser.createBrowserContext()
    await context.setCookie(...cookies)

    let page = await context.newPage()
    let finalUserAgent = userAgent || defaultUserAgent
    console.log('Attempting to login w existing session..')
    await page.setUserAgent(finalUserAgent)
    await page.setDefaultNavigationTimeout(100000); // 90 seconds

  
    await page.goto(url)
    //await page.waitForTimeout(5000)
    //await browser.close()
    console.log(`logged in`)
  })
  console.log(userAgent, proxy);
  res.send("browser launched with session");

Any kind of help is much appreciated.

Add new DOM element in Runtime using Node JS

In my server.js, I have a listener using tmi.js that gets the comments from a twitch channel, and I want to create a new DOM element everytime a new comment appears to display it on the page.

What is the best approach for this? I’ve been trying EJS but I don’t think that is possible using it.

Thanks in advance.

How can I embed an Express session into a Next.js application using NextAuth for authentication?

I have a Next.js frontend and an Express backend. My backend handles user authentication, and I use a JWT token for authentication and store it in the Express session. I want to connect this flow with NextAuth for authentication in Next.js, but I am facing issues with managing and persisting the Express session in the browser and passing it back to Express.

Backend Express Login code

 export class Login {

  public async login(req: Request, res: Response): Promise<Response> {
   
    const { email, password }: Pick<UserInterface, 'email' | 'password' > = req.body;

    // Check if user exists with the given email
    const user = await prisma.user.findUnique({
      where: { email },
    });

    if (!user) {
        throw new BadRequestError('Invalid email or password');
    }

    // Compare the provided password with the stored hashed password using bcrypt
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
     throw new BadRequestError('Invalid email or password');
    }

    // Generate a JWT token
    const token = jwt.sign(
      { email: user.email, username: user.username, role: user.role }, // Payload
      config.JWT_SECRET,             // Secret key for signing the token
      { expiresIn: '1h' }                                     // Token expiration time
    );

    req.session = {jwt: token};
 
    // Return a success message (without sending the token directly in the response body)
    return res.status(200).json({
      message: 'Login successful', token, role: user.role
    });
  }
}

Now for each route I have to use this middleware to check for the the validity of the JWT token stored in the session:

export class AuthMiddleware {
  public verifyUser(req: Request, _res: Response, next: NextFunction): void {
    if (!req.session?.jwt) {
      throw new NotAuthorizedError('Token invalid');
    }

    try {
      const payload: AuthPayload = JWT.verify(req.session?.jwt, config.JWT_SECRET) as AuthPayload;
      req.currentUser = payload;
    } catch (error) {
      throw new NotAuthorizedError(`Token invalid. Please login again: ${JSON.stringify(error)}`);
    }

    next();
  }
}

export const authMiddleware: AuthMiddleware = new AuthMiddleware();

example:

export default(app:Application) => {
    const routes = () =>{
    
        app.use(BASE_PATH, authMiddleware.verifyUser, unitsRoutes.routes());
     
    };

    routes();
};

I am using cookieSession to manage sessions in Express. It works well with Postman.

public Start(): void {
    this.securityMiddleware(this.app);
   // other middlewares come in here
  }

  private securityMiddleware(app: Application): void {
    app.use(
      cookieSession({
        name: 'session',
        keys: [config.SECRET_COOKIE_KEY_ONE!, config.SECRET_COOKIE_KEY_TWO!],
        maxAge: 24 * 7 * 3600000,
        // secure: config.NODE_ENV !== 'development'
          secure: false,
          signed:false,
          httpOnly:false,
          sameSite:'none',
      })
    );
    app.use(cookieParser()); // Use cookie-parser to access cookies in req.cookie
    app.use(hpp());
    app.use(helmet());
    app.use(
      cors({
        origin: '*',
        credentials: true,
        optionsSuccessStatus: 200,
        methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS']      
      })
    );
  }

The issue I’m facing is when integrating NextAuth for authentication in a Next.js project using the Credentials provider. My expectation is that once the user is authenticated by the backend and a cookieSession is created, the response should automatically set the req.session cookie on the browser, along with the appropriate headers as defined by the cookieSession middleware on the backend. However, this is not happening. There appears to be a barrier in how NextAuth handles response headers from a remote server. Even after successful authentication and the creation of a cookieSession by the backend, NextAuth generates its own session cookie, overriding / ignoring the backend’s session cookie. As a result, to use the backend’s session cookie, I must manually fetch it from the response headers and set it myself. Unfortunately, this process doesn’t seem to integrate well with NextAuth, as it continues to use its own session mechanism. Here’s the NextAuth configuration with the CredentialsProvider:

import { NextApiRequest, NextApiResponse } from "next";
import type { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
type NextAuthOptionsCallback = (req: NextApiRequest, res: NextApiResponse) => NextAuthOptions

export interface AuthPayload {
    // userId: string;   
    email: string;
    username: string;
    role: 'admin' | 'user';
  }

  export const options: NextAuthOptionsCallback = (_req: NextApiRequest,res: NextApiResponse) =>{
    return {
        providers: [
            CredentialsProvider({
              name: "Credentials",
              credentials: {
                email: {
                  label: "email:",
                  type: "text",
                  placeholder: "Enter your email",
                },
                password: {
                  label: "Password:",
                  type: "password",
                  placeholder: "Enter password",
                },
              },
              async authorize(credentials) {                 
               
                const response = await fetch("http://localhost:8081/api/v1/login", {
                  method: "POST",
                  body: JSON.stringify(credentials),
                  headers: { "Content-Type": "application/json" },                 
                });
 
        
                const user = await response.json();
        
                // If no error and we have user data, return it
                if (response.ok && user) {
                    const cookies = response.headers.get('set-cookie')
                    if (cookies) {                       
                        // Set the cookie from the backend to the response
                        res.setHeader('Set-Cookie', cookies);
                      }                   
                  return user;
                }
                // Return null if user data could not be retrieved
                return null;
              },
            }),
          ],
        
        
          // Callbacks to handle JWT and Session data
          callbacks: {
            async jwt({ token, user }) {
            // Save user details (email, username, role) to the JWT token
            if (user) {
                // Save user details (email, username, role) to the JWT token
                // token.email = user.email;  
                console.log('user is ', user)
                token.token = user.token
                token.role = user.role;
                token.session = user.token
              }
              return token;
            },
            // using the role in client component
            // async session({ session, token }) {
            //     console.log('Session callback reached');
            //     console.log('Token in session callback: ', token); // Check the token structure
            //     console.log('session is ',session)
            //     if (session) {
            //         // session.user.email = token.email;
            //         // session.user.username = token.username;
            //         console.log('token is ', token);
            //         session.session.jwt = token.session
            //         // session.user.session= token.session
            //         // session.user.role = token.role;
            //       }
            //       return session;
            // },
          },
    }
  }

So, everytime i send a request back to express and use credentials as true eg

export const InventoryApi = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: process.env.NEXT_PUBLIC_API_BASE_URL,
  
    credentials: "include"
  }),

it is the cookieSession by nextAuth that is getting sent to the backend and not the original session generated by express.
Example:

{
  'next-auth.csrf-token': '8a1e7c846d2bd62d8b167195c3c949a822aa9fe98b2005b0dde809021115e3dd|00ecab2216e215e08efda994dc4141185a502e43c61a983d227c57e624fbb212',
  'next-auth.callback-url': 'http://localhost:3000',
  'next-auth.session-token': 'eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..vnmck6_magHu4k3t.fQpkxzXRA2A5W3YKiIPV9N0ahVfs_KFsM4_2P9_1D2YgcbM7y9zKNvSLiNOhvglh14E4cdet4nKIBSL5gXHKIeHV266hJrpsLwuA9KP6pgTrwiRpR8UeaN5KtKeRkfoa45H9wv7EnXewifZ1Y1vvOSAGDwu9owOMusa5RT6CtulLpXNsr6BCLJ1U-fHCQUP5YEowhozciqKaoXgkVfhz0PZNd7hoqDaBM8x8uMhHX-JiXgSN_j78fH97_H255SRU2j0dut9Z194Wiv76U5IFbXXP4ZRBX6D3N5FArvmlNaP99hiIoQJxNL0ve1kFUNzOQcEhCaAj3SkT3rU1qncogVy8l9E1wipXfac9binjhCkG08PPVwpquLWe97eNHDYMbQI_LcIflDDnhKYcldZbkwEyLng3Jw5lV8A1UfP9vPRkz37wILJp-bMmigu3zQYcJw8GXSTGY36PMOAd42zd-4B5zHq5oz0okCukCPNAXFK915-HMvZsi0Iq5TbFgjAWNHHwRvSKT927ZKDMUsldHTxTy4M_cI6h-VZl5GFF6ZSC2x6m6LdzxqPylb8rTrfCIv4sQr-M9VD_3Q7Fc05ikibxuNOc2nWz3QyelTOtg7G_gnPwzYyXbKtBZGxePxIsR-K93-WCbEd2vuA53MxX35FEXfRjtGaqVqlsQShCCSfpljRbtRpFJOa4Bk6EGqMbTcQHgV8oaFHW4mcgXR6TOX5kmdfqpMQyRV_QD90q6rou2iSIU8-0PuWxo_N4P1xSGTWUYr2I1INX46UlhW7wWj8p7AAMs3uxN03ZcfV7kbQi2fWKQUH-adDbAzykjWVmwvuDnVGZOMndG4_1wUIo.WApg0cuxigjTu7gaM6RY7g'
}

My understanding is that express cannot work with ‘next-auth.session-token’ since it did not generate it . so am not able to verify the user since that sessioncookie canot be understood by express. Again, Even if I manually set the session header or try to sync the session from NextAuth to my Express app, NextAuth’s session token is still not usable directly by Express. The reason is that NextAuth’s session is independent, and the token it uses is encrypted and signed with NextAuth’s secret, which my Express app doesn’t have

How can I persist the session created by my Express backend on the browser and ensure that it’s sent back to the backend in subsequent requests,

I understand that one option is to manually fetch the token on the client side and embed it in each request as a payload. However, I don’t want to take this approach, as it defeats the purpose of securely storing the session on the browser. The goal is for the session to be automatically managed and sent with each request, without manually handling the token in every request.

I’ve researched and tried several approaches, including manipulating cookies, and configuring both NextAuth and the backend for cross-domain authentication on my CORS. However, it became increasingly difficult to get everything working as expected. From my findings, it seems NextAuth is primarily made for single-domain applications, and when it comes to handling cross-domain scenarios like mine, things become tricky. That’s why I’m turning to StackOverflow for help, hoping to find a solution that properly integrates the backend session with NextAuth on the frontend or a way forward or maybe am doing it wrong.

I am also aware this kind of question but not detailed was asked here before but not answered. How Can I Send the NextAuth Session Token to Express.js Server for Authentication

Post on all profiles

I have to create a social network project equivalent to facebook and I am in the process of publishing a message on the administrator’s profile, on his friend’s profile as well as on all profiles using boostrap 5 and following instructions that I am asked to make. I am in the process of posting messages on the profile and I am blocked when the administrator publishes a message about any member. In the browser when I try to post a “Hello” I get an error message telling me POST http://localhost:3000/api/postAllProfiles 403 (Forbidden)
(anonymous) and Error while publishing the message: Error: Error while publishing the message
at HTMLFormElement.<anonymous. Apparently my mistake would come from the scripts.js side on this part
your text//// Form to post a message to all the administrator’s profiles..

document.addEventListener("DOMContentLoaded", function () {
const postAllProfilesForm = document.getElementById("postAllProfilesForm");
const allProfilesMessagesList = document.getElementById(
"allProfilesMessagesList"
);
postAllProfilesForm.addEventListener("submit", async function (event) {
event.preventDefault();
const message = document.getElementById("postAllprofilesMessage").value;
try {
const response = await fetch(
"http://localhost:3000/api/postAllProfiles",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: Bearer ${localStorage.getItem("token")},
},
body: JSON.stringify({ content: message }),
}
);
if (!response.ok) {
throw new Error("Erreur lors de la publication du message");
}
const data = await response.json();
alert("Message publié avec succès sur tous les profils !");
postAllProfilesForm.reset();
loadAllProfilesMessages();
} catch (error) {
console.error("Erreur lors de la publication du message : ", error);
alert("Erreur lors de la publication du message : " + error.message);
}
```  But I can't find what's wrong. Can you please help me find the solution? Thank you all. Best regards




Webpack Module Federated Microfrontend and ViteJS

I have an existing Microfrontend built using Webpack Module Federation. So basically, I have a Host app and 3 child applications (all of them currently built using ReactJS/Webpack)

Now, I want to introduce a new micro frontend app and it is going to be a React app (but I want to build this app in a modern way using ViteJS instead of the conventional way and avoid using react-scripts)
However, I want to avoid using the existing Host app and the other child apps (since they are already live in Production and I do not want to do introduce any regression for them)

My question is if it is possible to do that i.e. have a mix of both. Anything specific that I need to take care of ?

Dom manipulation: “Value is required” even though there is a value in the web form field

I am developing an autofill plugin to autofill workday form, this is part of my program:

const lastNameInput = document.querySelector('[data-automation-id="legalNameSection_lastName"]');
if (lastNameInput) {
  lastNameInput.value = 'Last Name';
  lastNameInput.setAttribute('value', 'Last Name');
  await delay(1000);
  console.log(lastNameInput);
}
<input
    type="text"
    data-automation-id="legalNameSection_lastName"
    id="input-6"
    aria-required="true"
    class="css-1p1ka2x"
    value=""
    aria-describedby="error1-input-6"
    aria-invalid="true"
/>

As shown here:

“Value is required” issue

After I autofill the value using my program, the value appears in the user interface and the HTML element.

However, when I click the “Save and Continue” button, an error pops up, indicating that the field is empty.

I need to manually click the input field to fi x it.

How to ressolve this issue

cannot access own properties in javascript constructor

I have a base class and another that extends it, how can I access fields in the constructor?

class BaseModel {
    constructor() {
        console.log('no fields :(')
        console.log(this.fields)
        this.fields.map((field) => {
            field.label = field.label || field.name;
        })
    }
}

class UserModel extends BaseModel {
    fields = [
        { name: 'id' },
        { name: 'name' },
        { name: 'email' },
    ];
    constructor(name, email) {
        super();
        this.name = name;
        this.email = email;
    }
}

const user = new UserModel('bob', '[email protected]');
console.log(user);

I went about 2 pages deep and didn’t find a satisfactory answer of how to set this up. The best I found was to set a timeout in the constructor which seemed wrong.

Unable to fetch userinfo using access_token from auth0

I am trying to build a simple authentication library, and I am using axios instead of library built by auth0. I am unable to fetch the userdata using the access code. I am also using google provider for authentication.

import axios from 'axios'

export default class Auth {
    constructor(
        private domain: string,
        private client_id: string,
        private redirect_uri: string
    ) {}

    startAuthFlow(): string {
        const params = new URLSearchParams({
            response_type: 'code',
            client_id: this.client_id,
            redirect_uri: this.redirect_uri,
            scope: 'offline_access'
        })
        const authURI = `https://${this.domain}/authorize?${params.toString()}`
        return authURI
    }

    async handleCallback(code: string) {
        return await this.exchangeCodeForToken(code)
    }

    async getUserInfo(accessToken: string) {
        const userInfoEndpoint = `https://${this.domain}/userinfo`
        try {
            const response = await axios.get(userInfoEndpoint, {
                params: {
                    scope: "openid profile email"
                },
                headers: {
                    Authorization: `Bearer ${accessToken}`
                }
            })
            return response.data
        } catch (error) {
            throw error
        }
    }

    async refreshToken(refresh_token: string) {
        const tokenEndpoint = `https://${this.domain}/oauth/token`
        const payload = {
            grant_type: 'refresh_token',
            client_id: this.client_id,
            refresh_token
        }
        try {
            const response = await axios.post(tokenEndpoint, payload, {
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            return response.data
        } catch (error) {
            throw error
        }
    }

    private async exchangeCodeForToken(code: string) {
        const tokenEndPoint = `https://${this.domain}/oauth/token`
        const payload = {
            grant_type: 'authorization_code',
            client_id: this.client_id,
            client_secret: 'B60OCXAoe7KqIkwLTqHeDlLBMFYtMh6kLw7WAXJl0qCMXDyJzROHyAJr449LKXz9',
            code,
            redirect_uri: this.redirect_uri,
            scope: 'openid profile email'
        }
        try {
            const reponse = await axios.post(tokenEndPoint, payload)
            const { access_token, id_token, refresh_token } = reponse.data
            return { access_token, id_token, refresh_token }
        } catch (error) {
            throw error
        }
    }
}


I am using this library in a express application to test it.

const express = require('express')
const Auth = require('../auth').default
const auth = new Auth('dev-k2t4k3888k1ic1rm.us.auth0.com', 'Zg2GuO5NfJMFVbZsbRVn8naqFUJNKZdU', 'http://localhost:3000/callback')

const app = new express()

app.get('/', (req,res) => {
    return res.send('Hello')
})

app.get('/login', (req, res) => {
    res.redirect(auth.startAuthFlow())
})

app.get('/callback', async (req, res) => {
    const { code } = req.query
    try {
        const { access_token } = await auth.handleCallback(code)
        console.log(access_token)
        const user = await auth.getUserInfo(access_token)
        console.log("USER: ", user)

        res.redirect('/')
    } catch (error) {
        console.log(error)
        return res.status(404).send(error)
    }
})

app.listen(3000, () => {
    console.log('Server running on port 3000')
})

Can anyone help me why I am not able to fetch the user data? I can see the userdata in my auth0 dashboard
enter image description here

Greasemonkey: change text in HTML

I have looked at several solutions for similar problems in here but I wasn’t able to understand either

The webpage I’m trying to edit has the following bit:

<h4 data-v-42b52bab="" class="title is-4 mt-4">Behemoth <!----></h4>

I’m trying to make it say “Plots 19, 20, 21, 49, 50, 51” instead of Behemoth

What I attempted was:

var strongElems = document.getElementsByClassName('is-4');

for (var i=0; i<strongElems.length; i++)
{
  var thisElem = strongElems[i];
   thisElem.textContent = "Plots 19, 20, 21, 49, 50, 51"; // change it
}

But it doesn’t seem to work. What can I do?

How can one avoid the 5-second “lack of user activation” timeout for the file picker in Firefox?

I’m trying to avoid the dreaded ” picker was blocked due to lack of user activation” error when clicking on an <input type="file"> element. I know you think you’re seen this question before many times, but wait. This one is different.

Most/all other questions are about dispatching a click event on a file input element programmatically (.click()), but having it fail to open a picker for lack of user activation (i.e., a physical click).

In JavaScript can I make a “click” event fire programmatically for a file input element?

How can I programmatically open the file picker with JavaScript?

Firefox can’t override “<input> picker was blocked due to lack of user activation” in about:config

`<input>` picker was blocked due to lack of user activation when programmatically trying to open File Load dialog

This question involves physically clicking the file input element, but checking interactively if the user really wants to select a file now.

  1. The user clicks a button (or something that looks like a button) to load a file.
  2. If there are unsaved changes, the program prompts the user with a warning. The user can cancel the load.
  3. If not cancelled, the program opens a file picker. The user selects a file.
  4. The program replaces the current file buffer contents with the selected file.

I’ve implemented (a simplified version of) that ideal flow with the first “button” below. However, there’s a problem. If the user waits more than 5 seconds to decide that it’s okay to load the file, the picker refuses to open with the “lack of user activation” error logged in the console.

Less ideally, I’ve implemented an alternate flow with the second “button” below.

  1. The user clicks a button (or something that looks like a button) to load a file.
  2. The program opens a file picker. The user selects a file.
  3. If there are unsaved changes, the program prompts the user with a warning. The user can cancel the load.
  4. If not cancelled, the program replaces the current file buffer contents with the selected file.
( function () {
  'use strict';

  function onChange1( e ) {
    alert( 'contents overwritten' );
  }

  function onClick1( e ) {
    if (
      !confirm(
        'There are unsaved changes.n' +
        'Is it OK to discard them?' )
    ) {
      e.preventDefault();
    }
  }

  function onChange2() {
    if (
      confirm(
        'There are unsaved changes.n' +
        'Is it OK to discard them?' )
    ) {
      alert( 'contents overwritten' );
    }
  }

  function onContentLoaded() {
    var
      input1 = document.getElementById( 'input1' ),
      input2 = document.getElementById( 'input2' );

    input1.addEventListener( 'click', onClick1 );
    input1.addEventListener( 'change', onChange1 );

    input2.addEventListener( 'change', onChange2 );
  }
  document.addEventListener( 'DOMContentLoaded', onContentLoaded, { once: true } );
} () );
div {
  background-color: #eee;
  display: inline-block;
}
input {
  display: none;
}
label {
  line-height: 2;
  padding: 0.5em;
}
<!DOCTYPE html><html lang="en"><head>
  <title>Stack Overflow QA</title>
  <link rel="stylesheet" href="page.css">
  <script src="page.js"></script>
</head><body>
  <div><label><input id="input1" type="file">Open File 1 ...</label></div>
  <div><label><input id="input2" type="file">Open File 2 ...</label></div>
</body></html>

I really prefer the first flow, so I’d like to find a way around the 5-second timeout. I’m specifically interested in a Firefox solution, even if it might apply to other browsers, as well.

CSS and JavaScript

I want to learn CSS and Javascript and I want a learning platform which has text info plus videos I can follow. Reading alone is not helping me

I have tried W3schools but I cannot seem to follow their content properly due to the order.

How to generate dynamic metadata from an Angular component using node js?

I want to create a library with components example pages generated automatically by a node js code.
Using some Copilot help, I got this function to read the component’s metadata, but it is returning me empty. My knowledge in node is not so developed yet and I want to understand the process, not only copy from AI.
This is the function with the interfaces – the code is in typescript for node.
The function receives the angular component file path as parameter

interface InputMetadata {
  name: string;
  type: string | null;
  defaultValue: string | null;
}

interface ComponentMetadata {
  selector: string;
  standalone: boolean;
  inputs: InputMetadata[];
}

// Function to read component metadata
function readComponentMetadata(componentPath: string): ComponentMetadata {
  const componentFile = fs.readFileSync(componentPath, 'utf-8');
  const sourceFile = ts.createSourceFile(componentPath, componentFile, ts.ScriptTarget.Latest, true);
  const inputs: InputMetadata[] = [];
  let selector: string = '';
  let standalone: boolean = false;

  function visit(node: ts.Node) {
    if (ts.isClassDeclaration(node) && node.decorators) {
      node.decorators.forEach(decorator => {
        if (ts.isCallExpression(decorator.expression) && decorator.expression.expression.getText() === 'Component') {
          const args = decorator.expression.arguments;
          if (args.length) {
            const componentMetadata = args[0] as ts.ObjectLiteralExpression;
            componentMetadata.properties.forEach(property => {
              if (ts.isPropertyAssignment(property)) {
                if (property.name.getText() === 'selector') {
                  selector = (property.initializer as ts.StringLiteral).text;
                } else if (property.name.getText() === 'standalone') {
                  standalone = (property.initializer.kind === ts.SyntaxKind.TrueKeyword);
                }
              }
            });
          }
        }
      });
    }
    if (ts.isPropertyDeclaration(node) && node.decorators) {
      node.decorators.forEach(decorator => {
        if (ts.isCallExpression(decorator.expression) && decorator.expression.expression.getText() === 'Input') {
          const name = node.name.getText();
          const type = node.type ? node.type.getText() : null;
          const initializer = node.initializer ? node.initializer.getText() : null;
          inputs.push({name, type, defaultValue: initializer});
        }
      });
    }
    ts.forEachChild(node, visit);
  }

  visit(sourceFile);
  return {selector, standalone, inputs};
}

The file must be “compiled” using npx tsc and then the js file can be called.

The node and typescript I’m using are:

"devDependencies": {
  "@types/node": "^22.10.1",
  "typescript": "^5.7.2"
}

This is the tsconfig.json file:

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

Best Practices for Navigation and Data Exchange in React with index.js

I am creating an inventory tracking/event management software for internal use with my AV company using Expo/React Native. Looking at navigation and data exchange between screens, and it seems that everyone has a strong and differing opinion on how this should be handled. I’d like to learn what the preferred approaches/best practices are and why.

I have a database storing 3 main types of data: Gear, Technicians, and Events. The app has 3 screens as separate components:

  1. Inventory, an inventory tracking sheet. This will use Gear and Event data so that I can determine when a piece of Gear is available etc.
  2. Calendar, a calendar view of upcoming Events. This will use Events, Gear, and Technician data so that I can filter by what Gear is being used by an Event and what Technician is working, etc.
  3. Finance, several balance sheets to track finances. This will use Gear, Event, and Technician data so that I can get information about Technician rates, Event income, and Gear expenditure.

As you can see, almost all screens need access to all data. Right now, I’m pulling down the data from Firebase in my index.tsx. Index will not have a visible component, the “home” screen will default to calendar and I am implementing a nav bar to switch between the three screens (using expo-navigation or react-native-navigation). I’m using index purely to handle navigation between screens and fetch/organize/update shared data between the screens. I will implement logins/permissions eventually.

What are some best practices for these screens to exchange/share information? I’ve identified a few recommendations.

  1. Global variables: Storage in a separate globals.tsx for Gear, Technician, and Event lists with getters and setters so that index can pull down and parse data to store it there, and the individual screens can utilize it. It seems that some manage this with tools like Redux/Flux.
  2. Passing data via routes: With navigators like react-native-navigation, parameters can be passed between screens. Index.tsx would still act as storage/distribution for the data.
  3. Independent components: Each component pulls the data it needs independently. Index only handles navigation. Multiple screens would pull the same data on the render of each.

For each of these, some say never to do it, and other sware by it. I’ve also been advised against using an index file at all (navigation is handled by the screens between themselves, data is pulled by each component as needed). Is there an advantage to having a centralized navigation and data distribution handler like index? Isn’t an index file necessary? Is it best practice to treat it as a parent from which everything obtains data, or the main entry point which pulls data and components from elsewhere?

I’m not sure why I got a downvote, please leave a comment if I’ve missed something. I understand I have not included code but rather described my project structure, if this is an issue or I’ve formatted this incorrectly let me know, I am learning. Thank you knowledgeable people!

array return [object Object] on any kind of interaction, if returned from a class why?

Intro

I’m currently trying to get to know how spa commonly work, router, state, route etc,
I’ve done a basic hash router and can display on a fragment element, and now trying to introduce a custom react like component, but arrived to placeholder {{ }} replacement, I’ve been stuck for days on an error which, even if I’ve found a work around, still do not even begin to understand. it seems like if returned from within class constructor i cannot use […].join(“”) or […][1] without it to interpreted as [object Object]

Code & How it happened

In order not to interfere with nested component i settled for a DFS through child Node of my component
and delegated the parsing to a sub class, the specific condition handling that being :

      if (current && current?.getAttribute) {
          current.innerHTML = new _Fo_Component_PlaceholderParser({ node: current, content: current.innerHTML })
      }

in the _Fo_Component_PlaceholderParser


class _Fo_Component_PlaceholderParser {

    constructor({ node, content }) {
         this.node = node;

         return this.placeholderParser(content);
    }

     placeholderParser(value) {
        if(value.trim === "") {
            return value
        }
        
        const parts = value.split(/(</?w+[^>]*>)/g);

        const stack = [];
        let output = [];

        for (let part of parts) {
            const trimmedPart = part.trim();

            if (/^<w+[^>]*>$/.test(trimmedPart)) {
                stack.push(trimmedPart);
                const processedTag =
                    stack.length === 1
                        ? trimmedPart.replace(/{{.*?}}/g, "testing")
                        : trimmedPart;

                output.push(String(processedTag));

                if (this.isSelfClosing(trimmedPart)) {
                    stack.pop();
                }
            } else if (/^</w+>$/.test(trimmedPart)) {
                stack.pop();
                output.push(String(trimmedPart));
            } else if (/{{.*?}}/.test(trimmedPart) && stack.length === 0) {
                output.push(String(trimmedPart.replace(/{{.*?}}/g, "testing")));
            } else if (trimmedPart.length > 0) {
                output.push(String(trimmedPart));
            }
        }

        return output.join("");
    }

//rest of the method ...
}

To come to where my problem pops up, it’s in the _Fo_Component_PlaceholderParser. This class directly returns
this.placeholderParser(), which itself returns output.join("").

Except, on the DOM, output.join("") says [object Object] even though, when logged during the process,
it contains the parsed data that should be returned.

For proof, if instead I return simply output, it shows perfectly as an array in the DOM, comma-separated.

So output.join("") shouldn’t be a problem, right?
And also, it’s not only .join.
If I try output[0], it also says [object Object], so building a string out of output by hand doesn’t work—it’ll just return [object Object] [object Object] [object Object]....

And don’t even think my logic has anything to do with that—I cut it out and replaced output with ["test", "it works"].
It did the exact same thing, even when I did nothing to the array. The values were hardcoded and directly returned, but it behaved the same way. Just why?

What’s happening here?

It only works if I return output directly and do the joining from my DFS condition as:

if (current && current?.getAttribute) {
    current.innerHTML = new _Fo_Component_PlaceholderParser({ node: current, content: current.innerHTML }).join("")
}

What I Need Help With

  1. Why does output.join(“”) return [object Object] in the DOM when returned from the class?
  2. Is this related to how JavaScript handles the return value of a class constructor?
  3. What’s the proper way to fix this issue?

Perfectly template/indent it in NextJS?

I am working on a Leetcode clone for my practice and projects. I have a PostgreSQL db where I have the questions and the answer template that will be viewed in the coding area. But the indentation do not come in place and thus impacting user experience.

The website

Please suggest me ways to fix this.