0.0.1 • Published 10 months ago

@mkwebdev/express-typescript-server v0.0.1

Weekly downloads
-
License
ISC
Repository
github
Last release
10 months ago

Express TypeScript Server

Un serveur Express.js moderne avec TypeScript et ES modules, conçu pour être utilisé comme une librairie réutilisable.

🚀 Fonctionnalités

  • ✨ Configuration simple et flexible
  • 🔒 Sécurité intégrée avec Helmet
  • 🌐 CORS configurables
  • 🔄 Recherche automatique de port disponible
  • 📦 Support complet ES Modules
  • 🛠️ Middleware d'erreur intégré
  • 📝 Types TypeScript inclus
  • 💾 Support Prisma intégré

📦 Installation

# Avec npm
npm install express-typescript-server

# Avec yarn
yarn add express-typescript-server

# Avec pnpm
pnpm add express-typescript-server

🔧 Configuration

Variables d'environnement (.env)

PORT=3000
NODE_ENV=development
CORS_ORIGIN=*
AUTO_FIND_PORT=true
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"
NEXT_PUBLIC_FRONTEND_URL="http://localhost:3000"

Options de configuration TypeScript

interface ServerConfig {
  port?: number; // Port du serveur (défaut: 3000)
  nodeEnv?: string; // Environnement (défaut: "development")
  apiPrefix?: string; // Préfixe des routes API (défaut: "/api/v1")
  corsOptions?: {
    // Options CORS
    origin?: string; // Origine autorisée (défaut: "*")
    // ... autres options CORS
  };
  autoFindPort?: boolean; // Recherche auto de port si occupé (défaut: false)
}

📘 Utilisation

Exemple de base

import { ExpressServer } from "express-typescript-server";

const server = new ExpressServer();

server
  .start()
  .then(({ port, app }) => {
    console.log(`🚀 Serveur démarré sur le port ${port}`);
  })
  .catch(console.error);

Configuration personnalisée

import { ExpressServer } from "express-typescript-server";

const server = new ExpressServer({
  port: 3000,
  apiPrefix: "/api/v2",
  autoFindPort: true,
  corsOptions: {
    origin: ["http://localhost:3000", "https://monapp.com"],
    credentials: true,
  },
});

// Démarrage du serveur
const { port, app } = await server.start();

// Ajout de routes personnalisées
app.get("/custom", (req, res) => {
  res.json({ message: "Ma route personnalisée" });
});

Utilisation avec async/await

async function démarrerServeur() {
  try {
    const server = new ExpressServer({
      port: 3000,
      autoFindPort: true,
    });

    const { port, app } = await server.start();
    console.log(`🚀 Serveur démarré sur le port ${port}`);

    return app;
  } catch (error) {
    console.error("❌ Erreur lors du démarrage:", error);
    process.exit(1);
  }
}

démarrerServeur();

🛣️ Routes par défaut

MéthodeRouteDescription
GET/Message de bienvenue
GET/api/v1/statusÉtat du serveur
POST/api/v1/database/urlConfiguration de la base de données

🔐 Sécurité

La librairie inclut par défaut :

  • Protection CORS configurable
  • Headers de sécurité avec Helmet
  • Parser JSON avec limites
  • Gestion des erreurs centralisée

🧪 Tests

# Exécuter les tests
npm test

# Vérifier la couverture
npm run test:coverage

📚 Documentation API complète

Classe ExpressServer

class ExpressServer {
  constructor(config?: ServerConfig);

  // Démarre le serveur
  async start(): Promise<{ port: number; app: Express }>;

  // Récupère l'instance Express
  getApp(): Express;
}

🤝 Contribution

  1. Fork le projet
  2. Créez votre branche (git checkout -b feature/AmazingFeature)
  3. Committez vos changements (git commit -m 'Add: Amazing Feature')
  4. Push sur la branche (git push origin feature/AmazingFeature)
  5. Ouvrez une Pull Request

📝 Licence

ISC - Voir le fichier LICENSE pour plus de détails.

🆘 Support

Pour toute question ou problème :

  1. Consultez les issues
  2. Créez une nouvelle issue si nécessaire
  3. Contactez l'équipe de maintenance

📱 Utilisation avec Next.js, React et Prisma

Configuration Prisma

  1. Installation des dépendances
npm install @prisma/client
npm install prisma --save-dev
  1. Initialisation de Prisma
npx prisma init
  1. Exemple de schéma Prisma (prisma/schema.prisma)
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
}

Structure des fichiers Next.js

votre-projet/
├── prisma/
│   └── schema.prisma
├── src/
│   ├── pages/
│   │   ├── api/
│   │   │   └── database/
│   │   │       └── [model]/
│   │   │           └── all.ts
│   │   └── users/
│   │       └── index.tsx
│   ├── components/
│   │   └── UserList.tsx
│   └── hooks/
│       └── useDatabase.ts

Configuration de l'API (Next.js)

// pages/api/database/[model]/all.ts
import { NextApiRequest, NextApiResponse } from "next";
import { ExpressServer } from "express-typescript-server";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();
const server = new ExpressServer({
  corsOptions: {
    origin: process.env.NEXT_PUBLIC_FRONTEND_URL,
  },
});

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== "GET") {
    return res.status(405).json({ message: "Méthode non autorisée" });
  }

  const { model } = req.query;
  const app = server.getApp();

  // Redirection vers le contrôleur de base de données
  app.get(`/api/v1/database/${model}/all`, (req, res) =>
    databaseController.findAll(req, res)
  );
}

Hook React personnalisé

// hooks/useDatabase.ts
import { useState, useEffect } from "react";

interface DatabaseHookOptions {
  autoFetch?: boolean;
}

export function useDatabase<T>(
  modelName: string,
  options: DatabaseHookOptions = {}
) {
  const [data, setData] = useState<T[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const fetchData = async () => {
    try {
      setLoading(true);
      const response = await fetch(`/api/database/${modelName}/all`);

      if (!response.ok) {
        throw new Error("Erreur lors de la récupération des données");
      }

      const result = await response.json();
      setData(result.data);
    } catch (err) {
      setError(err instanceof Error ? err : new Error("Erreur inconnue"));
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (options.autoFetch) {
      fetchData();
    }
  }, [modelName]);

  return {
    data,
    loading,
    error,
    refetch: fetchData,
  };
}

Composant React d'exemple

// components/UserList.tsx
import { useDatabase } from "../hooks/useDatabase";

interface User {
  id: number;
  email: string;
  name: string | null;
}

export function UserList() {
  const {
    data: users,
    loading,
    error,
    refetch,
  } = useDatabase<User>("user", { autoFetch: true });

  if (loading) return <div>Chargement...</div>;
  if (error) return <div>Erreur: {error.message}</div>;

  return (
    <div>
      <h1>Liste des Utilisateurs</h1>
      <button onClick={refetch}>Rafraîchir</button>
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            {user.name} ({user.email})
          </li>
        ))}
      </ul>
    </div>
  );
}

Page Next.js

// pages/users/index.tsx
import { UserList } from "../../components/UserList";

export default function UsersPage() {
  return (
    <div>
      <h1>Gestion des Utilisateurs</h1>
      <UserList />
    </div>
  );
}

Commandes utiles

# Générer le client Prisma
npx prisma generate

# Appliquer les migrations
npx prisma migrate dev

# Ouvrir Prisma Studio
npx prisma studio