---
title: "Debug et Logs"
weight: 120
---

# Debug et Logs

SmartCommon fournit un système de logs colorés pour faciliter le debug de votre application.

## Activer le mode debug

Dans la configuration du Provider :

```
const config = {
  debug: true, // Active les logs globalement
  api: {
    debug: true // Active les logs API spécifiquement
  }
};
```

En développement, utilisez la variable d'environnement :

```
const config = {
  debug: import.meta.env.DEV // true en dev, false en prod
};
```

## Utilitaire log

SmartCommon exporte un utilitaire `log` avec des méthodes colorées :

```
import { log } from '@cap-rel/smartcommon';

// Logs d'état
log.state('Changement d\'état:', newState);
log.globalState('État global mis à jour:', globalState);

// Logs de cycle de vie
log.effect('useEffect déclenché');
log.page('Page chargée: /dashboard');

// Logs de statut
log.success('Opération réussie');
log.error('Une erreur est survenue:', error);
log.warning('Attention:', message);
log.info('Information:', data);

// Logs API
log.apiLoading('GET', '/api/items');
log.apiSuccess('GET - 200', '/api/items');
log.apiError('GET - 404', '/api/items');

// Logs base de données
log.db('INSERT:', item);

// Logs de localisation
log.location('Navigation vers:', path);

// Log personnalisé
log.custom('MON_TAG', 'purple', 'Mon message', data);
```

## Couleurs des logs

Chaque type de log a une couleur distincte dans la console :

| Méthode | Couleur | Usage |
| --- | --- | --- |
| `log.state` | Bleu | Changements d'état local |
| `log.globalState` | Cyan foncé | Changements d'état global |
| `log.effect` | Violet | Effets React (useEffect) |
| `log.page` | Orange | Chargement de pages |
| `log.success` | Vert | Opérations réussies |
| `log.error` | Rouge | Erreurs |
| `log.warning` | Doré | Avertissements |
| `log.info` | Gris | Informations |
| `log.apiLoading` | Gris | Requête API en cours |
| `log.apiSuccess` | Vert | Requête API réussie |
| `log.apiError` | Rouge | Requête API échouée |
| `log.db` | Bleu nuit | Opérations IndexedDB |
| `log.location` | Rose | Navigation |

## createLogger - Logger avec namespace

Pour les projets plus complexes, `createLogger` permet de créer un logger avec un namespace dédié. Les logs peuvent être filtrés par namespace via `localStorage.LOG_FILTER`.

```
import { createLogger } from '@cap-rel/smartcommon';

const logger = createLogger('MyModule');

logger.info('Module initialisé');
logger.success('Données chargées');
logger.error('Échec du chargement');
logger.warning('Données périmées');
logger.state('Changement local:', newState);
logger.globalState('Changement global:', data);
logger.effect('useEffect déclenché');
logger.page('/dashboard');
logger.db('INSERT', item);

// API (premier paramètre = label dynamique)
logger.apiLoading('GET /items');
logger.apiSuccess('GET /items', data);
logger.apiError('GET /items', error);

// Personnalisé
logger.custom('PERF', 'orange', 'Rendu en 12ms');

// Groupes
logger.group('Initialisation');
logger.info('Étape 1');
logger.info('Étape 2');
logger.groupEnd();
```

### Filtrer par namespace

Dans la console du navigateur :

```
localStorage.LOG_FILTER = 'MyModule,Auth';  // Affiche uniquement ces namespaces
localStorage.LOG_LEVEL = 'warn';            // debug | info | warn | error
```

## DebugConsole - Console intégrée

Le composant `DebugConsole` affiche les logs SmartCommon directement dans l'application (FAB flottant `>_` en bas à gauche, panneau avec toolbar de recherche/filtres, logs colorés auto-scrollés).

### Activation

