diff --git a/CREDITS.md b/CREDITS.md index f7e62ec..399d9e0 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -49,6 +49,14 @@ Les contenus pédagogiques (leçons, textes) sont sous licence CC BY-SA 4.0. inclus dans le moteur WebAssembly, licences compatibles GPLv3. L'image fournit aussi **Node.js** (MIT), qui rejoue la suite de contrat sur le moteur WebAssembly et lance `make bench`. +- **Image `ustagammon/web`** (`docker/web/Dockerfile`), construite sur + `node:22.11.0-alpine3.20` : **TypeScript** 6.0.3 (Apache-2.0), qui compile + `app/` ; **@types/node** 22.20.5 (MIT), types de Node pour les tests ; + **Biome** 2.5.15 (MIT ou Apache-2.0), lint et formatage ; + **@cucumber/cucumber** 12.9.0 (MIT), qui exécute les scénarios de + `docs/scenarios/` ; **dependency-cruiser** 18.6.0 (MIT), qui vérifie les + règles d'architecture. Ces outils et leurs dépendances servent seulement à + compiler et tester : rien n'est embarqué dans l'application. ## Remerciements diff --git a/Makefile b/Makefile index 861c59e..4689c18 100644 --- a/Makefile +++ b/Makefile @@ -20,17 +20,21 @@ REFERENCE_IMAGE := ustagammon/gnubg-reference:14b6798 BUILD_C_IMAGE := ustagammon/build-c:2 # Emscripten (compilation WebAssembly ; contient aussi Node et Python 3). WASM_IMAGE := emscripten/emsdk:3.1.64 +# Outils de l'application web (docker/web/) : TypeScript, Biome, Cucumber, +# dependency-cruiser. Changer l'étiquette à chaque modification du Dockerfile. +WEB_IMAGE := ustagammon/web:1 # Port de la page de test servie sur le réseau local (make deploy-web). WEB_PORT := 8080 -export SHELLCHECK_IMAGE GHERKIN_IMAGE BUILD_C_IMAGE WASM_IMAGE +export SHELLCHECK_IMAGE GHERKIN_IMAGE BUILD_C_IMAGE WASM_IMAGE WEB_IMAGE # Lance une commande dans la chaîne C, sous l'utilisateur courant pour que # build/ lui appartienne. DOCKER_C := docker run --rm --user "$$(id -u):$$(id -g)" -v "$(CURDIR):/src" -w /src $(BUILD_C_IMAGE) DOCKER_WASM := docker run --rm --user "$$(id -u):$$(id -g)" -e HOME=/tmp -v "$(CURDIR):/src" -w /src $(WASM_IMAGE) +DOCKER_WEB := docker run --rm --user "$$(id -u):$$(id -g)" -v "$(CURDIR):/src" -w /src $(WEB_IMAGE) -.PHONY: help setup build engine engine-wasm bench test lint deploy deploy-web clean reference-image reference +.PHONY: help setup build engine engine-wasm web bench test lint deploy deploy-web clean reference-image reference help: ## Liste les commandes disponibles @echo "Ustagammon : commandes disponibles" @@ -48,9 +52,11 @@ setup: ## Installe la chaîne d'outils (images Docker) ; sans effet si déjà fa || docker build -t $(BUILD_C_IMAGE) docker/build-c @docker image inspect $(WASM_IMAGE) >/dev/null 2>&1 \ || docker pull $(WASM_IMAGE) + @docker image inspect $(WEB_IMAGE) >/dev/null 2>&1 \ + || docker build -t $(WEB_IMAGE) docker/web @echo "Chaîne d'outils prête." -build: engine ## Compile le moteur (si nécessaire) puis l'application +build: engine-wasm web ## Compile le moteur (si nécessaire) puis l'application engine: ## Compile le moteur, ses données et build/engine-cli (dans Docker) @docker image inspect $(BUILD_C_IMAGE) >/dev/null 2>&1 \ @@ -62,6 +68,16 @@ engine-wasm: engine ## Compile le moteur en WebAssembly dans build/wasm/ (dans D || { echo "Emscripten absent : lancer d'abord make setup"; exit 1; } @$(DOCKER_WASM) make -f engine-wasm/wasm.mk -j2 --no-print-directory +# L'application est recompilée entièrement (quelques secondes) : build/web/ +# ne garde ainsi aucun fichier dont la source a disparu. Le package.json +# indique à Node que les .js produits sont des modules ES. +web: ## Compile l'application TypeScript (app/) dans build/web/ (dans Docker) + @docker image inspect $(WEB_IMAGE) >/dev/null 2>&1 \ + || { echo "Outils web absents : lancer d'abord make setup"; exit 1; } + @rm -rf $(BUILD_DIR)/web + @$(DOCKER_WEB) tsc -p app/tsconfig.json + @cp app/package.json $(BUILD_DIR)/web/package.json + bench: engine-wasm ## Mesure le moteur WebAssembly sous Node, sur ce PC (rapport texte) @$(DOCKER_WASM) node engine-wasm/bench.mjs diff --git a/app/biome.json b/app/biome.json new file mode 100644 index 0000000..8383124 --- /dev/null +++ b/app/biome.json @@ -0,0 +1,20 @@ +{ + "files": { + "includes": ["**", "!**/node_modules"] + }, + "formatter": { + "indentStyle": "space", + "indentWidth": 4, + "lineWidth": 100 + }, + "linter": { + "rules": { + "preset": "recommended" + } + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + } +} diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..fcec3c7 --- /dev/null +++ b/app/package.json @@ -0,0 +1,6 @@ +{ + "name": "ustagammon-app", + "private": true, + "license": "GPL-3.0-or-later", + "type": "module" +} diff --git a/app/tsconfig.json b/app/tsconfig.json new file mode 100644 index 0000000..59a052b --- /dev/null +++ b/app/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2023", + "lib": ["ES2023"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "types": ["node"], + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "rootDir": ".", + "outDir": "../build/web" + }, + "include": ["src", "tests"] +} diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile new file mode 100644 index 0000000..9ba20e6 --- /dev/null +++ b/docker/web/Dockerfile @@ -0,0 +1,25 @@ +# Outils de l'application web (ADR 0009) : TypeScript, Biome, Cucumber et +# dependency-cruiser, sous Node. Rien de tout cela n'est embarqué dans +# l'application : ces outils compilent, vérifient et testent. +# +# Les modules sont installés dans /opt/tools, puis rendus visibles sous +# /node_modules, à la racine du conteneur : Node et TypeScript les trouvent en +# remontant depuis le dépôt monté sous /src, sans node_modules dans le dépôt. +# (npm refuse d'installer directement à la racine.) +# +# Versions figées, publiées depuis plus de deux semaines au 2026-11-02. +# Cucumber reste en 12.x : la 13 charge des modules ES avec require(), ce que +# Node 22.11 ne fait pas sans option (il faut Node 22.12). +FROM node:22.11.0-alpine3.20 + +WORKDIR /opt/tools +RUN npm install --no-audit --no-fund --save-exact \ + typescript@6.0.3 \ + @types/node@22.20.5 \ + @biomejs/biome@2.5.15 \ + @cucumber/cucumber@12.9.0 \ + dependency-cruiser@18.6.0 \ + && npm cache clean --force \ + && ln -s /opt/tools/node_modules /node_modules + +ENV PATH="/opt/tools/node_modules/.bin:${PATH}" diff --git a/tests/lint.sh b/tests/lint.sh index 7631a75..7406a01 100755 --- a/tests/lint.sh +++ b/tests/lint.sh @@ -51,6 +51,19 @@ if [ "${#scripts[@]}" -gt 0 ]; then fi fi +# Application web (ADR 0009), dans Docker : Biome (style et erreurs +# courantes) et TypeScript (types). Le domaine est vérifié une seconde fois +# seul, sans les types de Node ni du navigateur : il doit rester pur. +if ! docker image inspect "${WEB_IMAGE:?lancer via make lint}" >/dev/null 2>&1; then + signaler "Outils web absents : lancer d'abord make setup" +else + web=(docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/src:ro" -w /src/app "$WEB_IMAGE") + "${web[@]}" biome check . || signaler "Biome a trouvé des problèmes (voir ci-dessus)" + "${web[@]}" tsc -p tsconfig.json --noEmit || signaler "TypeScript a trouvé des erreurs (voir ci-dessus)" + "${web[@]}" tsc -p src/domain/tsconfig.json \ + || signaler "le domaine utilise Node ou le navigateur (voir ci-dessus)" +fi + if [ "$erreurs" -gt 0 ]; then echo "Lint : $erreurs problème(s)." exit 1