nestgen-cli 0.0.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,32 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
2
4
 
3
5
  # ────── Charger les helpers ──────
4
- FEATURES_PATH="$(dirname "$0")/features"
6
+ FEATURES_PATH="$(dirname "$0")"
5
7
  source "$FEATURES_PATH/utils.sh"
6
8
  source "$FEATURES_PATH/logger.sh"
7
9
 
8
10
 
9
- PM=$1
10
- APP_NAME=$2
11
+ PM=${1:?Package manager requis}
12
+ APP_NAME=${2:?Nom_application_requis}
13
+
14
+ if [ -e prisma/schema.prisma ]; then
15
+ echo "❌ prisma/schema.prisma existe déjà. Aucune configuration Prisma n'a été remplacée."
16
+ exit 1
17
+ fi
11
18
 
12
- $PM install prisma --save-dev
13
- $PM install @prisma/client
14
- npx prisma init
19
+ pm_add_dev "$PM" prisma@6
20
+ pm_add "$PM" @prisma/client@6
21
+ pm_exec "$PM" prisma init
15
22
 
23
+ if [ ! -e .env ]; then
16
24
  cat > .env <<EOF
17
25
  DATABASE_URL="postgresql://postgres:postgres@localhost:5432/$APP_NAME"
18
26
  EOF
27
+ else
28
+ echo "ℹ️ .env existe déjà et a été conservé."
29
+ fi
19
30
 
20
31
  cat > prisma/schema.prisma <<EOF
21
32
  generator client {
@@ -28,6 +39,35 @@ datasource db {
28
39
  }
29
40
  EOF
30
41
 
31
- npx prisma generate
42
+ mkdir -p src/prisma
43
+ cat > src/prisma/prisma.service.ts <<'EOF'
44
+ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
45
+ import { PrismaClient } from '@prisma/client';
46
+
47
+ @Injectable()
48
+ export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
49
+ async onModuleInit(): Promise<void> {
50
+ await this.$connect();
51
+ }
52
+
53
+ async onModuleDestroy(): Promise<void> {
54
+ await this.$disconnect();
55
+ }
56
+ }
57
+ EOF
58
+
59
+ cat > src/prisma/prisma.module.ts <<'EOF'
60
+ import { Global, Module } from '@nestjs/common';
61
+ import { PrismaService } from './prisma.service';
62
+
63
+ @Global()
64
+ @Module({
65
+ providers: [PrismaService],
66
+ exports: [PrismaService],
67
+ })
68
+ export class PrismaModule {}
69
+ EOF
70
+
71
+ pm_exec "$PM" prisma generate
32
72
 
33
73
  echo "✅ Prisma initialisé avec succès !"
