Data in two different pages does not get updated immediately on UI with Redux Toolkit

I have a react 18 app and I am using Redux Toolkit for state management.

Below is an image of the blogs app on the users page. When I add/create a new blog on the blogs page, the new blog gets added properly. However, when I navigate to the users page the user in the box should have 3 blogs instead of 2. So, the number of blogs created by the user does not get updated immediately. But, when I reload the page the users page shows me the new number of blogs i.e., 3 for the user in the box.

enter image description here

QUESTION: How can I make the users page also reactive to when I add a new blog without doing a reload?

Below are some of my files.

blogReducer.js file:

import { createSlice } from '@reduxjs/toolkit';
import blogService from '../services/blogs';
import { setNotification } from './notificationReducer';

const blogSlice = createSlice({
  name: 'blogs',
  initialState: [],
  reducers: {
    setBlogs(state, action) {
      const sortedBlogs = [...action.payload].sort((a, b) => b.likes - a.likes);
      return sortedBlogs;
    },
    appendBlog(state, action) {
      state.push(action.payload);
    },
    increaseLikes(state, action) {
      const id = action.payload;
      const blogToVote = state.find((blog) => blog.id === id);
      const blogUpdated = {
        ...blogToVote,
        likes: blogToVote.likes + 1,
      };
      const blogList = state.map((blog) =>
        blog.id !== id ? blog : blogUpdated,
      );
      const sortedBlogs = blogList.sort((a, b) => b.likes - a.likes);
      return sortedBlogs;
    },
    removeBlog(state, action) {
      console.log('removeBlog action payload from blogReducer', action.payload);
      return state.filter((blog) => blog.id !== action.payload);
    },
  },
});

export const { setBlogs, appendBlog, increaseLikes, removeBlog } =
  blogSlice.actions;

export const initializeBlogs = () => {
  return async (dispatch) => {
    console.log('initializing blogs from blogReducer');
    const blogs = await blogService.getAllBlogs();
    dispatch(setBlogs(blogs));
  };
};

export const createBlog = (blog) => {
  console.log('creating blog');
  return async (dispatch) => {
    try {
      const newBlog = await blogService.createBlog(blog);
      dispatch(appendBlog(newBlog));
      dispatch(
        setNotification(
          { message: `SUCCESS: Added ${newBlog.title} blog.`, isError: false },
          5000,
        ),
      );
    } catch (error) {
      console.log('ERROR when creating blog: ', error.message);
      dispatch(
        setNotification(
          { message: error.response.data.error, isError: true },
          5000,
        ),
      );
    }
  };
};

export const voteBlog = (id, title) => {
  console.log('voting blog');
  return async (dispatch) => {
    try {
      const blogToVote = await blogService.getBlogById(id);
      console.log('voted blog', blogToVote);
      const blogUpdated = {
        ...blogToVote,
        likes: blogToVote.likes + 1,
      };
      await blogService.updateBlog(blogUpdated);
      dispatch(increaseLikes(id));
    } catch (error) {
      console.log('ERROR when voting blog: ', error.message);
      dispatch(
        setNotification(
          {
            message: `Blog '${title}' was removed from the server.`,
            isError: true,
          },
          5000,
        ),
      );
    }
  };
};

export const deleteBlogById = (id) => {
  console.log('deleting blog');
  return async (dispatch) => {
    try {
      await blogService.deleteBlog(id);
      console.log('deleted blog');
      dispatch(removeBlog(id));
    } catch (error) {
      console.log('ERROR when deleting blog: ', error.message);
      alert('Sorry! Blog was already removed from the server.');
    }
  };
};

export default blogSlice.reducer;

userReducer.js file:

import { createSlice } from "@reduxjs/toolkit";
import userService from '../services/users';

const userSlice = createSlice({
  name: 'users',
  initialState: [],
  reducers: {
    setUsers(state, action) {
      const sortedUsers = [...action.payload].sort();
      return sortedUsers;
    }
  },
});

export const { setUsers } = userSlice.actions;

export const initializeUsers = () => {
  return async (dispatch) => {
    console.log('initializing users from userReducer');
    const users = await userService.getAllUsers();
    dispatch(setUsers(users));
  }
}

export default userSlice.reducer;

loginReducer.js file:

import { createSlice } from '@reduxjs/toolkit';

const loginSlice = createSlice({
  name: 'loggedInUser',
  initialState: null,
  reducers: {
    setLoginUser(state, action) {
      return action.payload;
    },
    setLogoutUser() {
      return null;
    },
  },
});

export const { setLoginUser, setLogoutUser } = loginSlice.actions;

export default loginSlice.reducer;

App.jsx file:

