Not fetch data from some one of my JSON URL

I have try fetch json data from url getting data from some url & not getting data from some url.

getting data from this url : https://raw.githubusercontent.com/rsk1987/test-project/refs/heads/main/test2.json

not getting data from this url : https://raw.githubusercontent.com/rsk1987/test-project/refs/heads/main/test.json

let http = new XMLHttpRequest();

http.open('get', 'https://raw.githubusercontent.com/rsk1987/test-project/refs/heads/main/test.json', true);

http.send();
http.onload = function(){

    if(this.readyState == 4 && this.status == 200){

        let products = JSON.parse(this.responseText);

        let output = "";

        for(let item of products){
            output += `

    <a onclick="jwplayer().load({file: '${item.adfree_url}'})">
        <div class="product">
        <img src="${item.src}" alt="${item.title}">
        <p class="title" style="display:none">${item.title}</p>
        <p class="match_name">${item.match_name}</p>
        </div>
    </a>
            `;
        }
        document.querySelector(".json-data").innerHTML = output;
    }
} 
 .product{
    text-align: center;
    display: inline-grid;
    padding: 5px;
    box-shadow: -0px 5px 5px 8px rgba(1, 1, 1, 0.5);
    grid-gap: 10px;
    margin: 8px auto;
    width: 180px;
    max-width: 180px;
    height: : 280px;
    max-height:280px;
    padding: 5px;
}
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
  
    <div class="json-data"></div>

I want to show on page category, title, & image object.

How and when to use arrow functions efficiently in JavaScript

I’ve mostly been writing traditional (regular) functions up until now, but I still don’t fully understand how and when to use arrow functions. Could someone kindly explain the best practices for using arrow functions? Here’s a simple implementation of a minimum-finding algorithm written using a traditional function. I’d appreciate it if someone could show me how to rewrite it using an arrow function. Please be respectful when responding – I’m here to learn.

function findMinimum(values) {
  let minimum = values[0]

  for (let counter = 0; counter < values.length; counter++) {
    if (values[counter] < minimum) {
      minimum = values[counter]
    }
  }
  console.log(`The minimum value is ${minimum}`);
}

let numbers = [77, 45, 98, 77, 12, 33, 99, 76]

findMinimum(numbers)

Console is showing node rather than expected output with array and for loop

I am relatively new to coding and working through a bootcamp right now. I will summarize the task at hand and then post the code below and my console result. If anyone can help me see what I’m doing wrong that would be greatly appreciated!

Task: loop through the array and use the age of the people in the array to determine if they’re old enough to see Mad Max.

Context: earlier in my work, I was getting at least some output, not getting different results for different ages in the array (getting all “not old enough”), but there was at least something being displayed in the console. Now all I get is this:

node "/Users/me/Dev/vs intro/10-Loops-and-Arrays-Practice/loopsArrays.js"

Here is my code:

var peopleWhoWantToSeeMadMaxFuryRoad = [
    {
      name: "Mike",
      age: 12,
      gender: "male"
    },{
      name: "Madeline",
      age: 80,
      gender: "female"
    },{
      name: "Cheryl",
      age: 22,
      gender: "female"
    },{
      name: "Sam",
      age: 30,
      gender: "male"
    },{
      name: "Suzy",
      age: 4,
      gender: "female"
    }
  ];

for (var i = 0; i < peopleWhoWantToSeeMadMaxFuryRoad.length; i++){
    if (peopleWhoWantToSeeMadMaxFuryRoad.age >= 18){
        console.log("is old enough to see Mad Max")
    } else if (peopleWhoWantToSeeMadMaxFuryRoad.age <= 17){
        console.log("is not old enough to see Mad Max")
    }
};

Thank you again to anyone who can help!

How to implement text along a bezier curve in a react js canvas webapp?

I am making a custom canvas editor using the open-source polotno sdk with react js, whcih also uses the konva framework. It is aimed at making heraldry blazons.

I am trying to implement a feature so that a user can create text along a customizable bezier curve with handles, but i have found no resources online that address my specific problem.

I have successfully implemented a button that adds a modifiable bezier curve with two handles, but what i am looking for is a bezier curve that can have however many handles the user wants, and be able to have text on it. I am including the images of what i am looking to implement and how i want it to function.

This image is an example of the result I want the user to be able to create

This image is an example of how I image it would function in the canvas

I am doing this in separate files: Sections.js contains the sidepannels (text, images, upload, etc…) as well as their sub sections. Editor.js imports sections.js, and App.js is what imports Editor.js and runs.

Ideally, I would like to define the functions for the bezier text in a separate file, and include it inside the Sections.js file where the text panel is. But any functional way of implementing it is good enough.

My sections.js code is very long, so here is the relevant code of the text panel, where i want the buttons and options for the curved text to be:

const TextePanel = ({ store }) => {
  const [text, setText] = useState('');
  const [fontSize, setFontSize] = useState(24);
  const [fontFamily, setFontFamily] = useState('Arial');

  const addNormalText = () => {
    const page = store.activePage;
    page.addElement({
      type: 'text',
      text,
      fontSize,
      fontFamily,
      x: 100,
      y: 100,
    });
  };

  const addBezierCurve = () => {
    const page = store.activePage;
    page.addElement({
      type: 'bezier-curve',
      x1: 100,
      y1: 100,
      cx: 200,
      cy: 50,
      x2: 300,
      y2: 100,
      stroke: 'red',
      strokeWidth: 3,
    });
  };


  return (
    <div style={{ padding: 10 }}>
      <div>
        <label>Text:</label>
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
          style={{ width: '100%' }}
        />
      </div>

      <div style={{ marginTop: 10 }}>
        <label>Font:</label>
        <select
          value={fontFamily}
          onChange={(e) => setFontFamily(e.target.value)}
        >
          <option value="Arial">Arial</option>
          <option value="Georgia">Georgia</option>
          <option value="Courier New">Courier New</option>
          <option value="Comic Sans MS">Comic Sans</option>
        </select>
      </div>

      <div style={{ marginTop: 10 }}>
        <label>Font Size:</label>
        <input
          type="number"
          value={fontSize}
          onChange={(e) => setFontSize(parseInt(e.target.value))}
        />
      </div>
      <div style={{ marginTop: 10 }}>
        <button onClick={addNormalText}>Add Normal Text</button>
      </div>
      <div style={{ marginTop: 10 }}>
        <button onClick={addBezierCurve}>Add Bézier Curve</button>
      </div>
    </div>
  );
};