@@ -0,0 +1,57 @@
1
+ const RESOURCE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/i;
2
+ const ROUTE_PATTERN = /^[a-z][a-z0-9-]*$/;
3
+ const TABLE_PATTERN = /^[a-z][a-z0-9_]*$/;
4
+
5
+ function fail(message) {
6
+ throw new Error(`Nom de ressource invalide : ${message}`);
7
+ }
8
+
9
+ function pluralize(word) {
10
+ if (/(?:s|x|z|ch|sh)$/i.test(word)) return `${word}es`;
11
+ if (/[^aeiou]y$/i.test(word)) return `${word.slice(0, -1)}ies`;
12
+ return `${word}s`;
13
+ }
14
+
15
+ export function describeResource(rawName, options = {}) {
16
+ const name = String(rawName ?? '').trim();
17
+ if (!RESOURCE_NAME_PATTERN.test(name)) {
18
+ fail('il doit commencer par une lettre et ne contenir que des lettres, chiffres, tirets ou underscores.');
19
+ }
20
+
21
+ const segments = name.toLowerCase().split(/[-_]/);
22
+ const singular = segments.join('-');
23
+ const plural = options.plural
24
+ ? String(options.plural).trim().toLowerCase()
25
+ : `${segments.slice(0, -1).join('-')}${segments.length > 1 ? '-' : ''}${pluralize(segments.at(-1))}`;
26
+ const route = options.route ? String(options.route).trim().toLowerCase() : plural;
27
+ const table = options.table ? String(options.table).trim().toLowerCase() : plural.replaceAll('-', '_');
28
+
29
+ if (!ROUTE_PATTERN.test(plural)) fail('le pluriel doit être une ressource kebab-case.');
30
+ if (!ROUTE_PATTERN.test(route)) fail('la route doit être une ressource kebab-case.');
31
+ if (!TABLE_PATTERN.test(table)) fail('la table doit être une ressource snake_case.');
32
+
33
+ const pascal = segments.map((segment) => `${segment[0].toUpperCase()}${segment.slice(1)}`).join('');
34
+ return {
35
+ name: singular,
36
+ pascal,
37
+ camel: `${pascal[0].toLowerCase()}${pascal.slice(1)}`,
38
+ plural,
39
+ route,
40
+ table,
41
+ };
42
+ }
43
+
44
+ if (import.meta.url === `file://${process.argv[1]}`) {
45
+ try {
46
+ const [rawName] = process.argv.slice(2);
47
+ const resource = describeResource(rawName, {
48
+ plural: process.env.RESOURCE_PLURAL,
49
+ route: process.env.RESOURCE_ROUTE,
50
+ table: process.env.RESOURCE_TABLE,
51
+ });
52
+ for (const [key, value] of Object.entries(resource)) console.log(`${key.toUpperCase()}=${value}`);
53
+ } catch (error) {
54
+ console.error(`❌ ${error.message}`);
55
+ process.exitCode = 1;
56
+ }
57
+ }
@@ -1,27 +1,14 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
2
4
 
3
5
  # ────── Charger les helpers ──────
4
- FEATURES_PATH="$(dirname "$0")/features"
6
+ FEATURES_PATH="$(dirname "$0")"
5
7
  source "$FEATURES_PATH/utils.sh"
6
8
  source "$FEATURES_PATH/logger.sh"
7
9
 
8
10
 
9
- PM=$1
10
-
11
- $PM install @nestjs/swagger swagger-ui-express
12
-
13
- # Ajout dans main.ts (à faire manuellement ou via automatisation)
14
- echo ""
15
- echo "📘 Pour activer Swagger, ajoute ceci dans main.ts :"
16
- echo ""
17
- cat <<'DOC'
18
- import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
11
+ PM=${1:?Package manager requis}
19
12
 
20
- const config = new DocumentBuilder()
21
- .setTitle('API Docs')
22
- .setDescription('The API description')
23
- .setVersion('1.0')
24
- .build();
25
- const document = SwaggerModule.createDocument(app, config);
26
- SwaggerModule.setup('api', app, document);
27
- DOC
13
+ pm_add "$PM" @nestjs/swagger@12 swagger-ui-express@5
14
+ log_success "Swagger sera activé sur /api dans src/main.ts."
@@ -1,19 +1,80 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
 
3
- PM=$1
4
- APP_NAME=$2
3
+ set -euo pipefail
4
+
5
+ PM=${1:?Package manager requis}
6
+ APP_NAME=${2:?Nom_application_requis}
5
7
 
6
8
  # ────── Charger les helpers ──────
7
9
  FEATURES_PATH="$(dirname "$0")"
8
10
  source "$FEATURES_PATH/utils.sh"
9
11
  source "$FEATURES_PATH/logger.sh"
10
12
 
11
- INSTALL_CMD=$(get_install_cmd "$PM")
12
-
13
13
  log_info "📦 Installation de TypeORM et PostgreSQL..."
14
14
 
