diff --git a/scripts/check-licences.mjs b/scripts/check-licences.mjs
index 00e89c7..d5b2665 100644
--- a/scripts/check-licences.mjs
+++ b/scripts/check-licences.mjs
@@ -6,11 +6,10 @@
* Écrit parce que ce fichier est une affirmation juridique, et qu'une affirmation que
* personne ne revérifie dérive à la première montée de version.
*
- * CE FICHIER EST PARTAGÉ À L'IDENTIQUE par map3D, panels et IA Studio. La liste blanche,
+ * CE FICHIER EST PARTAGÉ À L'IDENTIQUE par map3D, panels et AI Desktop Studio. La liste blanche,
* les paquets embarqués et la nature du dépôt vivent dans `repo.config.json`.
*/
import { readFileSync, existsSync } from 'node:fs'
-import { execFileSync } from 'node:child_process'
import { resolve } from 'node:path'
const root = resolve(import.meta.dirname, '..')
@@ -54,37 +53,35 @@ for (const nom of EMBARQUES) {
if (!propre.devDependencies?.[nom]) problemes.push(`${nom} est déclaré embarqué mais n'est pas installé.`)
}
-/** La licence qu'un paquet déclare, lue dans l'arbre installé. */
+/**
+ * La licence qu'un paquet déclare, par le lien que le gestionnaire pose pour toute dépendance
+ * déclarée — alias `npm:` compris. Le balayage de `node_modules/.pnpm` qui la précédait s'arrêtait
+ * un segment trop haut, et ne voyait aucun paquet scopé.
+ */
function licenceDe(nom) {
try {
- const trouves = execFileSync('find', [
- 'node_modules/.pnpm',
- '-maxdepth',
- '4',
- '-path',
- `*/node_modules/${nom}/package.json`,
- ])
- .toString()
- .split('\n')
- .filter(Boolean)
-
- if (trouves.length === 0) return null
- return JSON.parse(readFileSync(trouves[0], 'utf8')).license ?? null
+ return JSON.parse(readFileSync(resolve(root, 'node_modules', nom, 'package.json'), 'utf8'))
+ .license ?? null
} catch {
return null
}
}
-const declarees = [
+const installees = [
...Object.keys(propre.dependencies ?? {}),
...Object.keys(propre.devDependencies ?? {}),
- ...Object.keys(propre.peerDependencies ?? {}),
]
+// Une pair est déclarée pour le consommateur, et le gestionnaire n'installe pas celles qui sont
+// optionnelles : absente ici, elle n'a rien à juger. Ce que CE dépôt installe, si.
+const declarees = [...installees, ...Object.keys(propre.peerDependencies ?? {})]
+const lues = declarees.map(nom => [nom, licenceDe(nom)])
-for (const nom of declarees) {
- const licence = licenceDe(nom)
- if (licence === null) continue // pas installé ici ; rien à juger
- if (!AUTORISEES.has(licence)) problemes.push(`${nom} est en ${licence}, absent de la liste blanche.`)
+for (const [nom, licence] of lues) {
+ // Taire l'échec de lecture est ce qui faisait passer pour jugé tout paquet que la lecture ratait.
+ if (licence === null && installees.includes(nom))
+ problemes.push(`${nom} est déclaré mais sa licence est illisible : paquet absent, ou sans champ « license ».`)
+ else if (licence !== null && !AUTORISEES.has(licence))
+ problemes.push(`${nom} est en ${licence}, absent de la liste blanche.`)
}
if (problemes.length > 0) {
@@ -93,4 +90,7 @@ if (problemes.length > 0) {
process.exit(1)
}
-console.log(`Licences contrôlées — ${declarees.length} paquets, tous permissifs, mentions présentes.`)
+const jugees = lues.filter(([, licence]) => licence !== null).length
+console.log(
+ `Licences contrôlées — ${jugees} paquets lus sur ${declarees.length} déclarés, tous permissifs, mentions présentes.`,
+)
diff --git a/site/template.html b/site/template.html
index 0d1a74e..bc37d6b 100644
--- a/site/template.html
+++ b/site/template.html
@@ -35,6 +35,14 @@
+
+
+