import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Route, Routes } from "react-router-dom";
import { initializeBlogs } from './reducers/blogReducer';
import { initializeUsers } from './reducers/userReducer';
import Notification from './components/Notification';
import LoginPage from './pages/LoginPage';
import BlogsPage from './pages/BlogsPage';
import UsersPage from './pages/UsersPage';
import MenuBar from './components/MenuBar';

const App = () => {
  const dispatch = useDispatch();
  const loggedInUserFromStore = useSelector(({ loggedInUser }) => loggedInUser);
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  useEffect(() => {
    if (loggedInUserFromStore) {
      dispatch(initializeBlogs());
      dispatch(initializeUsers());
    }
  }, [loggedInUserFromStore, dispatch]);

  return (
    <div>
      <h1>Blogs App</h1>

      <MenuBar setUsername={setUsername} setPassword={setPassword} />

      <Notification />
      
      <LoginPage 
        username={username} 
        password={password} 
        setUsername={setUsername} 
        setPassword={setPassword} 
      />

      <Routes>
        <Route path='/users' element={loggedInUserFromStore && <UsersPage /> } />
        <Route path='/' element={loggedInUserFromStore && <BlogsPage /> } />
      </Routes>
    </div>
  );
};

export default App;

BlogsPage.jsx file:

import { useRef } from 'react';
import Togglable from '../components/Togglable';
import NewBlogForm from '../components/NewBlogForm';
import BlogsList from '../components/BlogsList';
import { useDispatch } from 'react-redux';
import { createBlog } from '../reducers/blogReducer';

const BlogsPage = () => {
  const dispatch = useDispatch();
  const blogFormRef = useRef();

  const addBlog = (newBlog) => {
    blogFormRef.current.toggleVisibility();
    dispatch(createBlog(newBlog));
  };

  const blogForm = () => (
    <Togglable buttonLabel="new blog" ref={blogFormRef}>
      <NewBlogForm createBlog={addBlog} />
    </Togglable>
  );

  return (
    <>
      {blogForm()}
      <BlogsList />
    </>
  );
}

export default BlogsPage;

BlogsList.jsx file:

import { useSelector } from 'react-redux';
import Blog from './Blog';

const BlogsList = () => {
  const blogsFromStore = useSelector(({ blogs }) => blogs);

  return (
    <>
      <h1>Blogs</h1>

      <ul style={{ listStyleType: 'none', padding: 0 }}>
        {blogsFromStore.map((blog) => (
          <Blog key={blog.id} blog={blog} />
        ))}
      </ul>
    </>
  );
}

export default BlogsList;

Blog.jsx file:

import { useState } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { deleteBlogById, voteBlog } from '../reducers/blogReducer';

const Blog = ({ blog }) => {
  // styles
  const blogStyle = {
    paddingLeft: 10,
    paddingRight: 10,
    paddingBottom: 10,
    border: 'solid',
    borderWidth: 1,
    marginBottom: 5,
  };
  const removeBtnStyle = {
    backgroundColor: 'lightblue',
    padding: 5,
    borderRadius: 10,
    fontWeight: 'bold',
  };

  const [viewBlogInfo, setViewBlogInfo] = useState(false);
  const dispatch = useDispatch();
  const loggedInUserFromStore = useSelector(({ loggedInUser }) => loggedInUser);

  const handleLikes = () => {
    dispatch(voteBlog(blog.id, blog.title));
  };

  const handleDeleteBlog = () => {
    const toDelete = window.confirm(`Delete "${blog.title}" blog?`);
    console.log({ toDelete });

    if (toDelete) {
      dispatch(deleteBlogById(blog.id));
    }
  };

  const toggleShow = () => {
    setViewBlogInfo(!viewBlogInfo);
  };

  return (
    <li style={blogStyle} className="blog">
      <p>
        <span data-testid="title">{blog.title} </span>
        <button onClick={toggleShow} className="viewHideBtn">
          {viewBlogInfo ? 'hide' : 'view'}
        </button>
      </p>

      {viewBlogInfo && (
        <div>
          <div>
            <div>Author: {blog.author}</div>

            <div>
              <span data-testid="likes">Likes: {blog.likes}</span>
              <button onClick={handleLikes} className="likeBtn">
                like
              </button>
            </div>

            <div>URL: {blog.url}</div>

            <div>Added by: {blog.user.name}</div>
          </div>

          <br />

          {blog.user.username === loggedInUserFromStore.username && (
            <div>
              <button
                style={removeBtnStyle}
                onClick={handleDeleteBlog}
                className="removeBtn"
              >
                remove
              </button>
            </div>
          )}
        </div>
      )}
    </li>
  );
};