15
- $PM $INSTALL_CMD @nestjs/typeorm typeorm pg
15
+ pm_add "$PM" @nestjs/typeorm@12 typeorm@0.3 pg@8 dotenv@16
16
+ pm_add_dev "$PM" ts-node@10
17
+
18
+ mkdir -p src/database/migrations
19
+
20
+ cat > src/database/typeorm.config.ts <<'EOF'
21
+ import type { TypeOrmModuleOptions } from '@nestjs/typeorm';
22
+
23
+ function required(name: string): string {
24
+ const value = process.env[name];
25
+ if (!value) throw new Error(`Variable d'environnement manquante : ${name}`);
26
+ return value;
27
+ }
28
+
29
+ export function typeOrmOptions(): TypeOrmModuleOptions {
30
+ return {
31
+ type: 'postgres',
32
+ host: required('DATABASE_HOST'),
33
+ port: Number(process.env.DATABASE_PORT ?? 5432),
34
+ username: required('DATABASE_USER'),
35
+ password: required('DATABASE_PASSWORD'),
36
+ database: required('DATABASE_NAME'),
37
+ autoLoadEntities: true,
38
+ synchronize: false,
39
+ migrationsRun: false,
40
+ migrations: ['dist/database/migrations/*.js'],
41
+ };
42
+ }
43
+ EOF
44
+
45
+ cat > src/database/data-source.ts <<'EOF'
46
+ import 'dotenv/config';
47
+ import { DataSource, type DataSourceOptions } from 'typeorm';
48
+ import { typeOrmOptions } from './typeorm.config';
49
+
50
+ const options = typeOrmOptions();
51
+
52
+ export default new DataSource({
53
+ ...(options as DataSourceOptions),
54
+ entities: ['src/**/*.entity{.ts,.js}'],
55
+ migrations: ['src/database/migrations/*{.ts,.js}'],
56
+ });
57
+ EOF
58
+
59
+ cat > src/database/migrations/0000000000000-InitialSchema.ts <<'EOF'
60
+ import type { MigrationInterface, QueryRunner } from 'typeorm';
61
+
62
+ export class InitialSchema0000000000000 implements MigrationInterface {
63
+ async up(_queryRunner: QueryRunner): Promise<void> {}
64
+ async down(_queryRunner: QueryRunner): Promise<void> {}
65
+ }
66
+ EOF
67
+
68
+ if [ ! -e .env.example ]; then
69
+ cat > .env.example <<'EOF'
70
+ DATABASE_HOST=localhost
71
+ DATABASE_PORT=5432
72
+ DATABASE_USER=postgres
73
+ DATABASE_PASSWORD=change-me
74
+ DATABASE_NAME=appdb
75
+ EOF
76
+ fi
16
77
 
17
78
  log_success "✅ TypeORM installé avec succès"
18
79
 
