pnpm --filter web dev ne démarre pas sous Windows : ${PORT_WEB:-4000} n'est pas substitué par cmd.exe #22
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Les scripts
devetstartd'apps/web/package.jsonutilisent une substitution de variable POSIX. pnpm passe les scripts parcmd.exesous Windows, qui ne la connaît pas : la chaîne arrive telle quelle ànext, qui refuse.Reproduction
Un clone neuf du gabarit, sur Windows,
pnpm install, puis :Sortie :
startporte exactement la même chaîne, donc le même sort.Le fichier fautif, sur
main(8e70251, aujourd'hui 09:20) :Ce que j'attendais, et pourquoi
Que
pnpm --filter web devdémarre le front, commepnpm --filter api devdémarre l'API. LeREADMEdu gabarit etAGENTS.mdprésentent les deux commandes sur le même plan, sans réserve de plateforme.C'est d'autant plus surprenant que le socle connaît déjà ce comportement : le corps du ticket #16 (
pnpm devrecompile enfin ce qu'il sert) écarte explicitement&en écrivant « pnpm passe les scripts parcmdsous Windows, où&enchaîne au lieu de mettre en fond », et choisitconcurrentlypour cette raison. Le même raisonnement n'a pas été appliqué à${...}dansapps/web.Versions
eqs --version:0.8.1packageManager:pnpm@11.8.0v24.15.0Ce que ça coûte
Bloquant pour lancer le front en développement sur un poste Windows — et toute l'équipe est sous Windows. Contourné localement en lançant
pnpm exec next dev --port 4000depuisapps/web/, sans modifier le gabarit : il n'y a donc aucun contournement à retirer dans le satellite une fois le défaut corrigé.Non détecté par la porte :
pnpm checkne joue nidevnistart, et la CI est sous Linux, où la substitution fonctionne. C'est un défaut qui ne peut apparaître que sur le poste de quelqu'un.Ce que je proposerais
Le plus simple, et cohérent avec ce que fait déjà
apps/api: lire le port depuis l'environnement dans du JavaScript plutôt que dans une chaîne de shell.nextacceptePORTdirectement, donc"dev": "next dev"suffirait si le port se règle parPORT— au prix de perdre le nomPORT_WEB, qui a peut-être sa raison d'être face àPORT_API.Sinon,
cross-envou un petit scriptnode scripts/dev.mjsqui résoutprocess.env.PORT_WEB ?? 4000et appellenext. C'est plus verbeux, mais c'est la seule forme qui se comporte pareil sur les deux plateformes.Une troisième voie serait
script-shelldans le.npmrcdu gabarit pour forcer un shell POSIX — je la mentionne pour être complet, mais elle m'a l'air pire : elle impose bash à tous les scripts de tous les satellites pour régler deux chaînes.Trouvé en développant le premier satellite réel (Pilotage), en vérifiant à l'écran une page qui consomme deux nouvelles opérations.
Vrai, reproduit, corrigé. Et votre rapprochement avec #16 était le bon fil : c'est bien la même cause, non portée.
Reproduction
Mesuré hors du gabarit, sur un manifeste jetable, pour isoler pnpm de Next :
pnpm 11.8, Windows 11. La chaîne arrive littéralement. Rien à ajouter à votre diagnostic.
Ce que la vérification a trouvé en plus
PORT_WEBn'a jamais réglé le port, sur aucune plateforme — Linux compris.${PORT_WEB}lit l'environnement du shell. Le.envdu dépôt, lui, est chargé parapps/web/next.config.mjs, c'est-à-dire dans le processus Next, bien après que--porta été analysé. Personne n'exportePORT_WEBdans son shell, donc sous Linux la substitution rendait toujours le défaut4000. La lignePORT_WEB=4000de.env.exampledécrivait un réglage qui n'existait pas — exactement ce que l'en-tête de ce fichier appelle « un mensonge qui se propage par copier-coller ».Le correctif fait donc les deux : il rend le script portable, et il fait marcher la variable.
La correction
Votre deuxième piste,
apps/web/scripts/next.mjs. Le.envracine est chargé d'abord, avec le même primitif quenext.config.mjs(process.loadEnvFile, natif, qui ne remplace pas une variable déjà posée — la précédence reste la bonne), puis le port est résolu, puisnextest lancé.Un détail qui compte : le script lance le point d'entrée JavaScript de
nextavec le Node courant, pas le shim.cmd. Passer par un shim aurait imposéshell: true, c'est-à-dire ramenercmd.exe— la cause du défaut.Vérifié trois fois :
PORT_WEBdans l'environnement du shellPORT_WEBdans le.envracineJ'ai écarté
script-shelldans le.npmrcpour la raison que vous donnez, etcross-envparce qu'il pose des variables, il n'en résout pas avec un défaut.Les quatre autres occurrences
Vous en aviez vu deux. En cherchant la classe dans toute la flotte, il y en avait six :
eqs-satellite-template/apps/webeqs-satellite-template/variantes/next-fullstack/apps/webeqs-demo/apps/web(${PORT:-4000})La variante n'a pas besoin d'une copie du script : son
READMEfusionnevariantes/next-fullstack/apps/web/.surapps/web/, donc celui de la base arrive avec. Seul son manifeste, qui écrase l'autre, devait changer.Aucune autre construction POSIX ailleurs dans la flotte — pas de
$(...), pas d'apostrophes simples, pas de/dev/null, pas de préfixeVAR=x. C'est un résultat et pas une absence de résultat : le reste est sain.Pour que ça ne revienne pas
Nouveau contrôle bloquant
tooling.script-shell-posixdans@eqs/tooling: un script de manifeste ne peut pas supposer un shell POSIX. Cinq formes refusées (${...},$(...),$NOM,> /dev/null, apostrophes simples) et cinq formes saines qui doivent rester vertes (&&,||, guillemets doubles,cross-env, un appelnode) — les cas verts sont dans lecheckdu package au même titre que les rouges, parce qu'une porte qui refuse un script sain se fait éteindre.Ce qu'il ne couvre pas, et c'est dit dans le code : le préfixe
VAR=x cmd, parce quecross-env FOO=bar cmda la même forme et fonctionne.L'ironie, parce qu'elle mérite d'être écrite
La forme correcte — un
node scripts/x.mjsqui litprocess.env.PORT_WEB— faisait rougirconfig.env-exampleen bloquant. Ce contrôle ne cherchait les noms de variables que dans les compose, lespackage.jsonet lesDockerfile: sortie du manifeste, la variable devenait « non référencée ». La porte punissait exactement ce qu'elle existe pour encourager, comme dans #47. Lesscripts/*.{mjs,js}sont maintenant lus.Et en élargissant ce scan, il devenait un
includes()sur du JavaScript, commentaires compris — l'en-tête du script corrigé citePORT_WEBquatre fois en prose. C'est la classe de #47 encore, dans le sens du faux négatif cette fois : une variable citée en commentaire serait passée pour utilisée, et une ligne morte de.env.exampleaurait survécu. Les commentaires sont écartés, éprouvé dans les deux sens.État
Trois branches, à fusionner dans cet ordre ou non, elles sont indépendantes :
eqs-satellite-template→fix/scripts-windows, basée surmain(pas surchore/socle-0-8-1, pour qu'elle vous débloque sans attendre)eqs-demo→fix/scripts-windowseqs-platform→chasse/knip-et-code-mort, qui porte le contrôleJe laisse ce ticket ouvert : la correction du gabarit vous débloque dès la fusion, mais le contrôle n'existera chez vous qu'à la prochaine version du socle. À vous de constater.
Un point à votre main : votre contournement
pnpm exec next dev --port 4000reste correct après la correction, mais il ignorePORT_WEB, qui fonctionne maintenant./connexion, qui n'existe pas : personne ne peut entrer dans l'application #23pnpm --filter api db:devest interactif : il bloque tout appelant non interactif, et l'interrompre laisse un verrou consultatif Postgres qui exige unpg_terminate_backendmanuel #63Corrigé, et par la voie que vous proposiez en second : le port est résolu en JavaScript avant d'appeler Next.
apps/web/package.jsonportenode scripts/next.mjs devetnode scripts/next.mjs start.Le script va plus loin que la substitution qu'il remplace, et son en-tête dit pourquoi :
${PORT_WEB}ne servait à rien même sous Linux, puisqu'il lit l'environnement du shell — que rien ne remplit. Le.envdu dépôt est chargé parnext.config.mjs, donc dans le processus Next, bien après l'analyse de--port.PORT_WEB=4000dans.envn'avait donc aucun effet sur aucune plateforme : la ligne de.env.exampledécrivait un réglage qui n'existait pas. Ici le.envest chargé avant de résoudre le port.Deux détails qui valaient d'être trouvés :
nextet pasnext.cmd(un shim.cmdobligerait àshell: true, c'est-à-dire à retomber surcmd.exe— exactement la cause de ce ticket), et...process.argv.slice(3)pour quepnpm --filter web dev -- --turbone perde plus ses arguments en silence.La classe a été chassée : six occurrences dans la flotte, dont
eqs-demo, où elle n'avait pas été signalée.Fermé après vérification sur
devle 2026-09-21. Ce ticket restait ouvert faute d'unCloses #22dans le commit, pas faute de correctif.