Blog.propTypes = {
  blog: PropTypes.shape({
    id: PropTypes.string,
    title: PropTypes.string.isRequired,
    author: PropTypes.string.isRequired,
    url: PropTypes.string.isRequired,
    likes: PropTypes.number,
    user: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired,
      username: PropTypes.string.isRequired,
    }),
  }).isRequired,
};

export default Blog;

NewBlogForm.jsx file:

import { useState } from 'react';
import PropTypes from 'prop-types';

const NewBlogForm = ({ createBlog }) => {
  const [newBlogTitle, setNewBlogTitle] = useState('');
  const [newBlogAuthor, setNewBlogAuthor] = useState('');
  const [newBlogUrl, setNewBlogUrl] = useState('');

  const addBlog = (event) => {
    event.preventDefault();
    createBlog({
      title: newBlogTitle,
      author: newBlogAuthor,
      url: newBlogUrl,
    });
    setNewBlogTitle('');
    setNewBlogAuthor('');
    setNewBlogUrl('');
  };

  return (
    <div>
      <h2>Create a new blog</h2>

      <form onSubmit={addBlog}>
        <div>
          title:
          <input
            data-testid="blog-title"
            value={newBlogTitle}
            onChange={(event) => setNewBlogTitle(event.target.value)}
            name="title"
            id="blog-title"
          />
        </div>

        <div>
          author:
          <input
            data-testid="blog-author"
            value={newBlogAuthor}
            onChange={(event) => setNewBlogAuthor(event.target.value)}
            name="author"
            id="blog-author"
          />
        </div>

        <div>
          url:
          <input
            data-testid="blog-url"
            value={newBlogUrl}
            onChange={(event) => setNewBlogUrl(event.target.value)}
            name="url"
            id="blog-url"
          />
        </div>

        <button type="submit">create</button>
      </form>
    </div>
  );
};

NewBlogForm.propTypes = {
  createBlog: PropTypes.func.isRequired,
};

export default NewBlogForm;

UsersPage.jsx file:

import UsersList from "../components/UsersList";

const UsersPage = () => {
  return <UsersList />;
}

export default UsersPage;

UsersList.jsx file:

import { useSelector } from "react-redux";