19
- log_info "💡 TypeORM sera automatiquement configuré dans app.module.ts"
80
+ log_info "💡 TypeORM utilise src/database/typeorm.config.ts et src/database/data-source.ts pour des migrations explicites."
@@ -0,0 +1,146 @@
1
+ import fs from 'node:fs';
2
+
3
+ const [appModulePath, moduleClass, modulePath, orm] = process.argv.slice(2);
4
+
5
+ function fail(message) {
6
+ throw new Error(`Impossible de mettre à jour AppModule : ${message}`);
7
+ }
8
+
9
+ function findMatching(source, start, open, close) {
10
+ let depth = 0;
11
+ let quote = null;
12
+ let escaped = false;
13
+ let lineComment = false;
14
+ let blockComment = false;
15
+
16
+ for (let index = start; index < source.length; index += 1) {
17
+ const character = source[index];
18
+ const next = source[index + 1];
19
+
20
+ if (lineComment) {
21
+ if (character === '\n') lineComment = false;
22
+ continue;
23
+ }
24
+ if (blockComment) {
25
+ if (character === '*' && next === '/') {
26
+ blockComment = false;
27
+ index += 1;
28
+ }
29
+ continue;
30
+ }
31
+ if (quote) {
32
+ if (!escaped && character === quote) quote = null;
33
+ escaped = !escaped && character === '\\';
34
+ if (character !== '\\') escaped = false;
35
+ continue;
36
+ }
37
+ if (character === '/' && next === '/') {
38
+ lineComment = true;
39
+ index += 1;
40
+ continue;
41
+ }
42
+ if (character === '/' && next === '*') {
43
+ blockComment = true;
44
+ index += 1;
45
+ continue;
46
+ }
47
+ if (character === '"' || character === "'" || character === '`') {
48
+ quote = character;
49
+ continue;
50
+ }
51
+ if (character === open) depth += 1;
52
+ if (character === close) {
53
+ depth -= 1;
54
+ if (depth === 0) return index;
55
+ }
56
+ }
57
+
58
+ fail(`délimiteur ${open}${close} non fermé.`);
59
+ }
60
+
61
+ function findDecoratorObject(source) {
62
+ const decoratorMatch = /@Module\s*\(/.exec(source);
63
+ if (!decoratorMatch) fail('décorateur @Module introuvable.');
64
+
65
+ const objectStart = source.indexOf('{', decoratorMatch.index + decoratorMatch[0].length);
66
+ if (objectStart === -1) fail('objet du décorateur @Module introuvable.');
67
+
68
+ return {
69
+ start: objectStart,
70
+ end: findMatching(source, objectStart, '{', '}'),
71
+ };
72
+ }
73
+
74
+ function findImportsArray(source, object) {
75
+ const propertyPattern = /\bimports\s*:\s*\[/g;
76
+ let match;
77
+
78
+ while ((match = propertyPattern.exec(source)) !== null) {
79
+ if (match.index > object.end) break;
80
+ const before = source.slice(object.start + 1, match.index);
81
+ let depth = 0;
82
+ for (const character of before) {
83
+ if (character === '{') depth += 1;
84
+ if (character === '}') depth -= 1;
85
+ }
86
+ if (depth !== 0) continue;
87
+
88
+ const arrayStart = match.index + match[0].lastIndexOf('[');
89
+ return { start: arrayStart, end: findMatching(source, arrayStart, '[', ']') };
90
+ }
91
+
92
+ fail('tableau imports dans @Module introuvable ou non supporté.');
93
+ }
94
+
95
+ function containsToken(items, token) {
96
+ const escaped = token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
97
+ return new RegExp(`\\b${escaped}\\b`).test(items);
98
+ }
99
+
100
+ function appendImports(source, array, additions) {
101
+ if (additions.length === 0) return source;
102
+
103
+ const current = source.slice(array.start + 1, array.end);
104
+ const separator = current.trim() === '' ? '' : current.trimEnd().endsWith(',') ? '\n' : ',\n';
105
+ const indentation = current.includes('\n') ? (current.match(/\n([ \t]*)[^\n]*$/)?.[1] ?? ' ') : '';
106
+ const inserted = additions.map((item) => `${indentation}${item}`).join(',\n');
107
+ const replacement =
108
+ current.trim() === ''
109
+ ? current.includes('\n')
110
+ ? `\n${inserted}\n `
111
+ : inserted
112
+ : `${current}${separator}${inserted}`;
113
+
114
+ return `${source.slice(0, array.start + 1)}${replacement}${source.slice(array.end)}`;
115
+ }
116
+
117
+ function addImport(source, line) {
118
+ return source.includes(line) ? source : `${line}\n${source}`;
119
+ }
120
+
121
+ try {
122
+ let source = fs.readFileSync(appModulePath, 'utf8');
123
+ const object = findDecoratorObject(source);
124
+ const array = findImportsArray(source, object);
125
+ const currentImports = source.slice(array.start + 1, array.end);
126
+ const additions = [];
127
+
128
+ if (!containsToken(currentImports, 'CqrsModule')) additions.push('CqrsModule');
129
+ if (!containsToken(currentImports, moduleClass)) additions.push(moduleClass);
130
+ if (orm === 'typeorm' && !/\bTypeOrmModule\.forRoot(?:Async)?\s*\(/.test(currentImports)) {
131
+ additions.unshift('TypeOrmModule.forRootAsync({ useFactory: typeOrmOptions })');
132
+ }
133
+
134
+ source = appendImports(source, array, additions);
135
+ source = addImport(source, `import { ${moduleClass} } from '${modulePath}';`);
136
+ source = addImport(source, "import { CqrsModule } from '@nestjs/cqrs';");
137
+ if (orm === 'typeorm') {
138
+ source = addImport(source, "import { typeOrmOptions } from './database/typeorm.config';");
139
+ source = addImport(source, "import { TypeOrmModule } from '@nestjs/typeorm';");
140
+ }
141
+
142
+ fs.writeFileSync(appModulePath, source);
143
+ } catch (error) {
144
+ console.error(`❌ ${error.message}`);
145
+ process.exitCode = 1;
146
+ }
@@ -1,12 +1,55 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
 
3
- # ────── Commande d'installation adaptée au package manager ──────
4
- get_install_cmd() {
5
- local PM=$1
6
- case "$PM" in
7
- yarn) echo "add" ;;
8
- pnpm|npm) echo "install" ;;
9
- *) echo "install" ;;
3
+ NEST_CLI_VERSION="12.0.0"
4
+
5
+ assert_package_manager() {
6
+ local package_manager=$1
7
+ case "$package_manager" in
8
+ npm|pnpm|yarn) assert_command_exists "$package_manager" ;;
9
+ *)
10
+ echo "❌ Package manager non supporté : $package_manager. Valeurs acceptées : npm, pnpm, yarn."
11
+ return 1
12
+ ;;
13
+ esac
14
+ }
15
+
16
+ pm_add() {
17
+ local package_manager=$1
18
+ shift
19
+ case "$package_manager" in
20
+ npm) npm install "$@" ;;
21
+ pnpm) pnpm add "$@" ;;
22
+ yarn) yarn add "$@" ;;
23
+ esac
24
+ }
25
+
26
+ pm_add_dev() {
27
+ local package_manager=$1
28
+ shift
29
+ case "$package_manager" in
30
+ npm) npm install --save-dev "$@" ;;
31
+ pnpm) pnpm add --save-dev "$@" ;;
32
+ yarn) yarn add --dev "$@" ;;
33
+ esac
34
+ }
35
+
36
+ pm_exec() {
37
+ local package_manager=$1
38
+ shift
39
+ case "$package_manager" in
40
+ npm) npm exec -- "$@" ;;
41
+ pnpm) pnpm exec "$@" ;;
42
+ yarn) yarn exec "$@" ;;
43
+ esac
44
+ }
45
+
46
+ nest_new() {
47
+ local package_manager=$1
48
+ local destination=$2
49
+ case "$package_manager" in
50
+ npm) npx --yes "@nestjs/cli@${NEST_CLI_VERSION}" new "$destination" --package-manager npm --skip-git ;;
51
+ pnpm) pnpm dlx "@nestjs/cli@${NEST_CLI_VERSION}" new "$destination" --package-manager pnpm --skip-git ;;
52
+ yarn) yarn dlx "@nestjs/cli@${NEST_CLI_VERSION}" new "$destination" --package-manager yarn --skip-git ;;
10
53
  esac