const TexteSection = {  
  name: 'Texte',
  Tab: (props) => (
    <SectionTab name="Texte" {...props}>
      <img
        src="/tabicons/fountain-pen.svg"
        alt="Text"
        style={{ width: 30, height: 30 }}
      />
    </SectionTab>
  ),
  Panel: TextePanel,
};

Here is my full editor.js file:

// src/Editor.js
import React, { useEffect } from "react";
import {
  PolotnoContainer,
  SidePanelWrap,
  WorkspaceWrap,
} from "polotno";
import { Toolbar } from "polotno/toolbar/toolbar";
import { PagesTimeline } from "polotno/pages-timeline";
import { ZoomButtons } from "polotno/toolbar/zoom-buttons";
import { SidePanel } from "polotno/side-panel";
import { Workspace } from "polotno/canvas/workspace";

import "./elements/BezierCurveElement";

import { createStore } from "polotno/model/store";
import { sections } from "./Sections";

import "@blueprintjs/core/lib/css/blueprint.css";

const store = createStore({
  key: "YOUR_API_KEY",
  showCredit: true,
});

store.addPage();

const addWatermark = () => {
  const page = store.activePage;
  const imageUrl = "/watermark.png"; // Make sure it's in /public

  const image = new window.Image();
  image.src = imageUrl;

  image.onload = () => {
    const imageWidth = image.width;
    const imageHeight = image.height;

    const targetWidth = 300;
    const scaleFactor = targetWidth / imageWidth;
    const scaledHeight = imageHeight * scaleFactor;

    // Use the actual page height after ensuring it's available
    const pageHeight = page.height || 1080; // Fallback in case undefined
    const x = 15;
    const y = 850; // Bottom left

    page.addElement({
      type: "image",
      src: imageUrl,
      x,
      y,
      width: targetWidth,
      height: scaledHeight,
      alwaysOnTop: true,
      showInExport: true,
      locked: true,
      selectable: false,
      draggable: false,
      resizable: false,
      removable: false,
      name: "WATERMARK_IMAGE",
    });
  };
};

const Editor = () => {
  useEffect(() => {
    addWatermark();
  }, []);

  return (
    <PolotnoContainer style={{ width: "100vw", height: "100vh" }}>
      <SidePanelWrap>
        <SidePanel store={store} sections={sections} defaultSection="Gabarits" />
      </SidePanelWrap>
      <WorkspaceWrap>
        <Toolbar store={store} downloadButtonEnabled />
        <Workspace store={store} />
        <ZoomButtons store={store} />
        <PagesTimeline store={store} />
      </WorkspaceWrap>
    </PolotnoContainer>
  );
};

export default Editor;

And here is my App.js file:

// src/App.js
import React from "react";
import Editor from "./Editor";

function App() {
  return <Editor />;
}

export default App;

If you need any further files, information, or more contents from my Sections.js file, I can include it.

How can make the player and bots choose cards to pass to the player clockwise to them?

I’m trying to do an assignment where I have to create the card game Game of Hearts.

Here is an example game (scroll down for rules): https://cardgames.io/hearts/

Right now, I am trying to implement the part where the player selects 3 cards to pass to the player next to them, and the bots will also automatically do the same thing after pressing the ‘pass’ button. However, I can’t seem to get the pass button to appear. I also believe I have to put each card in a container to make them clickable, but I’m not 100% how to go about implementing that as well. I am only supposed to be updating the view, not the model or controller.

Here is the model:

import {HU} from "./hearts_utils.js";

export class HeartsModel extends EventTarget {
    #playerNames;
    #state;
    #scorelog;
    #hands;
    #current_trick;
    #collected_tricks;
    #passing;

constructor() {
    super();

    this.#playerNames = {
        north: null,
        east: null,
        south: null,
        west: null
    };

    this.#state = 'uninitialized';

    this.#scorelog = [];

    this.#hands = {
        north: null,
        east: null,
        south: null,
        west: null
    };

    this.#collected_tricks = {
        north: [],
        east: [],
        south: [],
        west: []
    };
}

// Private methods
#dealCards () {
    let deck = [];
    ['spades', 'hearts', 'diamonds', 'clubs'].forEach(suit => {
        [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14].forEach(rank => {
            deck.push(new Card(suit, rank));
        })
    });
    deck = deck.map((card) => [card, Math.random()]).sort((a,b) => a[1]-b[1]).map((cpair) => cpair[0]);
    return {
        north: new Hand(deck.slice(0,13)),
        east: new Hand(deck.slice(13,26)),
        south: new Hand(deck.slice(26,39)),
        west: new Hand(deck.slice(39,52))
    };
}

// These methods are only available to controller to update model.
// They should never be called from view objects.