const UsersList = () => {
  const usersFromStore = useSelector(({ users }) => users);

  console.log('<UsersList /> component - usersFromStore: ', usersFromStore);

  return (
    <>
      <h1>Users</h1>

      <table>
        <thead>
          <tr>
            <th>names</th>
            <th>blogs created</th>
          </tr>
        </thead>

        <tbody>
          {usersFromStore.map(user => (
            <tr key={user.id}>
              <td>{user.name || user.username}</td>
              <td>{user.blogs.length}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </>
  );
}

export default UsersList;

Passing blob URLs from main to renderer in Electron

I want to load images from paths given by the user (possibly modify them) and to display them using electron.
I used to use Electron many years ago and then it was quite easy since access to ‘fs’ node module was still unrestricted. Now, if I want to use ‘fs’ in the renderer I get error messages like this one:

Uncaught Error: Module “fs” has been externalized for browser compatibility. Cannot access “fs.existsSync” in client code.

So my solution was to load the file in the main process to a blob, create an URL for the blob and pass it to the renderer using IPC. This is a minimal example:

main.ts

export async function loadWebpFromFile(path: string) {
    const fileContents = await fs.promises.readFile(path, null);
    const webpImage = new Blob([fileContents], {
      type: 'image/webp',
    });

    return URL.createObjectURL(webpImage);
}

ipcMain.handle(
  'getWebpUrl',
  (event: any, path: string) => loadWebpFromFile(path),
);

preload.ts

contextBridge.exposeInMainWorld('fromMain', {
  getWebpUrl: async (path: string) => {
    return ipcRenderer.invoke('getWebpUrl', path);
  },
});

App.ts

const App = () => {
  const [webpUrl, setWebpUrl] = useState<string>("");
  
  useEffect(() => {
    (async () => {
      const webpUrl = await (window as any).fromMain.getWebpUrl ("C:\images\a.webp");
      setWebpUrl(webpUrl);
    })();
  }, []);
  return (
    <div>
      <h1>ElectroVite</h1>
      <img src={webpUrl} />
    </div>
  );
};

But I get the following error in the console:

Not allowed to load local resource: blob:nodedata:985f076a-f83d-4fb8-82e3-5826401afed1 localhost/:1

So how can I exactly access this URL. Why is it even blocked? Or perhaps should I use a completely different approach?

The example is based on the following Typescript-React-Vite boilerplaite:
https://github.com/guasam/electrovite-react

clipboard content doesn’t modifiy html input files array, why?

I have a form in which I let the user add up to 5 files in a way that I only show one <input type="file"> and if the user do put a file at the <input> then I update the form adding another input and so on. It works pretty well when I use the file picker and choose a file. But now I’m trying to add an option so the user can just CTRL+V an image clipboard content directly into the <input> field and then update the form as said before. I also added a loop verifying if the input fields do have content so the user don’t update, like, the 0th input and then a new input emerges for no necessity. And that’s the point that making my code fail as shown below:

<form class="form-post" role="form" method="POST" enctype="multipart/form-data" action="/someroute">
<!-- other inputs... -->
<input class="novo-post-form-item form-post-file-input" name="arquivos[]" type="file" onchange="addNovoInputFile(this, 5)">

</form>

on the page’s JS:

var addNovoInputFile = function(elem, max){
    fileInputs = $('.form-post-file-input');

    // When this loop is reached from a copypaste event, the content of fileInputs[0].files is empty
    // this doesn't happen when I just select a file from filepicker 
    for(var i=0; i < fileInputs.length; i++)
    {
        if(fileInputs[i].files.length === 0)
            return;
    }
    // I put this loop so I don't update the form in case, for example, if the user keeps updating a file at the 0th <input>
    // but maybe my solution is just changing the logic of this loop
    
    if(fileInputs.length >= max || elem.files.length === 0)
        return;
    
    var novoInput = "<div class="form-post-file-input-box">";
    novoInput += "<input class="novo-post-form-item form-post-file-input" name="arquivos[]" type="file" onchange="addNovoInputFile(this, " + max + ")">";
    novoInput += "</div>"
    
    $(novoInput).appendTo(".form-post #form-post-file-input-div");
};

// New event I just added in order to fill the input with a printscreen content in the clipboard
window.addEventListener('paste', e => {
    let inputs = document.getElementsByName('arquivos[]');
    let inputToChange = inputs[inputs.length-1];

    if(e.clipboardData.files.length > 0){
        inputToChange.files = e.clipboardData.files;
        addNovoInputFile(inputToChange, 5);
    }
});

Pass values when doing a redirect, so these values are accessible in another file [duplicate]

If in Members.jsx I have

const showMembers = () => {
   const [state, setState] = useState('create');

   return (
     ...
     <Button href="/CreateMember" value={4} onClick={setState('edit')}>Edit</Button>
     ...
   )
}

Now when that button is clicked, I want to send (or see) the value and the state to another file called CreateMember.jsx, as seen in the href. So basically, when the button is clicked, redirect user to /CreateMember, with the value 4 and ‘edit’.

How can I do this?

In CreateMember.jsx, I have something like this

const CreateMember = () => {
  let state = state Recieved From The redirect
  const id = id Recieved From The redirect

  if(state === 'edit')
    fetch('/api/getMemberByID', {
            method: 'post',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({id: id})
        })
    }
   else { ... }
}

—————— Update ———————

I’m using Routes like below

import { BrowserRouter, Route, Routes } from 'react-router-dom';
function App() {  
  return (
    <>
      <Buttons />
      <BrowserRouter>
        <Routes>
          <Route path='/' element={<Content />}></Route>
          <Route path='/CreateMember' element={<Content />}></Route>         
          <Route path='*' element={<PageNotFound />}></Route>
        </Routes>
      </BrowserRouter>
    </>
  );
}

The Content just looks like this

const Content = () => {
    const URL = window.location.pathname.split('/')[1];
    const renderPage = (url) => {
        switch (url) {
            case 'CreateMember':
                return CreateMember()
            ...
            default:
                return PageNotFound()
        }
    }

    return (
        renderPage(URL)
    )
}

No Overload Matches This Call with drizzle-orm and Postgres

I’m working with drizzle-orm to insert data into a PostgreSQL database using Node.js. However, I’m running into the following TypeScript error when trying to insert a post with an authorId that references a users table:

No overload matches this call.
  Overload 1 of 2, '(value: { title: string | SQL<unknown> | Placeholder<string, any>; content: string | SQL<unknown> | Placeholder<string, any>; }): PgInsertBase<PgTableWithColumns<{ name: "posts"; schema: undefined; columns: { ...; }; dialect: "pg"; }>, NodePgQueryResultHKT, undefined, false, never>', gave the following error.
    Object literal may only specify known properties, and 'authorId' does not exist in type '{ title: string | SQL<unknown> | Placeholder<string, any>; content: string | SQL<unknown> | Placeholder<string, any>; }'.

The issue arises when trying to insert an authorId (a foreign key) into the posts table that references the id of the users table.

Schema Definitions
Here is how I’ve defined my tables using drizzle-orm:

import { integer, pgTable, text, timestamp, varchar } from "drizzle-orm/pg-core";
import { usersTable } from "./users.schema";

export const posts = pgTable("posts", {
    id: integer().primaryKey().generatedAlwaysAsIdentity(),
    title: varchar({ length: 255 }).notNull(),
    content: text("content").notNull(),
    created: timestamp().defaultNow(),
    authorId: integer().references(() => usersTable.id) // Foreign key reference
});

The authorId column is supposed to store the user ID from the usersTable.

Insertion Code
In the main function, I’m trying to insert 50 posts with random data:

import { drizzle, NodePgDatabase } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import * as schema from "./schema/schema";
import "dotenv/config";
import { faker } from "@faker-js/faker";
import { randomInt } from "crypto";

const pool = new Pool({
    connectionString: process.env.DATABASE_URL,
    ssl: true
})

const db = drizzle(pool, { schema }) as NodePgDatabase<typeof schema>;

async function main() {
    const userIds = await Promise.all(
        Array(50).fill("").map(async () => {
            const user = await db.insert(schema.usersTable).values({
                email: faker.internet.email(),
                name: faker.person.fullName(),
                age: randomInt(1, 70)
            }).returning();
            return user[0].id;
        })
    );

    const postIds = await Promise.all(
        Array(50).fill("").map(async () => {
            const post = await db.insert(schema.posts).values({
                title: faker.lorem.sentence(5),
                content: faker.lorem.paragraph(),
                authorId: faker.helpers.arrayElement(userIds), // Select random userId
            }).returning();
            return post[0].id;
        })
    );
}

The Problem
The error indicates that the authorId field is not recognized as part of the posts table. Even though I defined it correctly in the schema, TypeScript fails to infer it during the insert.

How to Adjust Thumbnail Content Size in MacOS Quick Look Plugin Using JavaScript?

I’m trying to fix an issue with a Quick Look plugin where thumbnails are generated using JavaScript in the thumbnail.html file. The problem is that the content doesn’t scale properly to fit the thumbnail size.

How can I access the actual dimensions of the thumbnail within the JavaScript code in thumbnail.html to adjust the content accordingly? Any advice or code examples would be greatly appreciated!

minecraft custom block directional proceedure

**Hey. Pls help, Ive been trying with this for a minute..

Im making a custom modded fluid.

I’m hoping someone who knows a lil about minecraft java code can guide me?

I want to write a statement that only happens when the direction its trying to flow is DOWN.

Ive searched and searched.. pls help!
Im kinda dummy with java code.. if you could show me how it should be? **

If you know java but not minecraft.. heres what im working with:

https://nekoyue.github.io/ForgeJavaDocs-NG/javadoc/1.14.4/net/minecraft/util/Direction.html#DOWN

@Override
protected boolean canSpreadTo(BlockGetter worldIn, BlockPos fromPos, BlockState blockstate, Direction direction, BlockPos toPos, BlockState intostate, FluidState toFluidState, Fluid fluidIn) {
boolean condition = true;
if (worldIn instanceof LevelAccessor world) {
int x = fromPos.getX();
int y = fromPos.getY();
int z = fromPos.getZ();
if (direction == DOWN ) {
condition = my_ConditionProcedure.execute(world, x, y, z);
}
}
return super.canSpreadTo(worldIn, fromPos, blockstate, direction, toPos, intostate, toFluidState, fluidIn) && condition;
}

Multi div multi buttons change color

I’ve got html with multi div and buttons when I press a button in div 1 only buttons in there while change with class name active or remove it 1button is active

help with buttons

<div class="buttons">
  <button class="test active"">test1</div>
  <button class="test">test1</div>
  <button class="test">test1</div>
</div>

<div class="buttons2">
  <button class="test active"">test1</div>
  <button class="test">test1</div>
  <button class="test">test1</div>
</div>

R: not able to find elements in html using rvest, or V8

I want to download, as a table, the text in the main table of the following website:

https://seia.sea.gob.cl/expediente/expedientesEvaluacion.php?modo=ficha&id_expediente=7673283

The table seems to be dynamically generated, as suggested by an answer to this—practically equivalent— question. But trying to adapt the code, I haven’t been able to get what I need.

I have not tried Selenium, because it asks me to install Java, but I don’t have administrator permits on the computer I am using.

I tried using v8 following the answer to the question linked above, but, when running

ctx$eval(JS(js))

I get:

Error: ReferenceError: UbicaciónPlazos is not defined

I have no clue how to debug.

Perhaps this specific application will help others (and myself)

I’m iterating over a large dataset and want to see if there is a more optimal way to do it

My dataset looks like the array below. This data is also segemented into chunks of 500 lines for a easier bulk upload. Data var that is referenced in the loop below.

[
    [ // 500 lines in this sub-array
      ['value','value','value','value','value'],
      ['value','value','value','value','value'],
      ['value','value','value','value','value'],
      .........
    ],
    [
      ['value','value','value','value','value'],
      ['value','value','value','value','value'],
      ['value','value','value','value','value'],
      .........
    ],....
]

I also have another array that is a 1-1 relation between the data and the name of the column. Headers var that is referenced in the loop below.

['valueName','valueName','valueName','valueName','valueName'],

I iterate over this data and assign column names into a object structure and store that into a array that mimics the initial structure of chunks of data with 500 lines each.

{colName:'valueName',data:'value'} // End result is the same as Data var with these replacing 'value'

My big question is is there a better way for me to iterate over this aside from how I am doing it. I’m trying to avoid filter and map since I figure they initialize a new array when used so it takes longer to process. Instead I’ve opted for nested for loops but I may be falling victim to the temple of doom so wanted some second opinions on how to optimize this data restructuring.

My for loops

let newDataChunks = []
for(let dataSet = 0;dataSet < data.length;dataSet++){ // Datachunk
    newDataChunks.push([])
    for(let line = 0;line < data[dataSet].length;line++){ // Line of data
        newDataChunks[newDataChunks.length-1].push([])
        for(let headerPos = 0;headerPos < headers.length;headerPos++){
            newDataChunks[newDataChunks.length-1][newDataChunks[newDataChunks.length-1].length-1].push({
                colName:headers[headerPos],
                data:data[dataSet][line][headerPos]
            })
        }
    }
}

Thanks for the time.

Unable to use require() or import from Node.js in html website

I’ve tried to figure out how to do it and I give up. I’m trying to code something that allows users to visit my github website and type into a textbox, then the website stores their output into a text file located into the website. I found out you could use a node.js module “fs” to append text into that file, so I tried to implement it. But its just not working no matter what I try. Right now, its giving me the error “require() is not a function” and I seriously don’t understand what the problem is. Any help would be appreciated.

My code: (Pasting the entire html file, just for better help.)

<html><head>
    <meta property="og:title" content="OTFT: The Videogame Official Website">
    <meta property="og:description" content="The Official Website for OTFT!">
    <meta property="og:image:secure_url" content="https://otft.github.io/otft_tvg/images/OTFTSquare.png">
    <title>OTFT: The Videogame</title>
    <link rel="icon" href="../images/iconv1.png">
    <style>
    h1 {
    font-size: 50px;
    font-family: FlamingHope;
    }
    h2 {
    font-size: 40px;
    font-family: Blackentina;
    }
    body {
     padding:0;
      margin:0;
      width:100%;
      height:100%;
      background-image: url("../images/WebsiteBackground02.png");
      background-size: cover;
      background-repeat: repeat-y;
      background-position: center;
      background-color: rgba(0,0,0,0.6);
    }
    p {
      font-family: Tomorrow;
      font-size:25px;
    }
    text {
      font-family: Blackentina;
      font-size:70px;
      color:red;
      offset-position:50px;
    }
    a {
      font-family: Blackentina;
      font-size: 30px;
      color:red;
    }
    div {
        display: block;
        unicode-bidi: isolate;
    }
    @font-face {
        font-family: FlamingHope;
        src: url("../FlamingHope.ttf") format("opentype");
    }
    @font-face {
        font-family: AnotherDanger;
        src: url("../another danger.otf") format("opentype");
    }
    @font-face {
        font-family: AnotherDanger;
        font-weight: italics;
        src: url("../another danger italics.otf") format("opentype");
    }
    @font-face {
        font-family: Blackentina;
        src: url("../Blackentina 4F.ttf") format("opentype");
    }
    @font-face {
        font-family: Blackentina;
        font-weight: italics;
        src: url("../Blackentina 4F-Italic.ttf") format("opentype");
    }
    @font-face {
        font-family: Tomorrow;
        src: url("../Tomorrow.ttf") format("opentype");
    }
    @font-face {
        font-family: Tomorrow;
        font-weight: italics;
        src: url("../Tomorrow-Italic.ttf") format("opentype");
    }
    @font-face {
        font-family: Tomorrow;
        font-weight: bold;
        src: url("../Tomorrow-Bold.ttf") format("opentype");
    }
    </style>
    </head><body><center><div id="headerthingie" style="background-color: black;color: white;display: flex;justify-content: center;align-items: center;flex-direction: column;"><h1 style="font-size:40px;">OTFT: The Videogame</h1><template id="weblinksDiv"></template><script type="text/javascript" src="../reusedivfix.js"></script></div>
        <div style="width:700px;display: block;"><h1>FAQ</h1>
    <p>For now, the FAQ will be stored in a file that I will check for new entries! Later on, I will update the website to display the questions.</p>

    <textarea id="inputQuestion" rows="4" cols="50" placeholder="Question goes here..."></textarea>
    <br>
    <input type="submit" value="Submit" onclick="submitData()">
    </center>
    <br>
    <div id="footerthingie" style="background-color: black;color: white;display: flex;justify-content: center;align-items: center;flex-direction: column;position: relative;bottom: 0px;width: 100%;"><template id="weblinksDiv01"></template><script type="text/javascript" src="../reusablesubdiv.js"></script><p style="height:20px;font-size:20px;">ⓒ OTFT Studios 2024</p></div>
    </body>
    <script type="module">
        window.submitData = submitData();
        
        import * as require from 'https://requirejs.org/docs/release/2.3.5/minified/require.js';
        
        function submitData() {

        var fs = require('node:fs');

        let newData = "n" + document.getElementById("inputQuestion").value;

        fs.appendFile('storeduserdata.txt', newData, (err) => {

        if (err) throw err;
        })
    }
    </script>
    </html>

I tried a couple things, like double checking spelling, or my semi-colons, or reorganizing where everything goes. I’ve also consulted google to try and find my way around coding this, but now I’m stuck here.

OAuth Authentication Issue with ImmoScout API – “Inadequate OAuth consumer credentials”

Question:
Hi everyone, I’m trying to integrate with the ImmoScout API using OAuth 1.0a but I’m running into an issue. My current setup is using express, axios, and the oauth-1.0a package.

The problem:
When I try to get the request token or access token, I receive the following error response:

<common:messages xmlns:common="http://rest.immobilienscout24.de/schema/common/1.0">
    <message>
        <messageCode>ERROR_BAD_REQUEST</messageCode>
        <message>Inadequate OAuth consumer credentials.</message>
    </message>
</common:messages>

My code:
Below is the code I’m using to authenticate and make API calls:

const express = require('express');
const bodyParser = require('body-parser');
const OAuth = require('oauth-1.0a');
const axios = require('axios');
const crypto = require('crypto');

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));

