Stack qualité CI (MegaLinter, Trivy, ESLint) et purge du backlog lint web
Some checks failed
Qualité & Sécurité / MegaLinter (PMD · Ruff · Bandit · gitleaks · hadolint) (push) Successful in 1m9s
Build & Push Images / build (brain) (push) Successful in 1m10s
Qualité & Sécurité / Trivy (CVE dépendances Maven / pip / npm) (push) Failing after 2m36s
Build & Push Images / build (web) (push) Successful in 1m48s
Build & Push Images / build-switcher (push) Successful in 20s
Build & Push Images / build (core) (push) Successful in 3m9s
Qualité & Sécurité / Web (ESLint · angular-eslint + sonarjs) (push) Successful in 38s
Some checks failed
Qualité & Sécurité / MegaLinter (PMD · Ruff · Bandit · gitleaks · hadolint) (push) Successful in 1m9s
Build & Push Images / build (brain) (push) Successful in 1m10s
Qualité & Sécurité / Trivy (CVE dépendances Maven / pip / npm) (push) Failing after 2m36s
Build & Push Images / build (web) (push) Successful in 1m48s
Build & Push Images / build-switcher (push) Successful in 20s
Build & Push Images / build (core) (push) Successful in 3m9s
Qualité & Sécurité / Web (ESLint · angular-eslint + sonarjs) (push) Successful in 38s
CI (Gitea Actions) : - Nouveau workflow quality.yml (séparé de ci.yml, non bloquant pour la release) : MegaLinter v9 (PMD, Ruff, Bandit, gitleaks, hadolint), ng lint (web) et Trivy (CVE des dépendances Maven/pip/npm), sur main + beta + PR - Trivy : préchargement du cache Maven avant le scan — sans ça Maven Central rate-limite l'IP du runner (429) en résolvant les BOMs du parent Spring Boot - upload-artifact v4 → v3 : l'API artifacts v4 n'est pas supportée par Gitea (corrige aussi l'upload du rapport Playwright de e2e.yml, cassé depuis toujours) - Ruleset PMD projet (java-pmd-ruleset.xml, auto-détecté par MegaLinter) orienté bugs réels, sans le style Lombok-hostile du défaut : 11 337 → 65 findings ; PMD en mode rapport (JAVA_PMD_DISABLE_ERRORS) le temps de purger ce backlog Web : - angular-eslint 21 + eslint-plugin-sonarjs : les règles Sonar vivent désormais dans ESLint (config web/eslint.config.js, réglages justifiés en commentaire) - tsconfig : skipLibCheck + types:[] + node_modules ré-exclu — répare les builds desktop Windows/Linux cassés par le conflit @types/eslint-scope vs ESLint 9 - Purge du backlog lint : 114 erreurs → 0 sur 66 fichiers (ngOnDestroy vides supprimés, any typés avec les vrais DTOs, outputs (close) → (closed), regex super-linéaires désamorcées, ternaires/fonctions imbriqués dépliés, intention documentée sur les catch/error volontairement vides) - Bug latent corrigé au passage : license.service.disconnect() émettait undefined au lieu de true en cas de succès (masqué par un double cast)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable, catchError, of } from 'rxjs';
|
||||
import { Observable, catchError, map, of } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Reflet de LicenseStatus (enum cote backend).
|
||||
@@ -44,13 +44,13 @@ export interface BetaStatusDTO {
|
||||
enabled: boolean;
|
||||
updateAvailable: boolean;
|
||||
anyUnknown: boolean;
|
||||
images: Array<{
|
||||
images: {
|
||||
image: string;
|
||||
localVersion: string | null;
|
||||
remoteVersion: string | null;
|
||||
status: 'UP_TO_DATE' | 'UPDATE_AVAILABLE' | 'UNKNOWN';
|
||||
updateAvailable: boolean;
|
||||
}>;
|
||||
}[];
|
||||
checkedAt: string;
|
||||
disabledReason: string | null;
|
||||
}
|
||||
@@ -86,10 +86,13 @@ export class LicenseService {
|
||||
|
||||
disconnect(): Observable<boolean> {
|
||||
return this.http.delete<void>(this.apiUrl, this.authOptions).pipe(
|
||||
// Convertit en boolean : true = succes, false = erreur
|
||||
// (catchError plus bas masque les detail HTTP)
|
||||
catchError(() => of(false as any))
|
||||
) as unknown as Observable<boolean>;
|
||||
// Convertit en boolean : true = succes, false = erreur.
|
||||
// (Avant : le cast `as unknown as` masquait l'absence de map() — le
|
||||
// succes emettait `undefined`, donc falsy. Consommateur actuel ignore
|
||||
// la valeur, mais le type est desormais honnete.)
|
||||
map(() => true),
|
||||
catchError(() => of(false))
|
||||
);
|
||||
}
|
||||
|
||||
refresh(): Observable<LicenseStatusDTO | null> {
|
||||
|
||||
@@ -48,7 +48,9 @@ export interface NotebookAction {
|
||||
resolution?: string;
|
||||
}
|
||||
|
||||
const ACTION_RE = /```loremind-action\s*([\s\S]*?)```/g;
|
||||
// Pas de \s* avant la capture (backtracking quadratique) : la capture est
|
||||
// trim()ée avant JSON.parse de toute façon.
|
||||
const ACTION_RE = /```loremind-action([\s\S]*?)```/g;
|
||||
const VALID_TYPES = new Set(['npc', 'scene', 'chapter', 'arc', 'table']);
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,13 @@ import { Notebook, NotebookArchive, NotebookDetail, NotebookSource, NotebookChat
|
||||
import { LanguageService } from './language.service';
|
||||
import { parseSseStream } from '../shared/sse.util';
|
||||
|
||||
/** Normalise les sources renvoyées par le Brain (événement SSE `sources`). */
|
||||
function mapSseSources(sources: { source_id?: string; page?: number | null; score?: number }[] | undefined) {
|
||||
return (sources ?? []).map(s => ({
|
||||
sourceId: s.source_id ?? '', page: s.page ?? null, score: s.score ?? 0
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Service des notebooks (atelier RAG) : CRUD, upload/indexation de sources,
|
||||
* et chat ancré STREAMÉ (SSE via fetch, comme ai-chat.service).
|
||||
@@ -96,12 +103,7 @@ export class NotebookService {
|
||||
} else if (event === 'sources') {
|
||||
try {
|
||||
const o = JSON.parse(data) as { sources?: { source_id?: string; page?: number | null; score?: number }[] };
|
||||
emit({
|
||||
type: 'sources',
|
||||
sources: (o.sources ?? []).map(s => ({
|
||||
sourceId: s.source_id ?? '', page: s.page ?? null, score: s.score ?? 0
|
||||
}))
|
||||
});
|
||||
emit({ type: 'sources', sources: mapSseSources(o.sources) });
|
||||
} catch { /* ignore */ }
|
||||
} else if (event === 'progress') {
|
||||
try {
|
||||
|
||||
@@ -40,7 +40,7 @@ export interface Page {
|
||||
* Pour chaque champ TABLE (colonnes figees au template, lignes libres) :
|
||||
* fieldName → lignes ordonnees, chaque ligne = colonne → cellule.
|
||||
*/
|
||||
tableValues?: Record<string, Array<Record<string, string>>>;
|
||||
tableValues?: Record<string, Record<string, string>[]>;
|
||||
notes?: string | null;
|
||||
tags?: string[];
|
||||
relatedPageIds?: string[];
|
||||
|
||||
@@ -46,9 +46,10 @@ export class VersionCheckerService {
|
||||
*/
|
||||
start(): void {
|
||||
if (this.timer !== null) return;
|
||||
void this.fetchInitial();
|
||||
// Fire-and-forget : fetchInitial/poll gèrent leurs erreurs en interne.
|
||||
this.fetchInitial();
|
||||
this.timer = setInterval(
|
||||
() => void this.poll(),
|
||||
() => { this.poll(); },
|
||||
VersionCheckerService.POLL_INTERVAL_MS,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user