initialize (north_name, east_name, south_name, west_name) {
    if (this.#state != 'uninitialized') return;

    this.#playerNames.north = north_name;
    this.#playerNames.east = east_name;
    this.#playerNames.south = south_name;
    this.#playerNames.west = west_name;

    this.#scorelog = [];
    this.setupGame('right');
};

passCards (cards_to_pass) {
    if (this.#state != 'passing') return;

    HU.positions.forEach(p => this.#hands[p].remove(cards_to_pass[p]));
    HU.positions.forEach(p => {
        let pass_to = HU.passing_maps[this.#passing][p];
        this.#hands[pass_to].add(cards_to_pass[p]);
    });

    this.#state = 'playing';

    let lead = HU.positions.find(p => this.#hands[p].contains(Card.TWO_OF_CLUBS));
    
    this.#current_trick = new Trick(lead);

    this.dispatchEvent(new Event('stateupdate'));
    this.dispatchEvent(new Event('trickstart'));
};

playCardIntoTrick (position, card) {
    if (this.#state != 'playing') return;

    this.#hands[position].remove([card]);
    this.#current_trick.playCard(card);
    this.dispatchEvent(new CustomEvent('trickplay', {detail: {
        position: position,
        card: card
    }}));

    if (this.#current_trick.isComplete()) {
        this.dispatchEvent(new Event('trickend'));
    } 
};

collectTrick (position) {
    if (this.#state != 'playing') return;

    this.#collected_tricks[position].push(this.#current_trick);
    this.dispatchEvent(new CustomEvent('trickcollected', {detail: {
        position: position,
        trick: this.#current_trick}
    }));
    this.#current_trick = null;
};

setupTrick (position) {
    if (this.#state != 'playing') return;

    this.#current_trick = new Trick(position);
    this.dispatchEvent(new Event('trickstart'));
};

updateScoreLog (scorelog_entry, moonshooter) {
    this.#scorelog.push(scorelog_entry);
    this.dispatchEvent(new CustomEvent('scoreupdate', {detail: {
        entry: scorelog_entry,
        moonshooter: moonshooter
    }}));
};

setupGame (passing) {
    if ((this.#state == 'complete') || (this.#state == 'passing')) return;

    this.#passing = passing;
    this.#hands = this.#dealCards();
    this.#current_trick = null;
    this.#collected_tricks = {
        north: [],
        east: [],
        south: [],
        west: []
    };
    this.#state = 'passing';

    this.dispatchEvent(new Event('stateupdate'));
};

matchOver () {
    this.#state = 'complete';
    this.dispatchEvent(new Event('stateupdate'));
};

// These methods are available to view objects to query model information 

getState () {
    return this.#state;
}

getPlayerName (position) {
    return this.#playerNames[position];
};

getCurrentGamePoints (position) {
    return this.#collected_tricks[position].reduce((sum, trick) => sum + trick.getPoints(), 0);
};

getScoreLog () {
    return this.#scorelog;
};

getScore (position) {
    return this.#scorelog.reduce((score, entry) => score + entry[position], 0);
}

getPassing() {
    return this.#passing;
}

getCurrentTrick () {
    return this.#current_trick;
}

getTricksLeft () {
    return 13 - HU.positions.reduce((sum, p) => sum += this.#collected_tricks[p].length, 0);
}

getHand (position) {
    return this.#hands[position];
}

getCollectedTricks(position) {
    return this.#collected_tricks[position];
}
}

export class Card {
    #suit
    #rank

static TWO_OF_CLUBS = new Card('clubs', 2);
static QUEEN_OF_SPADES = new Card('spades', 12);

constructor (suit, rank) {
    this.#suit = suit;
    this.#rank = rank;
}

toString() {
        return `${this.getRankName()} of ${this.getSuit()}`;
}

getSuit() {
    return this.#suit;
}

getRank() {
    return this.#rank;
}

getRankName() {
    let honors_map = {};
    honors_map[11] = 'jack';
    honors_map[12] = 'queen';
    honors_map[13] = 'king';
    honors_map[14] = 'ace';

    return this.#rank < 11 ? this.#rank.toString() : honors_map[this.#rank];
}

equals(other) {
    return (other.getRank() == this.#rank) && (other.getSuit() == this.#suit);
}
}


export class Trick {
    #lead;
    #next_to_play;
    #played_by_position;

static #next_to_play_map = {
    north: 'east',
    east: 'south',
    south: 'west',
    west: 'north'
};

constructor(lead) {
    this.#lead = lead;
    this.#next_to_play = lead;
    this.#played_by_position = {
        north: null,
        east: null,
        south: null,
        west: null
    }
}

getLead() {
    return this.#lead;
}

getLeadSuit() {
    return this.getCard(this.getLead()).getSuit();
}

nextToPlay () {
    return this.#next_to_play;
}

playCard (card) {
    this.#played_by_position[this.#next_to_play] = card;
    this.#next_to_play = this.isComplete() ? null : Trick.#next_to_play_map[this.#next_to_play];
}

getCard(position) {
    return this.#played_by_position[position];
}

isComplete() {
    return !HU.positions.find(p => this.#played_by_position[p] == null);
};

getPoints() {
    return HU.positions.map(p => this.#played_by_position[p])
                       .filter(c => c != null)
                       .reduce((points, c) => points + 
                                (c.equals(Card.QUEEN_OF_SPADES) ? 13 : 
                                 ((c.getSuit() == 'hearts') ? 1 : 0)), 0);
}

toString() {
    return `next to play: ${this.#next_to_play}
north: ${this.#played_by_position.north}
east : ${this.#played_by_position.east}
south: ${this.#played_by_position.south}
west : ${this.#played_by_position.west}
`
    }
}

export class Hand extends EventTarget {
    #cards;

constructor (cards) {
    super();
    this.#cards = cards;
}

contains (card) {
    return this.#cards.some(c => c.equals(card));
}

hasSuit(suit) {
    return this.#cards.some(c => c.getSuit() == suit);
}

hasOnlyHearts() {
    return !this.#cards.some(c => c.getSuit() != 'hearts');
}

add (cards) {
    if (cards.length == 0) return;

    this.#cards.push(...cards);
    this.dispatchEvent(new CustomEvent('update', {detail:
        {type: 'add', cards: [...cards]}}));
}

remove (cards) {
    if (cards.length == 0) return;
    
    cards.forEach((c_to_remove) => {
        this.#cards = this.#cards.filter((c) => !c.equals(c_to_remove));
    });
    this.dispatchEvent(new CustomEvent('update', {detail:
        {type: 'remove', cards: [...cards]}}));
}

getCards () {
    return [...this.#cards];
}

toString() {
    return `Hearts  : ${this.#cards.filter(c=> c.getSuit() == 'hearts').sort((a,b) => a.getRank() - b.getRank()).map(c => c.getRankName()).join()}
Spades  : ${this.#cards.filter(c=> c.getSuit() == 'spades').sort((a,b) => a.getRank() - b.getRank()).map(c => c.getRankName()).join()}
Diamonds: ${this.#cards.filter(c=> c.getSuit() == 'diamonds').sort((a,b) => a.getRank() - b.getRank()).map(c => c.getRankName()).join()}
Clubs   : ${this.#cards.filter(c=> c.getSuit() == 'clubs').sort((a,b) => a.getRank() - b.getRank()).map(c => c.getRankName()).join()}
`;
    }
}

Here is the controller:

import { HU } from "./hearts_utils.js";
import { Card } from "./hearts_model.js";

export class HeartsController {
#model;
#cards_to_pass;
#hearts_broken;

constructor(model) {
    this.#model = model;
    this.#model.addEventListener('trickend', () => this.#handleTrickEnd());
}

#doAsync() {
    return new Promise((resolve) => setTimeout(resolve, 0));
}

startGame(north_name, east_name, south_name, west_name) {
    this.#cards_to_pass = {
        north: [],
        east: [],
        south: [],
        west: []
    };
    this.#hearts_broken = false;
    this.#doAsync().then(() => {
        this.#model.initialize(north_name, east_name, south_name, west_name);
    });
}

passCards(position, cards) {
    if (this.#model.getState() != 'passing') {
        alert('Controller error: attempt to pass cards when not in passing state');
        return;
    }

    if (this.#model.getPassing() == 'none') {
        alert('Controller error: attempt to pass cards when passing is none');
        return;
    }

    if (cards.length != 3) {
        alert('Controller error: attempt to pass more/less than three cards');
        return;
    }

    let hand = this.#model.getHand(position);
    if (cards.some(c => !hand.contains(c))) {
        alert('Controller error: attempt to pass a card not in the hand of position');
        return;
    }

    if (this.#cards_to_pass[position].length != 0) {
        alert('Controller error: attempt to pass cards twice');
        return;
    }

    this.#cards_to_pass[position] = [...cards];

    if (!HU.positions.find(p => this.#cards_to_pass[p].length == 0)) {
        this.#doAsync().then(() => {
            this.#model.passCards(this.#cards_to_pass);
            this.#cards_to_pass = {
                north: [],
                east: [],
                south: [],
                west: []
            }
        });
    }
}

isPlayable(position, card) {
    let cur_trick = this.#model.getCurrentTrick();
    let hand = this.#model.getHand(position);

    if (cur_trick.getLead() == position) {
        // If lead of first trick in game, then only 2 of clubs is playable.
        if (this.#model.getTricksLeft() == 13) {
            return card.equals(Card.TWO_OF_CLUBS);
        }

        // Can only lead hearts if hearts are broken or hand only has hearts.
        if (card.getSuit() == 'hearts') {
            if (!this.#hearts_broken) {
                return hand.hasOnlyHearts();
            }
        }
        return true;
    } else {
        let lead_card = cur_trick.getCard(cur_trick.getLead());
        if (!lead_card) {
            return false;
        }
        if (!hand.hasSuit(lead_card.getSuit())) {
            return true;
        }
        return card.getSuit() == lead_card.getSuit();
    }
}

playCard(position, card) {
    if (this.#model.getState() != 'playing') {
        alert('Controller error: playCard called when not in playing state.');
        return;
    }

    if (this.#model.getCurrentTrick().nextToPlay() != position) {
        alert('Controller error: attempt to play card out of position');
        return;
    }

    if (!this.#model.getHand(position).contains(card)) {
        alert('Controller error: attmept to play card not in hand');
        return;
    }

    if (!this.isPlayable(position, card)) {
        alert('Controller error: attmept to play unplayable card');
        return;
    }

    this.#doAsync().then(() => {
        this.#model.playCardIntoTrick(position, card);
        this.#hearts_broken ||= (card.getSuit() == 'hearts');
    });
}

#handleTrickEnd() {
    // Figure out who won.
    let cur_trick = this.#model.getCurrentTrick();
    let winner = cur_trick.getLead();
    let winning_card = cur_trick.getCard(winner);

    HU.positions.forEach(position => {
        if (winner != position) {
            let card = cur_trick.getCard(position);
            if ((card.getSuit() == winning_card.getSuit()) &&
                (card.getRank() > winning_card.getRank())) {
                winning_card = card;
                winner = position;
            }
        }
    });
    
    this.#doAsync().then(() => this.#model.collectTrick(winner))
        .then(() => {
            if (this.#model.getTricksLeft() > 0) {
                this.#model.setupTrick(winner);
                return false;
            } else {
                // Game's over.
                // Create scorelog entry (detect shooting the moon)
                // Update scorelog
                // Detect possible match end.
                // Figure out next passing mode and set up next game.

                //                let scorelog_entry = HU.positions.reduce((entry, pos) => entry[pos] = this.#model.getCurrentGamePoints(pos), {});
                let scorelog_entry = {
                    north: this.#model.getCurrentGamePoints('north'),
                    east: this.#model.getCurrentGamePoints('east'),
                    south: this.#model.getCurrentGamePoints('south'),
                    west: this.#model.getCurrentGamePoints('west'),
                };

                let moonshooter = HU.positions.find(p => scorelog_entry[p] == 26);
                if (moonshooter) {
                    HU.positions.forEach(p => {
                        scorelog_entry[p] = (scorelog_entry[p] + 26) % 52;
                    });
                } else {
                    moonshooter = null;
                }

                this.#model.updateScoreLog(scorelog_entry, moonshooter);
                return true;
            }
        })
        .then((game_over) => {
            if (game_over) {
                if (HU.positions.find(p => this.#model.getScore(p) >= 100)) {
                    this.#model.matchOver();
                } else {
                    let next_passing = HU.next_passing_map[this.#model.getPassing()];
                    this.#hearts_broken = false;
                    this.#cards_to_pass = {
                        north: [],
                        east: [],
                        south: [],
                        west: []
                    };
                    this.#model.setupGame(next_passing);

                    if (next_passing == 'none') {
                        this.#doAsync().then(() => this.#model.passCards(this.#cards_to_pass));
                    }
                }
            }
        });
}

}

And here is the view (only file that can be altered)

import {HeartsRobotKmp} from "./hearts_robot_kmp.js";
import {Card, Hand, Trick} from "./hearts_model.js";
import {HU} from "./hearts_utils.js";

export class HeartsView {

#model
#controller

constructor(model, controller) {
    this.#model = model;
    this.#controller = controller;
    this.dealPressed = false;
}

render(render_div) {
    this.render_div = render_div;
    render_div.innerHTML = '';

this.#model.addEventListener("stateupdate", () => this.update());
this.#model.addEventListener("trickplay", () => this.updateTrick());
this.#model.addEventListener("scoreupdate", () => this.updateScores());

if (this.#model.getState() === 'uninitialized') {
    this.renderNameSetup();
}  else {
    this.renderGameTable();
    this.update();
}
}

renderNameSetup() {
    this.render_div.innerHTML = `
        <div class="name-setup">
            <h2>Welcome to Hearts!</h2>
            <label>Your Name: <input type="text" id="player-name" placeholder="You (South)"></label>
            <label>West Player: <input type="text" id="west-name" ></label>
            <label>North Player: <input type="text" id="north-name"></label>
            <label>East Player: <input type="text" id="east-name"></label>
            <button id="confirm-names">Start Game</button>
        </div>
    `;

    document.getElementById('confirm-names').addEventListener('click', () => {
        const south = document.getElementById('player-name').value || "You";
        const west = document.getElementById('west-name').value;
        const north = document.getElementById('north-name').value;
        const east = document.getElementById('east-name').value;

        this.#model.getPlayerName('north');
        this.#model.getPlayerName('east');
        this.#model.getPlayerName('south');
        this.#model.getPlayerName('west');

        this.#controller.startGame(north, east, south, west);
    });
}

renderGameTable() {
    const names = {
        north: this.#model.getPlayerName('north'),
        east: this.#model.getPlayerName('east'),
        south: this.#model.getPlayerName('south'),
        west: this.#model.getPlayerName('west')
    }
    this.render_div.innerHTML = `
        <div id="game-table" style="display: grid; grid-template-areas:
            'north north north'
            'west center east'
            'south south south';
            gap: 20px; justify-items: center; align-items: center;">
            
            <div id="north" style="grid-area: north;">${names.north}
            <div id="north-hand" class="hand"></div>
            </div>
            
            <div id="west" style="grid-area: west;">${names.west}
                <div id="west-hand" class="hand"></div>
            </div>
            <div id="center" style="grid-area: center;">
                <div id="trick-area">Trick Goes Here</div>
                <button id="deal-button">Deal</button>
                <button id="pass-button" style="display:none;">Pass</button>
                <div id="score-table">Scores Go Here</div>
            </div>
            <div id="east" style="grid-area: east;">${names.east}
                <div id="east-hand" class="hand"></div>
            </div>
            <div id="south" style="grid-area: south;">${names.south}
                <div id="south-hand" class="hand"></div>
            </div>
        </div>
    `;

    document.getElementById("deal-button").addEventListener("click", () => {
        this.dealPressed = true;
        this.renderHands();
                  
    });
    


}


update() {
    const state = this.#model.getState();
    if (!document.getElementById("game-table")) {
        this.renderGameTable();
    }
    if (state === 'passing') {
        if (this.dealPressed) {
            this.showPassCardsUI();
        }
    } else if (state === 'playing') {
        this.showPlayableCards();
        this.updateTrick();
    } else if (state === 'complete') {
        this.showWinner();
    }
    this.updateScores();
}

renderHands() {
    const positions = ["north", "east", "south", "west"];

    positions.forEach(position => {
        const hand = this.#model.getHand(position); // A Hand object
        if (!hand) return;

        const cards = hand.getCards(); // Array of Card objects
        const container = document.getElementById(`${position}-hand`);
        container.innerHTML = '';

        cards.forEach(card => {
            const cardDiv = document.createElement("div");
            cardDiv.className = "card";
            cardDiv.textContent = `${card.getRankName()} of ${card.getSuit()}`;
            container.appendChild(cardDiv);
        });
    });
}

showPassCardsUI() {
    const southHandDiv = document.getElementById('south-hand');
    const passButton = document.getElementById('pass-button');
    passButton.style.display = 'inline-block';

    const selectedCards = new Set();

    // Make each card clickable
    [...southHandDiv.children].forEach(cardDiv => {
        cardDiv.addEventListener('click', () => {
            const cardText = cardDiv.textContent;
            cardDiv.classList.toggle('selected');

            if (selectedCards.has(cardText)) {
                selectedCards.delete(cardText);
            } else if (selectedCards.size < 3) {
                selectedCards.add(cardText);
            }

            passButton.disabled = selectedCards.size !== 3;
        });
    });

    passButton.disabled = true;

    passButton.addEventListener('click', () => {
        // Convert text labels back to actual Card objects from model
        const southHand = this.#model.getHand('south').getCards();
        const selectedCardObjs = [...selectedCards].map(text =>
            southHand.find(c => `${c.getRankName()} of ${c.getSuit()}` === text)
        );

        // Player passes cards
        this.#controller.passCard("south", selectedCardObjs);

        // Other players pass random cards
        for (const pos of ["north", "east", "west"]) {
            const hand = this.#model.getHand(pos).getCards();
            const randomCards = this.getRandomCards(hand, 3);
            this.#controller.passCard(pos, randomCards);
        }

        passButton.style.display = 'none'; // Hide after passing
    });
}

getRandomCards(cards, count) {
    const shuffled = [...cards].sort(() => 0.5 - Math.random());
    return shuffled.slice(0, count);
}


showPlayableCards() { /* To be implemented */ }
updateTrick() { /* To be implemented */ }
updateScores() { /* To be implemented */ }
showWinner() { /* To be implemented */ }

renderMatchOver() {
    // todo
}

}

any help would be appreciated, Thank you so much!

How to redirect to GitHub login page using Clerk?

I’m using Clerk for authentication in my web application. I successfully created that social connection but I want to redirect users to the GitHub login page (using Clerk’s GitHub OAuth provider) when they click a “Login with GitHub” button — without showing Clerk’s default sign-in page first.

How can I achieve this?
Is there a specific method or URL I should use to directly trigger GitHub OAuth via Clerk?
mention that i don’t want to use clerks Components.

Any code snippet or reference would be greatly appreciated.
Thanks!

Prismic Slice machine is not working with the raw official starter

I had a problem opening the slice machine panel in my app so I tried to install a brand new repo with the official Prismic nextJS starter. Same problem. When I open localhost:9999, I got this :

hook.js:608 Error: react-modal: No elements were found for selector #__next.
at l (…

re-fetch a fresh copy SyntaxError: Unexpected token ‘L’, “Loading{“p”… is not valid JSON
at JSON.parse ()

Basically it’s saying that pageProps is empty

Here is the package.json

{
  "name": "nextjs-starter-prismic-multi-page",
  "version": "0.0.0",
  "private": true,
  "license": "Apache-2.0",
  "author": "Prismic <[email protected]> (https://prismic.io)",
  "scripts": {
    "dev": "concurrently "npm:next:dev" "npm:slicemachine" --names "next,slicemachine" --prefix-colors blue,magenta",
    "next:dev": "next",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "slicemachine": "start-slicemachine",
    "format": "prettier --write ."
  },
  "dependencies": {
    "@prismicio/client": "^7.17.2",
    "@prismicio/next": "^2.0.1",
    "@prismicio/react": "^3.2.1",
    "clsx": "^2.1.1",
    "next": "^15.1.6",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@slicemachine/adapter-next": "^0.3.75",
    "@tailwindcss/aspect-ratio": "^0.4.2",
    "@tailwindcss/postcss": "^4.0.1",
    "@types/node": "^22.12.0",
    "@types/react": "^19.0.8",
    "@types/react-dom": "^19.0.3",
    "concurrently": "^9.1.2",
    "eslint": "^9.19.0",
    "eslint-config-next": "^15.1.6",
    "postcss": "^8.5.1",
    "prettier": "^3.4.2",
    "prettier-plugin-tailwindcss": "^0.6.11",
    "slice-machine-ui": "^2.15.2",
    "tailwindcss": "^4.0.1",
    "typescript": "^5.7.3"
  }
}

I was on node 23.
I tried to downgrade on v18.20.2, but it didn’t solved anything

Could it be a config problem in my laptop? 4 hours that I try everything and still at the same point.

How to make Shopify Admin API GraphQL call using offline session in Remix Flow Action handler?

I’m building a Shopify app using the Remix template (@shopify/shopify-app-remix). I have a Flow Action trigger that needs to make a GraphQL call to the Shopify Admin API from the backend action handler to fetch the shop’s email address (shop { email }).

The Flow action is triggered correctly, and I can authenticate the request using shopify.authenticate.flow(request). I can also successfully retrieve the shop’s offline session (which includes the accessToken) from my Prisma database using the sessionStorage provided by the library.

But I’m struggling to find the right way to instantiate an authenticated GraphQL client using this offline session to make the Admin API call.

Context:

Framework: Remix (using Shopify Remix App template)

Library: @shopify/shopify-app-remix (mention version if known, e.g., v3.x) / @shopify/shopify-api (mention version if known, e.g., v11.x)

Goal: Inside a Flow Action handler (a Remix action function), fetch the shop’s email using an offline token.

shopify.server.js Config:

// app/shopify.server.js (relevant parts)
import "@shopify/shopify-app-remix/adapters/node";
import {
  ApiVersion,
  AppDistribution,
  shopifyApp,
} from "@shopify/shopify-app-remix/server";
import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma";
import prisma from "./db.server";

const shopify = shopifyApp({
  apiKey: process.env.SHOPIFY_API_KEY,
  apiSecretKey: process.env.SHOPIFY_API_SECRET || "",
  apiVersion: ApiVersion.January25, // Or your version
  scopes: process.env.SCOPES?.split(","), // Includes 'read_shop'
  appUrl: process.env.SHOPIFY_APP_URL || "",
  authPathPrefix: "/auth",
  sessionStorage: new PrismaSessionStorage(prisma),
  distribution: AppDistribution.AppStore,
  future: {
    unstable_newEmbeddedAuthStrategy: true,
    removeRest: false, // Currently set to false for testing, but also failed with true
  },
  // ...
});

export default shopify;
export const authenticate = shopify.authenticate;
export const sessionStorage = shopify.sessionStorage;
// ...

Prisma Session Model:

// prisma/schema.prisma
model Session {
  id            String    @id
  shop          String
  state         String
  isOnline      Boolean   @default(false)
  scope         String?
  expires       DateTime?
  accessToken   String
  userId        BigInt?
  firstName     String?
  lastName      String?
  email         String?
  accountOwner  Boolean?
  locale        String?
  collaborator  Boolean?
  emailVerified Boolean?
}

Problem:

Inside my Flow action handler (app/routes/api.flow.action.send-email.jsx), after successfully getting the shopDomain and fetching the offlineSession using sessionStorage.findSessionsByShop(shopDomain), I cannot create a working GraphQL client.

Attempts Made & Errors:

// Inside the action function, after getting shopDomain and offlineSession

// Method 1: Standard path via shopify.api.clients
try {
  const client = new shopify.api.clients.Graphql({ session: offlineSession });
  // FAILED with: TypeError: Cannot read properties of undefined (reading 'clients')
} catch (e) { console.error("Method 1 Failed", e); }

// Method 2: Using shopify.admin (doesn't seem correct for offline)
try {
  const adminContext = await shopify.admin({ session: offlineSession });
  // FAILED with: TypeError: shopify.admin is not a function
} catch (e) { console.error("Method 2 Failed", e); }

// Method 3: Direct import of GraphqlClient (only session)
try {
  // import { GraphqlClient } from "@shopify/shopify-api";
  const client = new GraphqlClient({ session: offlineSession });
  // FAILED with: TypeError: Cannot read properties of undefined (reading 'isCustomStoreApp')
} catch (e) { console.error("Method 3 Failed", e); }

// Method 4: Direct import + specific config from main shopify object
try {
  // import { GraphqlClient } from "@shopify/shopify-api";
  // import shopify, { apiVersion } from "../shopify.server";
  const client = new GraphqlClient({
       config: shopify.config, // Also tried passing specific props like apiVersion, hostName etc.
       session: offlineSession
      });
   // FAILED with: TypeError: Cannot read properties of undefined (reading 'isCustomStoreApp' or 'hostName')
} catch (e) { console.error("Method 4 Failed", e); }

// Method 5: Using admin client from authenticate.flow context
// const flowContext = await shopify.authenticate.flow(request);
// if (flowContext && flowContext.admin && typeof flowContext.admin.graphql === 'function') {
//    const response = await flowContext.admin.graphql(SHOP_EMAIL_QUERY);
//    // FAILED with: 401 Unauthorized (suggests this client isn't using the correct offline token)
// }

Question:

What is the correct way to instantiate or obtain an authenticated Shopify Admin API GraphQL client within a Remix backend route (like a Flow action handler), using an offline session token retrieved from sessionStorage, especially considering the potential impact of the removeRest: true future flag (even if currently disabled)?

I can successfully make the shop { email } query using the GraphiQL tool provided by shopify app dev, which confirms the offline session and read_shop scope are valid. I just can’t get the client working in the action handler code.

Any help or examples would be greatly appreciated!

Bootstrap DatePicker disappearing

My CSS code is like below.

<link href="http://127.0.0.1:8000/assets/libs/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="http://127.0.0.1:8000/assets/libs/jquery-ui/jquery-ui.min.css" rel="stylesheet">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/css/animate.min.css">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/libs/owl-carousel/owl.carousel.min.css">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/libs/owl-carousel/owl.theme.default.min.css">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/libs/venobox/venobox.min.css">
<link href="http://127.0.0.1:8000/assets/css/icons.min.css" rel="stylesheet">
<link href="http://127.0.0.1:8000/assets/css/style.css" rel="stylesheet">
<link href="http://127.0.0.1:8000/assets/css/extra-style.css" rel="stylesheet">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/css/responsive.css">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/sweetalert2/sweetalert2.css">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/css/toastr.min.css">
<link rel="stylesheet" href="http://127.0.0.1:8000/assets/css/dropify.css">
<link href="http://127.0.0.1:8000/assets/libs/dropzone/dropzone.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="http://keith-wood.name/css/jquery.signature.css">
<link href="http://127.0.0.1:8000/assets/css/select2.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/build/css/intlTelInput.css">        
<link href="http://127.0.0.1:8000/assets/libs/datatables.net-bs4/css/dataTables.bootstrap4.min.css" rel="stylesheet">
<link href="http://127.0.0.1:8000/assets/libs/datatables.net-buttons-bs4/css/buttons.bootstrap4.min.css" rel="stylesheet">
<link href="http://127.0.0.1:8000/assets/libs/datatables.net-select-bs4/css/select.bootstrap4.min.css" rel="stylesheet">
<link href="http://127.0.0.1:8000/assets/libs/datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css" rel="stylesheet">

My JavaScript Code is like below.

<script src="http://127.0.0.1:8000/assets/libs/jquery/jquery-3.6.0.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/jquery-easing/jquery.easing.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/jquery-ui/jquery-ui.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/owl-carousel/owl.carousel.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/venobox/venobox.min.js"></script>
<script src="http://127.0.0.1:8000/assets/js/iconify.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/metismenu/metisMenu.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/simplebar/simplebar.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/dropzone/dropzone.js"></script>
<script src="http://127.0.0.1:8000/assets/js/pages/form-file-upload.init.js"></script>
<script src="http://127.0.0.1:8000/assets/sweetalert2/sweetalert2.all.js"></script>
<script src="http://127.0.0.1:8000/assets/js/toastr.min.js"></script>
<script src="http://127.0.0.1:8000/assets/js/custom/common.js"></script>
<script src="http://127.0.0.1:8000/assets/js/moment.js"></script>
<script src="http://127.0.0.1:8000/assets/js/dropify.js"></script>
<script src="http://127.0.0.1:8000/assets/js/select2.min.js"></script>
<script src="http://127.0.0.1:8000/assets/js/custom/information-view.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/signature_pad/1.5.3/signature_pad.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-bs4/js/dataTables.bootstrap4.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-buttons/js/dataTables.buttons.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-buttons-bs4/js/buttons.bootstrap4.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-buttons/js/buttons.html5.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-buttons/js/buttons.print.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-buttons/js/buttons.colVis.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-keytable/js/dataTables.keyTable.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-select/js/dataTables.select.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-responsive/js/dataTables.responsive.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatable/jszip/jszip.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatable/pdfmake/pdfmake.min.js"></script>
<script src="http://127.0.0.1:8000/assets/libs/datatable/pdfmake/vfs_fonts.js"></script>
<script src="http://127.0.0.1:8000/assets/js/custom/gas_safeties.js"></script>

I am using Bootstrap Datepicker in my Web Page. My DatePicker code is like below.

$(".datepicker").datepicker({
        dateFormat: "dd-mm-yy", 
        changeMonth: true, 
        changeYear: true, 
        yearRange: "1950:2050", 
        showButtonPanel: true,
    });

My Datepicker is look like below.

enter image description here

My issue is when I click on drop down arrow of Month then list of Month appears but the list disappears at once. Month list is not stay.

symfony ORM mapping any expert please help me or I will hit my head on wall

I am mapping one to many relation. I have a product entity under which there will be multiple features but I am getting this error and now I am frustrated here
error: Unrecognized field: AppEntityProduct: :$product (500 Internal Server Error)
this error is raising while calling the API
below is the relevant files contents

calling file

/**
 * @Route("/api/products/{id}/features", name="Features_list", methods={"GET"})
 */
public function featuresList(int $id, EntityManagerInterface $em): JsonResponse
{
    $product = $em->getRepository(Product::class)->find($id);
    if (!$product) {
        return new JsonResponse(['message' => 'No product found'], 404);
    }
    // print_r($product);exit();
    $features = $em->getRepository(Feature::class)->findBy([
        'product' => $product,
        'deleted' => 0 
    ]);

    if (!$features) {
        return new JsonResponse(['message' => 'No features found'], 404);
    }

Feature.php

/**
 * @ORMManyToOne(targetEntity="AppEntityProduct", inversedBy="features")
 * @ORMJoinColumn(name="product_id", referencedColumnName="id", nullable=false, 
   onDelete="CASCADE")
 */
private $product;

Product.php

/**
 * @ORMOneToMany(targetEntity="AppEntityFeature", mappedBy="product", orphanRemoval=true, cascade={"persist", "remove"})
 */
private $features;

/**
 * @return Collection|Feature[]
 */
public function getFeatures(): Collection
{
    return $this->features;
}

public function addFeature(Feature $feature): self
{
    if (!$this->features->contains($feature)) {
        $this->features[] = $feature;
        $feature->setProduct($this);
    }

    return $this;
}

public function removeFeature(Feature $feature): self
{
    if ($this->features->removeElement($feature)) {
        if ($feature->getProduct() === $this) {
            $feature->setProduct(null);
        }
    }

    return $this;
}

How can I optimize a PHP script that fetches 1M+ MySQL rows for reporting without exhausting memory? [duplicate]

I’m working on a PHP web application that generates reports from a MySQL table with over 1 million rows.

What I’m trying to do:

  • Fetch a large dataset and process it to generate a downloadable report (CSV format).

  • Improve speed and reduce memory usage.

What I’ve tried:

  • Pagination: I tried using LIMIT and OFFSET in chunks of 10,000.

  • Indexing: The main table is indexed on user_id and created_at.

  • Redis: I cache commonly accessed parts of the result set.

  • Output buffering: Used ob_flush() and flush() to stream output.

What I expected:

  • Significant reduction in memory usage and generation time.

  • Avoid timeouts and memory exhaustion.

What actually happened:

  • Still facing high memory usage (Allowed memory size exhausted) when generating large reports.

  • Execution time exceeds 30 seconds in some cases

set_time_limit(0);
ini_set('memory_limit', '512M');

$offset = 0;
$limit = 10000;
$fp = fopen('php://output', 'w');

while (true) {
    $query = "SELECT * FROM reports_table ORDER BY created_at ASC LIMIT $limit OFFSET $offset";
    $results = mysqli_query($conn, $query);

    if (mysqli_num_rows($results) == 0) break;

    while ($row = mysqli_fetch_assoc($results)) {
        fputcsv($fp, $row);
    }

    $offset += $limit;
    ob_flush();
    flush();
}

Stripe Auto-Payment does not working properly

I am encountering an issue with Stripe’s auto-payment process.

I need to create Stripe subscriptions in the unpaid state, setting the first payment date in the future. I can successfully create the subscription and set the future date using the trial_end parameter.

However, when the time comes for Stripe to process the automatic payment, the payment doesn’t go through properly — instead, Stripe creates the invoice in a draft state. As a result, the invoice.payment_succeeded webhook also fails to trigger and send the request to our website.

Below is create subscription request parameter:

API: https://api.stripe.com/v1/subscriptions

Method: POST

Authorization / Header: I am sending it correctly

Request Parameter:

trial_end:1746253519
items[0][price]:`my plan value`
customer:`stripe customer id`
proration_behavior:always_invoice
collection_method:charge_automatically
default_payment_method:`default payment id`

Note:
The same process works correctly when I create a Stripe subscription with a paid status — in that case, the auto-payment runs successfully, and the webhook (invoice.payment_succeeded) properly sends the response to our website.

I also tried modifying the request by adding the billing_cycle_anchor parameter, but I’m still facing the same issue.

Can someone help me understand what might be wrong with the parameters in my subscription creation request?

Thank you.

ECDSA-signed JWT validation failures between .NET and PHP

Why does a ECDSA-signed JWT in .NET fail validation in PHP when using OpenSSL, even with matching keys and algorithms?

  • In .NET using System.Security.Cryptography and System.IdentityModel.Tokens.Jwt packages.
  • In PHP using OpenSSL extension and Firebase's JWT library.
  • Algo: ECDSA(ES256)
  • Public key format: PEM

My example .NET code to generate JWT:

// ECDSA-signed JWT

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;

var privateKey = ECDsa.Create(ECCurve.NamedCurves.nistP256); // ES256
var securityKey = new ECDsaSecurityKey(privateKey) { KeyId = "1" };
var credentials = new SigningCredentials(securityKey, "ES256");
var token = new JwtSecurityToken(
    issuer: "https://example.com",
    audience: "https://example.com",
    claims: new[] { new Claim("test", "value") },
    expires: DateTime.UtcNow.AddHours(1),
    signingCredentials: credentials
);
var jwt = new JwtSecurityTokenHandler().WriteToken(token);
Console.WriteLine("JWT (will fail in PHP): " + jwt);
Console.Read();

My example PHP code to consume JWT:

<?php

require 'vendor/autoload.php';

use FirebaseJWTJWT;
use FirebaseJWTKey;

$jwt = '<JWT STRING HERE>'; // From .NET
$publicKey = openssl_pkey_get_public('path/to/public_key.pem'); // PEM-formatted public key.
try
{
   $decoded = JWT::decode($jwt, new Key($publicKey, 'ES256'));
   print_r($decoded);
}
catch (Exception $e)
{
   echo 'Validation error: ' . $e->getMessage();
}

PHP output:

Validation error: OpenSSL error: error:1C800064:Provider routines::bad signature

My instructions to create EXTRA ECDSA PEM formatted public-key for JWT:

# Generate private-key.
openssl ecparam -name prime256v1 -genkey -noout -out ec-private-key.pem

# Extract public-key from private-key.
openssl ec -in ec-private-key.pem -pubout -out ec-public-key.pem

Output files:

  • ec-private-key.pem (private)
  • ec-public-key.pem (public, for JWT validation).

Any idea why this happens?

ESLint import sorting rule not enforcing React import at the top of the file

Project Setup:
I have a new React project set up with TypeScript and Vite. I’m using ESLint for code linting with a custom configuration that enforces proper import ordering. The project is set up with the following dependencies:

  • React with TypeScript.
  • Vite as the build tool.

I have configured ESLint to ensure that imports are ordered properly, with the react import appearing at the top of the file.

eslint.config.js

import js from '@eslint/js';
import importPlugin from 'eslint-plugin-import';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import globals from 'globals';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  {
    ignores: ['dist'],
  },

  js.configs.recommended,
  ...tseslint.configs.recommended,

  {
    files: ['**/*.{ts,tsx,js,jsx}'],
    languageOptions: {
      ecmaVersion: 2020,
      sourceType: 'module',
      globals: {
        ...globals.browser,
        React: 'readonly', // Make React available globally
      },
    },
    plugins: {
      'react-hooks': reactHooks,
      'react-refresh': reactRefresh,
      import: importPlugin,
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],

      // formatting
      semi: ['error', 'always'],
      indent: ['error', 2],
      'no-mixed-spaces-and-tabs': 'error',

      // import sorting - enhanced rules
      'import/first': 'error', // Ensures all imports are at the top of the file
      'import/no-duplicates': 'error', // Prevents duplicate imports
      'import/newline-after-import': 'error', // Enforces a newline after import statements
      'import/order': [
        'error',
        {
          groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
          pathGroups: [
            {
              pattern: 'react',
              group: 'external',
              position: 'before',
            },
            {
              "pattern": "assets/**",
              "group": "internal",
              "position": "before"
            },
          ],
          pathGroupsExcludedImportTypes: ['react'],
          'newlines-between': 'always',
          alphabetize: {
            order: 'asc',
            caseInsensitive: true,
          },
        },
      ],
    },
  }
);

App.tsx

import reactLogo from './assets/react.svg';

import { useState } from 'react';

import viteLogo from '/vite.svg';
import './App.css';

function App() {
  const [count, setCount] = useState(0);

  return (
    <>
      <div>
        <a href="https://vite.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
   
    </>
  );
}

export default App;

Problem:

I expect ESLint to enforce that the react import appears at the top of the file (based on the ‘import/order’ rule), but it does not show an error when react is below other imports like viteLogo. However, when I move the react import below viteLogo, I do see the error saying react import should occur before import of ./assets/react.svg eslint(import/order)

I have the following import sorting rules in place:

  • ‘import/first’: ‘error’ (ensures imports appear at the top).

  • ‘import/order’: […] (sorting groups with a specific position for react).

What could be the issue with my configuration that prevents the react import from being enforced at the top of the file?