const SANDBOX_URL = "https://rest.sandbox-immobilienscout24.de";
const REQUEST_TOKEN_URL = `${SANDBOX_URL}/restapi/security/oauth/request_token`;
const ACCESS_TOKEN_URL = `${SANDBOX_URL}/restapi/security/oauth/access_token`;
const ACCESS_CONFIRMATION_URL = `${SANDBOX_URL}/restapi/security/oauth/confirm_access`;
const RESOURCE_ENDPOINT_URL = `${SANDBOX_URL}/restapi/api/offer/v1.0/user/me/realestate/`;

const CLIENT_KEY = '';
const CLIENT_SECRET = '';

let requestTokenRepository = {};
let accessTokenRepository = {};

const oauth = OAuth({
    consumer: { key: CLIENT_KEY, secret: CLIENT_SECRET },
    signature_method: 'HMAC-SHA1',
    hash_function(baseString, key) {
        return crypto.createHmac('sha1', key).update(baseString).digest('base64');
    },
});

// Initialize token exchange
app.get('/initialize-token-exchange', async (req, res) => {
    const callbackUrl = `http://localhost:${process.env.PORT || 3000}/callback`;

    const requestTokenParams = {
        url: REQUEST_TOKEN_URL,
        method: 'POST',
        data: { oauth_callback: callbackUrl },
    };

    try {
        const requestTokenResponse = await axios(requestTokenParams);
        const requestToken = requestTokenResponse.data;
        const userName = req.user.name;

        requestTokenRepository[userName] = requestToken;
        res.redirect(`${ACCESS_CONFIRMATION_URL}?oauth_token=${requestToken.oauth_token}`);
    } catch (error) {
        console.error(error);
        res.status(500).send('Error obtaining request token');
    }
});