11
54
  }
12
55
 
@@ -16,11 +59,6 @@ assert_command_exists() {
16
59
  if ! command -v "$CMD" &> /dev/null; then
17
60
  echo "❌ Commande introuvable : $CMD"
18
61
  echo "👉 Installe-la ou vérifie ton PATH"
19
- exit 1
62
+ return 1
20
63
  fi
21
64
  }
22
-
23
- # ────── Formatage ──────
24
- to_pascal_case() {
25
- echo "$1" | sed -E 's/(^|-|_)([a-z])/\U\2/g'
26
- }
@@ -1,9 +1,10 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
 
3
3
  # ────── INIT ──────
4
- set -e
4
+ set -euo pipefail
5
5
 
6
- FEATURES_PATH="$(dirname "$0")/features"
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ FEATURES_PATH="$SCRIPT_DIR/features"
7
8
  source "$FEATURES_PATH/utils.sh"
8
9
  source "$FEATURES_PATH/logger.sh"
9
10
 
@@ -19,6 +20,20 @@ debug_log() {
19
20
  fi
20
21
  }
21
22
 
23
+ run_step() {
24
+ local step=$1
25
+ shift
26
+
27
+ log_info "$step"
28
+ if "$@"; then
29
+ return 0
30
+ else
31
+ local status=$?
32
+ log_error "$step a échoué (code $status)."
33
+ exit "$status"
34
+ fi
35
+ }
36
+
22
37
  debug_log "Script lancé avec les arguments : $*"
23
38
  debug_log "Chemin du script courant : $(pwd)"
24
39
  debug_log "Features path : $FEATURES_PATH"
@@ -30,14 +45,8 @@ FULL_PATH="$PROJECT_PATH/$APP_NAME"
30
45
  PM=${PM:-$(read -p "📦 Package manager (npm/yarn/pnpm) : " tmp && echo "$tmp")}
