Guide de résolution des erreurs de chemin dans Cool Admin Midway : de l'échec au démarrage à la gestion élégante

Cet article propose une solution complète pour résoudre les erreurs de chemin fréquentes dans le projet Cool Admin Midway. Vous apprendrez à diagnostiquer, corriger et prévenir ces problèmes pour assurer un démarrage fiable de votre application.

1. Architecture des chemins dans Cool Admin Midway

1.1 Structure des répertoires du projet

Cool Admin Midway adopte une architecture modulaire. Voici un aperçu de sa structure de dossiers :

src/
├── comm/           # Modules communs
│   ├── path.ts     # Utilitaire de gestion des chemins
│   ├── port.ts     # Configuration des ports
│   └── utils.ts    # Fonctions utilitaires générales
├── config/         # Répertoire des fichiers de configuration
└── modules/        # Modules métier
    ├── base/       # Module de base
    ├── demo/       # Module d'exemple
    └── ...         # Autres modules métier

1.2 Module principal de gestion des chemins

Le fichier src/comm/path.ts est le cœur de la gestion des chemins. Il fournit des fonctions utilitaires pour centraliser et normaliser les opérations sur les chemins.

// Extrait de src/comm/path.ts
import { join } from 'path';
import { app } from 'midway';

export class PathUtil {
  static getRootPath(): string {
    return app.baseDir;
  }

  static getResourcePath(...paths: string[]): string {
    return join(this.getRootPath(), 'src', 'resources', ...paths);
  }
  // Autres méthodes...
}

2. Types d'erreurs de chemin et diagnostic

2.1 Symptômes courants

  • Erreur au démarrage : le projet plante immédiatement avec un message comme Error: ENOENT: no such file or directory.
  • Erreur à l'exécution : le projet démarre, mais échoue lors d'une opération spécifique.
  • Erreur intermittente : fonctionne en développement, mais échoue en production.

2.2 Causes fréquentes

  • Mauvaise utilisation des chemins relatifs : résolution incohérente selon le contexte d'exécution.
  • Dépendance aux variables d'environnement : variables non configurées dans certains enviornnements.
  • Différences de système de fichiers : utilisation de séparateurs de chemin inadaptés (Windows vs Linux).
  • Problèmes de build : erreurs de conversion de chemins lors de la compilation TypeScript.

3. Solutions détaillées

3.1 Utilisation de PathUtil pour centraliser la gestion

Voici un exemple comparatif :

// ❌ Mauvais : chemin relatif direct
import { readFileSync } from 'fs';
const config = JSON.parse(readFileSync('../../config/app.json', 'utf8'));

// ✅ Bon : utilisation de PathUtil
import { PathUtil } from '../comm/path';
import { readFileSync } from 'fs';
const configPath = PathUtil.getResourcePath('config', 'app.json');
const config = JSON.parse(readFileSync(configPath, 'utf8'));

3.2 Gestion des chemins dynamiques

Pour les chemins générés dynamiquement (ex : upload de fichiers) :

// src/modules/base/service/fileService.ts
import { Provide } from '@midwayjs/decorator';
import { PathUtil } from '../../../comm/path';
import { writeFile } from 'fs/promises';

@Provide()
export class FileService {
  async saveUploadFile(fileName: string, content: Buffer): Promise<string> {
    const date = new Date();
    const subDir = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
    const fullPath = PathUtil.getResourcePath('uploads', subDir, fileName);
    await this.ensureDirExists(PathUtil.getResourcePath('uploads', subDir));
    await writeFile(fullPath, content);
    return fullPath;
  }

  private async ensureDirExists(dirPath: string): Promise<void> {
    // Logique de création de répertoire...
  }
}
</void></string>

3.3 Chemins dans les fichiers de configuration

Utilisez toujours des chemins relatifs dans les configurations, résolus à l'exécution via PathUtil :

// src/config/config.default.ts
export default {
  uploadPath: 'resources/uploads', // Relatif, pas absolu
};

// Dans le service
import { Config } from '@midwayjs/decorator';
import { PathUtil } from '../comm/path';

export class UploadService {
  @Config('uploadPath')
  private uploadPath!: string;

  getUploadPath(): string {
    return PathUtil.getRootPath(this.uploadPath);
  }
}

4. Prévention des erreurs de chemin

4.1 Règles à suivre

  • Utilisez PathUtil pour toutes les opérations sur les chemins.
  • Évitez tout chemin codé en dur dans le code métier.
  • Dans les configurations, utilisez des chemins relatifs au répertoire racine.
  • Utilisez path.join() ou les méthodes de PathUtil pour concaténer les chemins.

4.2 Tests unitaires des chemins

// test/unit/comm/path.test.ts
import { PathUtil } from '../../../src/comm/path';
import { expect } from 'chai';

describe('PathUtil', () => {
  describe('getResourcePath', () => {
    it('should return correct resource path', () => {
      const path = PathUtil.getResourcePath('config', 'app.json');
      // Vérification...
    });
  });
});

4.3 Surveillance des erreurs de chemin

Ajoutez un middleware global pour capturer les erreurs de chemin :

// src/middleware/errorHandler.ts
import { Middleware, IMiddleware } from '@midwayjs/decorator';
import { Context } from 'egg';

@Middleware()
export class ErrorHandlerMiddleware implements IMiddleware<context> {
  resolve() {
    return async (ctx: Context, next: () => Promise<void>) => {
      try {
        await next();
      } catch (err) {
        if (err.code === 'ENOENT' || err.message.includes('path') || err.message.includes('directory')) {
          ctx.logger.error('Erreur de chemin :', {
            message: err.message,
            stack: err.stack,
            path: err.path || 'inconnu',
            requestId: ctx.requestId,
            timestamp: new Date().toISOString()
          });
          this.sendPathErrorAlert(err, ctx);
        }
        // Autres erreurs...
      }
    };
  }

  private async sendPathErrorAlert(err: Error, ctx: Context): Promise<void> {
    // Logique d'alerte...
  }
}
</void></void></context>

5. Étude de cas : d'un crash à la reprise

5.1 Problème

Après déploiement en production, le projet plante au démarrage avec :

Error: ENOENT: no such file or directory, open '/root/cool-admin/resources/templates/mail.html'

5.2 Diagnostic

Le service mail utilisait un chemin relatif qui fonctionnait en développement, mais échouait en production car le code compilé se trouve dans dist/.

// Code problématique
const templatePath = '../../resources/templates/mail.html';
const templateContent = fs.readFileSync(templatePath, 'utf8');

5.3 Correction

Remplacez par PathUtil :

import { PathUtil } from '../../../comm/path';
const templatePath = PathUtil.getResourcePath('templates', 'mail.html');
const templateContent = fs.readFileSync(templatePath, 'utf8');

5.4 Mesures préventives

  • Ajoutez une vérification des chemins dans le processus de revue de code.
  • Créez des tests unitaires pour les chemins.
  • Intégrez une validation des chemins dans le pipeline CI/CD.

6. Conclusion

Les erreurs de chemin sont courantes dans Cool Admin Midway, mais peuvent être évitées en centralisant la gestion via PathUtil, en utilisant des chemins relatifs et en automatisant les tests. Suivez ces bonnes pratiques pour garantir un démarrage fiable de votre projet.

Étiquettes: Cool Admin Midway Midway.js TypeScript gestion des chemins PathUtil

Publié le 14 juillet à 11h08