youtubeDownloader/client/build.mjs
Nicolas 29aadd28a4
All checks were successful
Publier l'image Docker / test (push) Successful in 30s
Publier l'image Docker / publish (push) Successful in 1m10s
feat: squelette serveur/client + Docker + CI de build/release
Pose l'infrastructure de base avant l'implémentation des fonctionnalités :
- server/ : Fastify + TypeScript (ESM), route /health, sert client/dist
- client/ : TypeScript vanilla + esbuild/sass, vue placeholder (shell)
- server/Dockerfile : image multi-étapes avec yt-dlp + ffmpeg embarqués
- .forgejo/workflows/publish-docker.yml : test puis publication sur le
  registre de conteneurs Forgejo (nécessite le secret REGISTRY_TOKEN)
- biome.json : lint du repo entier (downloader/ exclu)
- spec/architecture.md : documentation de ces choix

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 07:55:43 +02:00

57 lines
2 KiB
JavaScript

// Build client : TypeScript (+ .html/.scss par vue) -> client/dist, via
// esbuild. Script à la main plutôt qu'un outil plus lourd (Vite, webpack) :
// le client reste pour l'instant minimal, et esbuild suffit - y compris
// pour le Sass (voir le plugin ci-dessous, qui délègue à `sass` puis laisse
// esbuild regrouper le CSS résultant, importé depuis le JS, dans un
// app.css voisin).
//
// Usage : node build.mjs [--watch]
// npm run build -> build unique (celui lancé par server/Dockerfile)
// npm run watch -> reconstruit à chaque sauvegarde, pour le dev local
import { copyFileSync, mkdirSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import * as esbuild from 'esbuild';
import * as sass from 'sass';
const here = path.dirname(fileURLToPath(import.meta.url));
const outdir = path.join(here, 'dist');
mkdirSync(outdir, { recursive: true });
copyFileSync(path.join(here, 'src', 'index.html'), path.join(outdir, 'index.html'));
/** Plugin esbuild : compile les imports `.scss` en CSS via le paquet `sass`. */
const sassPlugin = {
name: 'sass',
setup(build) {
build.onLoad({ filter: /\.scss$/ }, async (args) => {
const result = await sass.compileAsync(args.path);
return { contents: result.css, loader: 'css' };
});
},
};
const buildOptions = {
entryPoints: [path.join(here, 'src', 'app.ts')],
outfile: path.join(outdir, 'app.js'),
bundle: true,
format: 'esm',
target: 'es2020',
sourcemap: true,
// Chaque vue importe son propre gabarit comme chaîne brute (`import html
// from './Vue.html'` - voir global.d.ts) et son propre style Sass ; les
// styles sont regroupés automatiquement par esbuild dans app.css.
loader: { '.html': 'text' },
plugins: [sassPlugin],
};
const watch = process.argv.includes('--watch');
if (watch) {
const ctx = await esbuild.context(buildOptions);
await ctx.watch();
console.log('[youtubedownloader-client] watching for changes...');
} else {
await esbuild.build(buildOptions);
console.log('[youtubedownloader-client] built to client/dist');
}