31
46
  ORM=${ORM:-$(read -p "🧠 ORM ? (typeorm/prisma) : " tmp && echo "$tmp")}
32
47
 
33
- INSTALL_CMD=$(get_install_cmd "$PM")
34
- debug_log "Install command : $PM $INSTALL_CMD"
35
-
36
- # ────── Vérification de Nest CLI ──────
37
- if ! command -v nest &> /dev/null; then
38
- log_warn "Nest CLI non installée. Installation avec npm..."
39
- npm install -g @nestjs/cli
40
- fi
48
+ run_step "Vérification du package manager" assert_package_manager "$PM"
49
+ debug_log "Package manager : $PM ; Nest CLI local : $NEST_CLI_VERSION"
41
50
 
42
51
  # ────── Création du projet ──────
43
52
  log_info "Création du projet à $FULL_PATH"
@@ -47,23 +56,19 @@ cd "$FULL_PATH" || {
47
56
  exit 1
48
57
  }
49
58
 
50
- nest new . --package-manager "$PM" --skip-git || {
51
- log_error "Échec de nest new"
52
- exit 1
53
- }
59
+ run_step "Création du projet NestJS" nest_new "$PM" .
54
60
 
55
- log_info "Installation des packages communs..."
56
- $PM $INSTALL_CMD @nestjs/cqrs class-validator class-transformer @nestjs/config
61
+ run_step "Installation des packages communs" pm_add "$PM" @nestjs/cqrs@12 @nestjs/config@4 class-validator@0.14 class-transformer@0.5
57
62
 
58
63
  # ────── ORM SETUP ──────
59
64
  case "$ORM" in
60
65
  typeorm)
61
66
  debug_log "Appel de typeorm.sh"
62
- bash "$FEATURES_PATH/typeorm.sh" "$PM" "$APP_NAME"
67
+ run_step "Configuration de TypeORM" bash "$FEATURES_PATH/typeorm.sh" "$PM" "$APP_NAME"
63
68
  ;;
64
69
  prisma)
65
70
  debug_log "Appel de prisma.sh"
66
- bash "$FEATURES_PATH/prisma.sh" "$PM" "$APP_NAME"
71
+ run_step "Configuration de Prisma" bash "$FEATURES_PATH/prisma.sh" "$PM" "$APP_NAME"
67
72
  ;;
68
73
  *)
69
74
  log_error "❌ ORM non reconnu : $ORM"
@@ -73,62 +78,27 @@ esac
73
78
 
74
79
  # ────── Docker, Swagger, Git ──────
75
80
  WITH_DOCKER=${WITH_DOCKER:-$(read -p "🐳 Activer Docker ? (y/n) : " tmp && echo "$tmp")}
76
- [ "$WITH_DOCKER" = "y" ] && bash "$FEATURES_PATH/docker.sh" "$APP_NAME"
81
+ if [ "$WITH_DOCKER" = "y" ]; then
82
+ run_step "Configuration Docker" bash "$FEATURES_PATH/docker.sh" "$APP_NAME" "$PM"
83
+ fi
77
84
 
78
85
  WITH_SWAGGER=${WITH_SWAGGER:-$(read -p "📚 Activer Swagger ? (y/n) : " tmp && echo "$tmp")}
79
- [ "$WITH_SWAGGER" = "y" ] && bash "$FEATURES_PATH/swagger.sh" "$PM"
80
-
81
- WITH_GIT=${WITH_GIT:-$(read -p "🔃 Initialiser Git ? (y/n) : " tmp && echo "$tmp")}
82
- [ "$WITH_GIT" = "y" ] && bash "$FEATURES_PATH/git.sh"
83
-
84
- # ────── Modules à générer ──────
85
- MODULES=${MODULES:-$(read -p "👤 Modules à générer (séparés par espaces) : " tmp && echo "$tmp")}
86
- for MODULE in $MODULES; do
87
- debug_log "Génération du module $MODULE"
88
- bash "$FEATURES_PATH/add_module.sh" "$MODULE" "$ORM"
89
- done
90
-
91
- # ────── Injection dans app.module.ts ──────
92
- APP_MODULE="src/app.module.ts"
93
-
94
- # CqrsModule
95
- if ! grep -q "CqrsModule" "$APP_MODULE"; then
96
- sed -i '' "1i\\
97
- import { CqrsModule } from '@nestjs/cqrs';
98
- " "$APP_MODULE"
99
- sed -i '' "s|imports: \[|imports: [CqrsModule, |" "$APP_MODULE"
100
- echo "✅ CqrsModule injecté"
86
+ if [ "$WITH_SWAGGER" = "y" ]; then
87
+ run_step "Configuration Swagger" bash "$FEATURES_PATH/swagger.sh" "$PM"
101
88
  fi