La `DebugConsole` est montée par le `Provider` **uniquement si la prop `debug` est passée explicitement** (ce n'est PAS `config.debug` qui la déclenche, mais la prop du Provider lui-même) :

```
import { Provider } from '@cap-rel/smartcommon';

// Active uniquement en mode développement
<Provider config={config} debug={import.meta.env.DEV}>
  <App />
</Provider>

// Toujours active
<Provider config={config} debug>
  <App />
</Provider>
```

La prop `config.debug` reste indépendante : elle contrôle la verbosité des logs produits par les hooks SmartCommon (useStates, useGlobalStates, useApi, etc.), indépendamment de l'affichage de la `DebugConsole`.

### Props

| Prop | Type | Défaut | Description |
| --- | --- | --- | --- |
| `defaultOpen` | boolean | false | Console ouverte au démarrage |
| `position` | string | "bottom" | Position : "bottom", "top", "left", "right" |
| `height` | string/number | "40vh" | Hauteur de la console |
| `maxLogs` | number | 500 | Nombre maximum de logs conservés |
| `showFab` | boolean | true | Afficher le bouton flottant ">_" |

### Utilisation manuelle (sans Provider)

```
import { DebugConsole } from '@cap-rel/smartcommon';

<DebugConsole defaultOpen={true} position="bottom" maxLogs={200} />
```

La console peut être détachée dans une fenêtre séparée via le bouton de détachement. Les logs sont partagés entre les fenêtres via `BroadcastChannel`.

## DebugWarnings - Breakpoints automatiques sur warnings React

Le composant `DebugWarnings` intercepte `console.error` pendant qu'il est monté et déclenche `debugger` dès qu'un warning React connu est émis. Les DevTools (Firefox ou Chrome) mettent alors l'exécution en pause pile au moment du warning, avec la pile React complète accessible pour identifier le composant fautif.

Quand les DevTools sont fermées, `debugger` est un `no-op` : aucun impact sur l'exécution normale.

### Activation

Comme la `DebugConsole`, `DebugWarnings` est automatiquement monté par le `Provider` **quand la prop `debug` est passée** :

```
<Provider config={config} debug={import.meta.env.DEV}>
  <App />
</Provider>
```

Inactif en production (quand `debug` est `false` / absent). Aucune configuration supplémentaire nécessaire dans les projets SmartMaker.

### Warnings interceptés

Les motifs suivants déclenchent un breakpoint automatique :
- `Received NaN for the value attribute` - NaN passé à un `<input>`
- `value prop on input should not be null` - `value={null}` sur un input
- `changing a controlled input to be uncontrolled` - `value` passe de défini à `undefined`
- `changing an uncontrolled input to be controlled` - inverse
- `Each child in a list should have a unique "key"` - `key` manquante dans un `.map()`
- `Maximum update depth exceeded` - boucle infinie de re-renders
- `Cannot update a component` - setState pendant le render d'un autre composant
- `Warning: Failed prop type` - prop-types violé
- `Warning: React does not recognize` - prop non standard passée au DOM

### Diagnostic automatique avant le breakpoint

Avant de déclencher `debugger`, `DebugWarnings` affiche un `console.group` orange contenant :

  - **Raw console.error args** : tableau brut des arguments de React (utile si React inclut un `componentStack`)
  - **React hint** : extraction du "Check the render method of `XXX`" quand React le mentionne
  - **Suspects ciblés** : pour les warnings `value` et `NaN`, la liste des fibers dont `memoizedProps.value` correspond au problème, avec l'owner React et la source `.jsx`
  - **Dump complet des fibers de formulaire** (`console.table`) : tous les `<input>`, `<textarea>`, `<select>` du DOM avec leur `value`, `type`, `name`, `owner` (nom du composant parent React) et `source` (fichier:ligne:col si disponible)

Le dump est construit en parcourant tous les fiber roots via `window.__REACT_DEVTOOLS_GLOBAL_HOOK__`. **React DevTools doit être installé** dans le navigateur pour que le fallback fonctionne complètement.

Dans 90% des cas la table `console.table` suffit à identifier visuellement la ligne qui a une valeur inattendue (`undefined`, `NaN`, `null`, type incohérent).

### Usage avec les DevTools

  - Ouvre les DevTools (`F12`)
  - Onglet Console : repère le bloc orange `[DebugWarnings]`
  - Déroule la table des form fibers -> spot la ligne avec une valeur anormale -> tu as `owner` et `source`
  - Si besoin de la Call Stack React : onglet Debugger, l'exécution est en pause sur `debugger` dans `DebugWarnings/index.jsx`
  - Avec les source maps activées (voir *Configuration Vite pour debug* ci-dessous), cliquer sur `source` t'amène directement au fichier `.jsx`

### Utilisation manuelle

Si tu veux activer uniquement les breakpoints sans la `DebugConsole` UI :

```
import { DebugWarnings } from '@cap-rel/smartcommon';

<App>
  {import.meta.env.DEV && <DebugWarnings />}
  ...
</App>
```

Ou inversement : `DebugConsole` sans les breakpoints en le montant manuellement au lieu d'utiliser la prop `debug` du Provider.

## Configuration Vite pour debug

Le `vite.config.js` de SmartCommon (et celui de tout projet SmartMaker qui produit une lib) est configuré pour deux modes de build :

```javascript
const shouldMinify = process.env.MINIFY !== "false";

export default defineConfig({
  build: {
    sourcemap: true,            // Toujours generer les source maps
    minify: shouldMinify,       // Minifier sauf si MINIFY=false
    lib: { ... }
  },
  ...
});
```

### Deux modes

| Commande | Usage | Taille dist |
| --- | --- | --- |
| `npm run build` | Build prod minifié + sourcemap | Normal (~1.2 MB pour smartcommon) |
| `MINIFY=false npm run build` | Build dev lisible + sourcemap | Plus gros (~1.7 MB) mais noms originaux preserves |

### Pourquoi les source maps

Sans source maps, les stack traces dans Firefox / Chrome affichent des noms minifiés (`FM`, `Nn`, `ee2`...) impossibles à interpreter.

Avec source maps :
- La Call Stack affiche les vrais noms de composants (`Tabbar`, `SignaturePad`, `HomePage`...)
- Cliquer sur une frame t'amène directement au `.jsx` source, ligne exacte
- `DebugWarnings` renseigne le champ `source` dans ses dumps (fichier:ligne:col)
- React DevTools peut remonter correctement aux composants applicatifs

**Dans Firefox**, si tu vois le message *"Le mappage des noms originaux est désactivé"*, coche **"Afficher les variables originales"** dans le panneau Portées du Debugger.

### Pourquoi le mode non-minifié (MINIFY=false)

Même avec les source maps, le code minifié peut résister au débugage (noms de variables locales compactés, reassignments hors ordre...). Le mode `MINIFY=false` garde tous les noms originaux dans le bundle lui-même, ce qui rend le debugger beaucoup plus lisible quand tu mets des `breakpoint` dans le source smartcommon.

**Règle** : utiliser `MINIFY=false` uniquement pour débugger en local, jamais pour la publication.

## Workflow de développement local avec smartcommon

Pour itérer rapidement sur smartcommon sans avoir à publier une version npm à chaque changement, utiliser un symlink depuis les `node_modules` du projet consommateur.

### Setup initial

```bash
# Dans le projet consommateur (ex. smartInterventions mobile)
cd ~/dev/monprojet/mobile
rm -rf node_modules/@cap-rel/smartcommon
ln -s ~/dev/smartcommon node_modules/@cap-rel/smartcommon
```

Le projet consommateur lit directement le `dist/` de `~/dev/smartcommon/` via le symlink.

### Boucle de dev

  - Modifier le source dans `~/dev/smartcommon/src/`
  - `cd ~/dev/smartcommon && MINIFY=false npm run build` (4-5 secondes)
  - Dans le projet consommateur : `rm -rf node_modules/.vite` (purge du pre-bundle Vite)
  - Vite recharge automatiquement au prochain hit

### Avantages / inconvénients
- **Avantages** : pas de `npm publish`, pas d'attente d'indexation du registre, pas de bump de version à chaque test
- **Inconvénient** : il faut purger `.vite/` à chaque rebuild car Vite pre-bundle les `node_modules`

### Retour au mode normal

Pour reinstaller la version du registre :

```bash
rm ~/dev/monprojet/mobile/node_modules/@cap-rel/smartcommon
cd ~/dev/monprojet/mobile
npm install @cap-rel/smartcommon@<version>
```

## Logs automatiques

Quand `debug: true` est activé, SmartCommon log automatiquement :

### useStates

```
const st = useStates({
  initialStates: { count: 0 },
  debug: true // Active les logs pour ce hook
});

st.set('count', 1);
// Console: [STATE] SET count => 1
```

### useGlobalStates

```
const gst = useGlobalStates();
gst.local.set('user', userData);
// Console: [GLOBAL STATE] SET user => {...}
```

### useDb

```
const db = useDb({
  name: 'myApp',
  stores: { items: 'id++' },
  debug: true
});

await db.items.add({ name: 'Item' });
// Console: [DB] CREATE key = 1, item = {...}
```

### useApi

```
// Avec api.debug: true dans la config

api.private.get('items');
// Console: [GET - LOADING] https://api.example.com/items
// Console: [GET - 200] https://api.example.com/items
```

## Debug conditionnel

Activez le debug uniquement pour certains hooks :

```
// Debug global désactivé
const config = { debug: false };

// Mais debug activé pour un hook spécifique
const st = useStates({
  initialStates: { ... },
  debug: true // Override la config globale
});
```

## Console du navigateur

Les logs SmartCommon utilisent des styles CSS dans la console. Pour les voir correctement :

1. Ouvrez les DevTools (F12)
2. Allez dans l'onglet "Console"
3. Assurez-vous que le filtre "Verbose" est activé

### Filtrer les logs

Dans la console, utilisez le filtre pour afficher uniquement certains types :
- Tapez `STATE` pour voir les logs d'état
- Tapez `API` pour voir les logs API
- Tapez `DB` pour voir les logs base de données

## Bonnes pratiques

### Désactiver en production

```
const config = {
  debug: import.meta.env.DEV,
  api: {
    debug: import.meta.env.DEV
  }
};
```

### Logs personnalisés dans vos composants

```
import { log } from '@cap-rel/smartcommon';
import { useLibConfig } from '@cap-rel/smartcommon';

const MyComponent = () => {
  const { debug } = useLibConfig();

  const handleClick = () => {
    if (debug) {
      log.custom('MY_COMPONENT', 'teal', 'Button clicked');
    }
    // ...
  };
};
```

### Ne pas logger de données sensibles

```
// Mauvais
log.info('User logged in:', { password: user.password });

// Bon
log.info('User logged in:', { id: user.id, email: user.email });
```

## Voir aussi
- [Configuration](/front/configuration) - Configuration du Provider
- [Hooks](/front/hooks) - Documentation des hooks