// OAuth callback handling
app.get('/callback', async (req, res) => {
    const { state, oauth_token, oauth_verifier } = req.query;
    const userName = req.user.name;

    if (state !== 'authorized') return res.status(401).send('Authorization was rejected.');

    const latestRequestToken = requestTokenRepository[userName];

    if (!latestRequestToken || latestRequestToken.oauth_token !== oauth_token) {
        return res.status(400).send('Invalid request token.');
    }

    try {
        const accessTokenParams = {
            url: ACCESS_TOKEN_URL,
            method: 'POST',
            data: { oauth_verifier },
            headers: oauth.toHeader(oauth.authorize(requestTokenParams, latestRequestToken)),
        };

        const accessTokenResponse = await axios(accessTokenParams);
        accessTokenRepository[userName] = accessTokenResponse.data;

        res.redirect('/load-real-estates');
    } catch (error) {
        console.error(error);
        res.status(500).send('Error exchanging for access token');
    }
});

// Load real estates
app.get('/load-real-estates', async (req, res) => {
    const userName = req.user.name;
    const accessToken = accessTokenRepository[userName];

    if (!accessToken) return res.redirect('/initialize-token-exchange');

    try {
        const resourceParams = {
            url: RESOURCE_ENDPOINT_URL,
            method: 'GET',
            headers: oauth.toHeader(oauth.authorize(resourceParams, accessToken)),
        };

        const realEstatesResponse = await axios(resourceParams);
        res.send(realEstatesResponse.data);
    } catch (error) {
        console.error(error);
        res.status(500).send('Error loading real estates');
    }
});

// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

Questions:

  1. Is there anything wrong with my OAuth implementation or the way I’m signing the requests?
  2. Could this issue be related to incorrect scopes, permissions, or API configuration?
  3. Are there specific headers or additional parameters I might be missing?

I’d appreciate any help or guidance to resolve this issue! Thanks in advance.

What I’ve tried:

  1. Double-checked the CLIENT_KEY and CLIENT_SECRET to ensure they are correct.
  2. Used both sandbox and production URLs.
  3. Made sure that the callback URL is correctly set to http://localhost:3000/callback.
  4. Validated my request token logic, but I still get the “Inadequate OAuth consumer credentials” error.

Removing paragraph `p` tags around marked.js content

It seems that the marked library by default is wrapping the content it processes with pp tags (at least, for me). Following this and checked out this (but the questions and suggestions are all quite old).

Also there is a claim in 2023 on the Github issue that “this issue has been resolved,” with no explanation of what that means (still happening for me – I am using https://cdn.jsdelivr.net/npm/marked/marked.min.js which currently says v14.1.3).

One user on the Github issue suggested I use marked.parseInline…. However this seems to remove all line breaks from the content, not just the outer wrapping p tags that marked seems to be adding.

Anyone know how to remove just the outer tags, while preserving intended line breaks in the content itself?

Next.js on server component is not sending request to the backend (express.js) if a change happen in the backend?

I am using newest version of Next.js , and inside the route /userprofile/[username] i have a page.jsx that works on server side (non client component), everything is gucci when i make a request to the backend, which is in express.js

however, once i make a small change in express.js somehow next.js stop sending the request to express, and I have to delete .next folder and re-run the application on frontend in order for next.js to send a request to the backend and render the component.

express.js userModel file has this code:


const User = {}

User.get = async function ({username}){
    console.log('print something')

    try{
    const fetchData = await pool.query('SELECT firstname, lastname, _username, bio, profilelogo FROM _user WHERE _username = $1',[username])
    console.log(fetchData)
    console.log('print something again')
    print('again and again')
    return {success:true, data:fetchData.rows[0],message:'User data has been fetched successfully'}
    }



    catch(e){
        console.log(e)
        return {success:false, data:null, message: e.message}
    }
}

express.js UserController file:

const UserController = {}


UserController.get = async function (req,res){
    console.log('try')
    

    try{
        const userInfo = await User.get(req.params)
        console.log(req.params)
  
        if(userInfo.success){

            return res.status(200).json({data:userInfo.data})
        }

        return res.status(401).json({message:userInfo.message})

    }
    catch(err){
        console.log(err)

        return res.status(500).json({error:err.message})
    }
}


module.exports = UserController

express routing:

router.get('/userprofile/:username', UserController.get)

next.js /userprofile/[username] server component inside page.tsx


import Image from "next/image"

interface UserInfo{
    _username:string,
    firstname:string,
    lastname:string,
    bio:string,
    profilelogo:string
}

export default async function UserProfile({params}:{params:{username:string}}){

    const data = await fetch(`http://127.0.0.1:3000/userprofile/${params.username}/`,{headers:{'Content-Type':'application/json','Accept':'application/json'}})
    const userInfo = await data.json()
   console.log(userInfo)


    return(

    <div className=''>
        <div className=''>

   <div>
            <div>
                <Image src={userInfo.profilelogo} alt='profilelogo'></Image>
            </div>
            <div >
                <div>{userInfo._username}</div>
            </div>
            </div>

            <div>
                <div className=''>
                    {userInfo.firstname} {userInfo.lastname}
                </div>
                <div>
                    {userInfo.bio}
                </div>
            </div>

            

        </div>

    </div> 

    )
}

how do i resolve this?

when i make a change in the backend, the userInfo in the frontend is basically an empty object, and nothing in the backend happen, which basically means the console.log() that i put everywhere in the backend code is not printed anymore.