102
89
 
103
- # TypeOrmModule
104
- if [ "$ORM" = "typeorm" ]; then
105
- if ! grep -q "TypeOrmModule" "$APP_MODULE"; then
106
- sed -i '' "1i\\
107
- import { TypeOrmModule } from '@nestjs/typeorm';
108
- " "$APP_MODULE"
109
- echo "✅ Import de TypeOrmModule ajouté"
110
- fi
90
+ run_step "Configuration du bootstrap Nest" node "$FEATURES_PATH/configure_bootstrap.mjs" src/main.ts "$WITH_SWAGGER"
111
91
 
112
- if ! grep -q "TypeOrmModule.forRoot" "$APP_MODULE"; then
113
- sed -i '' -E 's/(imports: \[[^]]*)(])/\1\
114
- TypeOrmModule.forRoot({\
115
- type: '\''postgres'\'',\
116
- host: '\''localhost'\'',\
117
- port: 5432,\
118
- username: '\''postgres'\'',\
119
- password: '\''postgres'\'',\
120
- database: '\''appdb'\'',\
121
- synchronize: true,\
122
- autoLoadEntities: true,\
123
- }), \2/g' "$APP_MODULE"
124
- echo "✅ TypeOrmModule.forRoot injecté"
125
- fi
92
+ WITH_GIT=${WITH_GIT:-$(read -p "🔃 Initialiser Git ? (y/n) : " tmp && echo "$tmp")}
93
+ if [ "$WITH_GIT" = "y" ]; then
94
+ run_step "Initialisation Git" bash "$FEATURES_PATH/git.sh"
126
95
  fi
127
96
 
128
- # Modules générés
97
+ # ────── Modules à générer ──────
98
+ MODULES=${MODULES-$(read -p "👤 Modules à générer (séparés par espaces) : " tmp && echo "$tmp")}
129
99
  for MODULE in $MODULES; do
130
- debug_log "Injection de $MODULE dans app.module.ts"
131
- bash "$FEATURES_PATH/inject_module_to_app.sh" "$MODULE" "$ORM"
100
+ debug_log "Génération du module $MODULE"
101
+ run_step "Génération du module $MODULE" bash "$FEATURES_PATH/add_module.sh" "$MODULE" "$ORM"
132
102
  done
133
103
 
134
104
  # ────── Résumé final ──────
@@ -137,7 +107,7 @@ log_success "✅ Projet NestJS \"$APP_NAME\" généré avec succès 🎉"
137
107
  echo "📁 Localisation : $FULL_PATH"
138
108
  echo "📦 Package manager : $PM"
139
109
  echo "🧠 ORM : $ORM"
140
- [ "$WITH_DOCKER" = "y" ] && echo "🐳 Docker activé"
141
- [ "$WITH_SWAGGER" = "y" ] && echo "📚 Swagger activé"
142
- [ "$WITH_GIT" = "y" ] && echo "🔃 Git initialisé"
143
- [ -n "$MODULES" ] && echo "📦 Modules générés : $MODULES"
110
+ if [ "$WITH_DOCKER" = "y" ]; then echo "🐳 Docker activé"; fi
111
+ if [ "$WITH_SWAGGER" = "y" ]; then echo "📚 Swagger activé"; fi
112
+ if [ "$WITH_GIT" = "y" ]; then echo "🔃 Git initialisé"; fi
113
+ if [ -n "$MODULES" ]; then echo "📦 Modules générés : $MODULES"; fi