@artilingo/artiframe-cli 1.0.8 → 1.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.
Files changed (40) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +1 -1
  3. package/bin/artiframe.php +1 -1
  4. package/core-stubs/app/Database.php +1 -1
  5. package/core-stubs/app/DotEnv.php +1 -1
  6. package/core-stubs/app/R2Manager.php +1 -1
  7. package/core-stubs/bin/SystemMethod.php +292 -16
  8. package/core-stubs/bin/ViewMethod.php +146 -37
  9. package/core-stubs/docs/de.html +4419 -951
  10. package/core-stubs/docs/en.html +4419 -952
  11. package/core-stubs/docs/es.html +4419 -947
  12. package/core-stubs/docs/fr.html +4102 -533
  13. package/core-stubs/docs/tr.html +4978 -951
  14. package/core-stubs/stubs/service/image.stub +334 -0
  15. package/core-stubs/stubs/service/iyzico.stub +637 -0
  16. package/core-stubs/stubs/service/jwt.stub +312 -0
  17. package/core-stubs/stubs/service/pusher.stub +232 -0
  18. package/core-stubs/stubs/service/redis.stub +361 -0
  19. package/core-stubs/stubs/service/s3.stub +377 -0
  20. package/core-stubs/stubs/service/sentry.stub +139 -0
  21. package/core-stubs/stubs/service/stripe.stub +526 -0
  22. package/core-stubs/stubs/service/twilio.stub +361 -0
  23. package/package.json +4 -4
  24. package/src/App.php +70 -1
  25. package/src/Commands/AddCommand.php +392 -0
  26. package/src/Commands/GoCommand.php +48 -0
  27. package/src/Commands/ListCommand.php +67 -0
  28. package/src/Commands/MakeApiCommand.php +4 -4
  29. package/src/Commands/MakeClassCommand.php +8 -8
  30. package/src/Commands/MakeViewCommand.php +3 -3
  31. package/src/Commands/NewProjectCommand.php +187 -33
  32. package/src/Commands/RemoveCommand.php +121 -0
  33. package/src/Commands/ServeCommand.php +71 -0
  34. package/src/Commands/ShowCommand.php +24 -0
  35. package/src/Commands/VersionCommand.php +4 -4
  36. package/src/Lang/de.php +56 -0
  37. package/src/Lang/en.php +56 -0
  38. package/src/Lang/es.php +56 -0
  39. package/src/Lang/fr.php +56 -0
  40. package/src/Lang/tr.php +56 -0
@@ -0,0 +1,392 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class AddCommand
7
+ {
8
+ private Translator $translator;
9
+
10
+ /**
11
+ * ArtiFrame'in desteklediği paket kayıt defteri.
12
+ *
13
+ * 'composer' => Composer paket adı
14
+ * 'type' => 'integrated' | 'direct'
15
+ * 'service' => Oluşturulacak sınıf dosyası yolu (integrated için)
16
+ * 'stub' => Stub dosya adı (integrated için)
17
+ * 'env' => .env dosyasına eklenecek satırlar (integrated için)
18
+ */
19
+ private array $registry = [
20
+ // ── Entegrasyonlu Paketler (Composer + Servis Sınıfı + .env) ───
21
+ 'iyzico' => [
22
+ 'composer' => 'iyzipay/iyzipay-php',
23
+ 'type' => 'integrated',
24
+ 'service' => 'src/Service/Iyzico.php',
25
+ 'stub' => 'iyzico.stub',
26
+ 'env' => [
27
+ '# ── iyzico ──────────────────────',
28
+ 'IYZICO_API_KEY=',
29
+ 'IYZICO_SECRET_KEY=',
30
+ 'IYZICO_BASE_URL=https://sandbox-api.iyzipay.com',
31
+ ],
32
+ ],
33
+ 'stripe' => [
34
+ 'composer' => 'stripe/stripe-php',
35
+ 'type' => 'integrated',
36
+ 'service' => 'src/Service/Stripe.php',
37
+ 'stub' => 'stripe.stub',
38
+ 'env' => [
39
+ '# ── stripe ──────────────────────',
40
+ 'STRIPE_SECRET_KEY=',
41
+ 'STRIPE_PUBLISHABLE_KEY=',
42
+ 'STRIPE_WEBHOOK_SECRET=',
43
+ ],
44
+ ],
45
+ 'jwt' => [
46
+ 'composer' => 'firebase/php-jwt',
47
+ 'type' => 'integrated',
48
+ 'service' => 'src/Auth/JwtAuth.php',
49
+ 'stub' => 'jwt.stub',
50
+ 'env' => [
51
+ '# ── jwt ─────────────────────────',
52
+ 'JWT_SECRET_KEY=',
53
+ 'JWT_ALGORITHM=HS256',
54
+ 'JWT_EXPIRY=3600',
55
+ ],
56
+ ],
57
+ 'image' => [
58
+ 'composer' => 'intervention/image',
59
+ 'type' => 'integrated',
60
+ 'service' => 'src/Service/ImageProcessor.php',
61
+ 'stub' => 'image.stub',
62
+ 'env' => [
63
+ '# ── image ───────────────────────',
64
+ 'IMAGE_DRIVER=gd',
65
+ 'IMAGE_QUALITY=80',
66
+ ],
67
+ ],
68
+ 's3' => [
69
+ 'composer' => 'aws/aws-sdk-php',
70
+ 'type' => 'integrated',
71
+ 'service' => 'src/Service/S3Storage.php',
72
+ 'stub' => 's3.stub',
73
+ 'env' => [
74
+ '# ── aws s3 ──────────────────────',
75
+ 'AWS_ACCESS_KEY_ID=',
76
+ 'AWS_SECRET_ACCESS_KEY=',
77
+ 'AWS_DEFAULT_REGION=eu-central-1',
78
+ 'AWS_BUCKET=',
79
+ 'AWS_ENDPOINT=',
80
+ ],
81
+ ],
82
+ 'sentry' => [
83
+ 'composer' => 'sentry/sentry',
84
+ 'type' => 'integrated',
85
+ 'service' => 'config/sentry.php',
86
+ 'stub' => 'sentry.stub',
87
+ 'env' => [
88
+ '# ── sentry ──────────────────────',
89
+ 'SENTRY_DSN=',
90
+ ],
91
+ ],
92
+ 'redis' => [
93
+ 'composer' => 'predis/predis',
94
+ 'type' => 'integrated',
95
+ 'service' => 'src/Service/RedisCache.php',
96
+ 'stub' => 'redis.stub',
97
+ 'env' => [
98
+ '# ── redis ───────────────────────',
99
+ 'REDIS_HOST=127.0.0.1',
100
+ 'REDIS_PORT=6379',
101
+ 'REDIS_PASSWORD=',
102
+ 'REDIS_DATABASE=0',
103
+ ],
104
+ ],
105
+ 'pusher' => [
106
+ 'composer' => 'pusher/pusher-php-server',
107
+ 'type' => 'integrated',
108
+ 'service' => 'src/Service/Pusher.php',
109
+ 'stub' => 'pusher.stub',
110
+ 'env' => [
111
+ '# ── pusher ──────────────────────',
112
+ 'PUSHER_APP_ID=',
113
+ 'PUSHER_APP_KEY=',
114
+ 'PUSHER_APP_SECRET=',
115
+ 'PUSHER_CLUSTER=eu',
116
+ ],
117
+ ],
118
+ 'twilio' => [
119
+ 'composer' => 'twilio/sdk',
120
+ 'type' => 'integrated',
121
+ 'service' => 'src/Service/Twilio.php',
122
+ 'stub' => 'twilio.stub',
123
+ 'env' => [
124
+ '# ── twilio ──────────────────────',
125
+ 'TWILIO_SID=',
126
+ 'TWILIO_AUTH_TOKEN=',
127
+ 'TWILIO_FROM_NUMBER=',
128
+ ],
129
+ ],
130
+
131
+ // ── Direkt Kullanılabilir Paketler (Sadece Composer) ───────────
132
+ 'phpmailer' => [
133
+ 'composer' => 'phpmailer/phpmailer',
134
+ 'type' => 'direct',
135
+ ],
136
+ 'mpdf' => [
137
+ 'composer' => 'mpdf/mpdf',
138
+ 'type' => 'direct',
139
+ ],
140
+ 'dompdf' => [
141
+ 'composer' => 'dompdf/dompdf',
142
+ 'type' => 'direct',
143
+ ],
144
+ 'spreadsheet' => [
145
+ 'composer' => 'phpoffice/phpspreadsheet',
146
+ 'type' => 'direct',
147
+ ],
148
+ 'qrcode' => [
149
+ 'composer' => 'endroid/qr-code',
150
+ 'type' => 'direct',
151
+ ],
152
+ 'guzzle' => [
153
+ 'composer' => 'guzzlehttp/guzzle',
154
+ 'type' => 'direct',
155
+ ],
156
+ 'uuid' => [
157
+ 'composer' => 'ramsey/uuid',
158
+ 'type' => 'direct',
159
+ ],
160
+ 'carbon' => [
161
+ 'composer' => 'nesbot/carbon',
162
+ 'type' => 'direct',
163
+ ],
164
+ 'monolog' => [
165
+ 'composer' => 'monolog/monolog',
166
+ 'type' => 'direct',
167
+ ],
168
+ ];
169
+
170
+ public function __construct(Translator $translator)
171
+ {
172
+ $this->translator = $translator;
173
+ }
174
+
175
+ public function execute(array $args): void
176
+ {
177
+ $packageAlias = strtolower($args[0] ?? '');
178
+
179
+ // ── Parametre kontrolü ───────────────────────────────────
180
+ if ($packageAlias === '') {
181
+ echo PHP_EOL;
182
+ echo " ❌ " . $this->translator->get('ADD_MISSING_NAME') . PHP_EOL;
183
+ echo PHP_EOL;
184
+ $this->showAvailablePackages();
185
+ return;
186
+ }
187
+
188
+ // ── "list" alt komutu ────────────────────────────────────
189
+ if ($packageAlias === 'list') {
190
+ $this->showAvailablePackages();
191
+ return;
192
+ }
193
+
194
+ // ── Kayıt defterinde ara ─────────────────────────────────
195
+ if (!isset($this->registry[$packageAlias])) {
196
+ echo PHP_EOL;
197
+ echo " ❌ " . $this->translator->get('ADD_NOT_FOUND', ['name' => $packageAlias]) . PHP_EOL;
198
+ echo PHP_EOL;
199
+ $this->showAvailablePackages();
200
+ return;
201
+ }
202
+
203
+ $package = $this->registry[$packageAlias];
204
+ $composerName = $package['composer'];
205
+
206
+ // ── Composer kontrolü ────────────────────────────────────
207
+ if (!$this->isComposerInstalled()) {
208
+ echo PHP_EOL;
209
+ echo " ❌ " . $this->translator->get('COMPOSER_MISSING_TITLE') . PHP_EOL;
210
+ return;
211
+ }
212
+
213
+ // ── composer.json kontrolü ───────────────────────────────
214
+ $projectRoot = getcwd();
215
+ if (!file_exists($projectRoot . '/composer.json')) {
216
+ echo PHP_EOL;
217
+ echo " ❌ " . $this->translator->get('ADD_NO_PROJECT') . PHP_EOL;
218
+ return;
219
+ }
220
+
221
+ // ── Zaten kurulu mu? ─────────────────────────────────────
222
+ if ($this->isAlreadyInstalled($projectRoot, $composerName)) {
223
+ echo PHP_EOL;
224
+ echo " ⚠️ " . $this->translator->get('ADD_ALREADY', ['name' => $packageAlias]) . PHP_EOL;
225
+ return;
226
+ }
227
+
228
+ // ── Kurulum başlasın ─────────────────────────────────────
229
+ echo PHP_EOL;
230
+ echo " 📦 " . $this->translator->get('ADD_INSTALLING', ['name' => $packageAlias, 'composer' => $composerName]) . PHP_EOL;
231
+ echo PHP_EOL;
232
+
233
+ $command = 'composer require ' . escapeshellarg($composerName);
234
+ $exitCode = 0;
235
+ passthru($command, $exitCode);
236
+
237
+ if ($exitCode !== 0) {
238
+ echo PHP_EOL;
239
+ echo " ❌ " . $this->translator->get('ADD_FAILED', ['name' => $packageAlias]) . PHP_EOL;
240
+ return;
241
+ }
242
+
243
+ // ── Entegrasyonlu paket ise ek işlemler ──────────────────
244
+ if ($package['type'] === 'integrated') {
245
+ $this->copyServiceStub($projectRoot, $package, $packageAlias);
246
+ $this->appendEnvVariables($projectRoot, $package, $packageAlias);
247
+ }
248
+
249
+ // ── Başarılı ─────────────────────────────────────────────
250
+ echo PHP_EOL;
251
+ echo " ╔══════════════════════════════════════════════════╗" . PHP_EOL;
252
+ echo " ║ ✅ " . $this->translator->get('ADD_SUCCESS', ['name' => $packageAlias, 'composer' => $composerName]) . PHP_EOL;
253
+ echo " ╚══════════════════════════════════════════════════╝" . PHP_EOL;
254
+
255
+ if ($package['type'] === 'integrated') {
256
+ echo PHP_EOL;
257
+ echo " 📄 " . $this->translator->get('ADD_SERVICE_CREATED', ['path' => $package['service']]) . PHP_EOL;
258
+ echo " 🔑 " . $this->translator->get('ADD_ENV_UPDATED') . PHP_EOL;
259
+ echo " ⚙️ " . $this->translator->get('ADD_EDIT_ENV') . PHP_EOL;
260
+ }
261
+
262
+ echo PHP_EOL;
263
+ }
264
+
265
+ // ─── Servis Sınıfı Kopyalama ─────────────────────────────────
266
+
267
+ /**
268
+ * CLI'daki stub dosyasını projenin içine kopyalar.
269
+ */
270
+ private function copyServiceStub(string $projectRoot, array $package, string $alias): void
271
+ {
272
+ $stubPath = \ARTIFRAME_CLI_ROOT . '/core-stubs/stubs/service/' . $package['stub'];
273
+ $targetPath = $projectRoot . '/' . $package['service'];
274
+
275
+ if (!file_exists($stubPath)) {
276
+ echo " ⚠️ " . $this->translator->get('ADD_STUB_MISSING', ['name' => $alias]) . PHP_EOL;
277
+ return;
278
+ }
279
+
280
+ // Hedef dizini oluştur
281
+ $targetDir = dirname($targetPath);
282
+ if (!is_dir($targetDir)) {
283
+ mkdir($targetDir, 0755, true);
284
+ }
285
+
286
+ // Zaten varsa üzerine yazma
287
+ if (file_exists($targetPath)) {
288
+ echo " ⚠️ " . $this->translator->get('ADD_SERVICE_EXISTS', ['path' => $package['service']]) . PHP_EOL;
289
+ return;
290
+ }
291
+
292
+ copy($stubPath, $targetPath);
293
+ }
294
+
295
+ // ─── .env Değişkenleri Ekleme ────────────────────────────────
296
+
297
+ /**
298
+ * .env ve .env.example dosyalarına gerekli anahtarları ekler.
299
+ */
300
+ private function appendEnvVariables(string $projectRoot, array $package, string $alias): void
301
+ {
302
+ if (empty($package['env'])) {
303
+ return;
304
+ }
305
+
306
+ $envBlock = PHP_EOL . implode(PHP_EOL, $package['env']) . PHP_EOL;
307
+
308
+ // .env dosyasına ekle
309
+ $envFile = $projectRoot . '/.env';
310
+ if (file_exists($envFile)) {
311
+ // Zaten eklenmişse tekrar ekleme
312
+ $currentContent = file_get_contents($envFile);
313
+ if (str_contains($currentContent, $package['env'][0])) {
314
+ return; // Başlık satırı zaten var, atla
315
+ }
316
+ file_put_contents($envFile, $envBlock, FILE_APPEND);
317
+ }
318
+
319
+ // .env.example dosyasına ekle
320
+ $envExample = $projectRoot . '/.env.example';
321
+ if (file_exists($envExample)) {
322
+ $currentContent = file_get_contents($envExample);
323
+ if (!str_contains($currentContent, $package['env'][0])) {
324
+ file_put_contents($envExample, $envBlock, FILE_APPEND);
325
+ }
326
+ }
327
+ }
328
+
329
+ // ─── Yardımcı Metodlar ───────────────────────────────────────
330
+
331
+ /**
332
+ * Paketin zaten kurulu olup olmadığını kontrol eder.
333
+ */
334
+ private function isAlreadyInstalled(string $projectRoot, string $composerName): bool
335
+ {
336
+ $lockFile = $projectRoot . '/composer.lock';
337
+ if (!file_exists($lockFile)) {
338
+ return false;
339
+ }
340
+ $lockContent = file_get_contents($lockFile);
341
+ return str_contains($lockContent, '"' . $composerName . '"');
342
+ }
343
+
344
+ /**
345
+ * Kayıtlı tüm paketleri kategorili bir şekilde listeler.
346
+ */
347
+ private function showAvailablePackages(): void
348
+ {
349
+ $g = "\033[38;2;0;157;108m"; // green
350
+ $y = "\033[38;5;220m"; // yellow
351
+ $d = "\033[38;2;100;100;100m"; // dim
352
+ $c = "\033[38;5;81m"; // cyan
353
+ $w = "\033[1;37m"; // white bold
354
+ $r = "\033[0m"; // reset
355
+
356
+ echo PHP_EOL;
357
+ echo " " . $w . $this->translator->get('ADD_LIST_TITLE') . $r . PHP_EOL;
358
+ echo " " . $d . "─────────────────────────────────────────────────────────────" . $r . PHP_EOL;
359
+ echo PHP_EOL;
360
+
361
+ // Entegrasyonlu Paketler
362
+ echo " " . $y . "⚡ " . $this->translator->get('ADD_CAT_INTEGRATED') . $r . PHP_EOL;
363
+ echo PHP_EOL;
364
+
365
+ foreach ($this->registry as $alias => $info) {
366
+ if ($info['type'] === 'integrated') {
367
+ $service = $info['service'] ?? '';
368
+ echo " " . $g . " add " . $alias . $r . $d . str_repeat(' ', max(1, 16 - strlen($alias))) . $info['composer'] . " → " . $service . $r . PHP_EOL;
369
+ }
370
+ }
371
+
372
+ echo PHP_EOL;
373
+
374
+ // Direkt Paketler
375
+ echo " " . $c . "📦 " . $this->translator->get('ADD_CAT_DIRECT') . $r . PHP_EOL;
376
+ echo PHP_EOL;
377
+
378
+ foreach ($this->registry as $alias => $info) {
379
+ if ($info['type'] === 'direct') {
380
+ echo " " . $g . " add " . $alias . $r . $d . str_repeat(' ', max(1, 16 - strlen($alias))) . $info['composer'] . $r . PHP_EOL;
381
+ }
382
+ }
383
+
384
+ echo PHP_EOL;
385
+ }
386
+
387
+ private function isComposerInstalled(): bool
388
+ {
389
+ $check = shell_exec('composer --version 2>&1');
390
+ return $check !== null && str_contains($check, 'Composer');
391
+ }
392
+ }
@@ -0,0 +1,48 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class GoCommand
7
+ {
8
+ private Translator $translator;
9
+
10
+ public function __construct(Translator $translator)
11
+ {
12
+ $this->translator = $translator;
13
+ }
14
+
15
+ public function execute(array $args): void
16
+ {
17
+ $target = $args[0] ?? null;
18
+
19
+ if (!$target) {
20
+ echo "
21
+ ❌ " . $this->translator->get('GO_MISSING_DIR') . "
22
+
23
+ ";
24
+ return;
25
+ }
26
+
27
+ if ($target === 'back') {
28
+ $target = '..';
29
+ }
30
+
31
+ if (!is_dir($target)) {
32
+ $notFound = str_replace(':dir', $target, $this->translator->get('GO_NOT_FOUND'));
33
+ echo "
34
+ ❌ " . $notFound . "
35
+
36
+ ";
37
+ return;
38
+ }
39
+
40
+ chdir($target);
41
+ echo "
42
+ ✅ " . $this->translator->get('GO_SUCCESS') . "
43
+ ";
44
+ echo " " . getcwd() . "
45
+
46
+ ";
47
+ }
48
+ }
@@ -0,0 +1,67 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class ListCommand
7
+ {
8
+ private Translator $translator;
9
+
10
+ public function __construct(Translator $translator)
11
+ {
12
+ $this->translator = $translator;
13
+ }
14
+
15
+ public function execute(array $args): void
16
+ {
17
+ $dir = getcwd();
18
+ $projectName = basename($dir);
19
+
20
+ echo "
21
+ 📂 " . $projectName . "/
22
+ ";
23
+
24
+ $priorityOrder = [
25
+ 'bin', 'config', 'src', 'app', 'public', '.agents',
26
+ 'vendor', '.env', '.env.example', '.gitignore',
27
+ 'composer.json', 'composer.lock', 'schema.sql',
28
+ 'README.md', 'OKUBENI.md', 'LESEMICH.md', 'LISEZMOI.md', 'LEAME.md',
29
+ 'kilavuz.html', 'guide.html', 'handbuch.html', 'guide_fr.html', 'guia.html', 'LICENSE',
30
+ ];
31
+
32
+ $entries = array_filter(scandir($dir), fn($e) => $e !== '.' && $e !== '..');
33
+
34
+ usort($entries, function ($a, $b) use ($priorityOrder) {
35
+ $ia = array_search($a, $priorityOrder);
36
+ $ib = array_search($b, $priorityOrder);
37
+ $ia = ($ia === false) ? 99 : $ia;
38
+ $ib = ($ib === false) ? 99 : $ib;
39
+ return $ia <=> $ib;
40
+ });
41
+
42
+ $entries = array_values($entries);
43
+ $total = count($entries);
44
+
45
+ foreach ($entries as $i => $entry) {
46
+ $isLast = ($i === $total - 1);
47
+ $connector = $isLast ? '└──' : '├──';
48
+ $fullPath = $dir . DIRECTORY_SEPARATOR . $entry;
49
+
50
+ if (is_dir($fullPath)) {
51
+ $subItems = array_filter(scandir($fullPath), fn($e) => $e !== '.' && $e !== '..');
52
+ $subCount = count($subItems);
53
+ $countStr = $subCount > 0 ? ' ' . $this->translator->get('DIR_ITEM_COUNT', ['count' => $subCount]) : '';
54
+ echo " │ {$connector} 📂 {$entry}/{$countStr}
55
+ ";
56
+ } else {
57
+ $size = filesize($fullPath);
58
+ $sizeStr = $size > 1024 ? round($size / 1024, 1) . ' KB' : $size . ' B';
59
+ echo " │ {$connector} 📄 {$entry} [{$sizeStr}]
60
+ ";
61
+ }
62
+ }
63
+ echo " │
64
+
65
+ ";
66
+ }
67
+ }
@@ -22,12 +22,12 @@ class MakeApiCommand
22
22
 
23
23
  if (!$type || !in_array($type, ['standart', 'switch-case'])) {
24
24
  echo "❌ " . $this->translator->get('ERROR_API_TYPE') . PHP_EOL;
25
- exit(1);
25
+ return;
26
26
  }
27
27
 
28
28
  if (!$target) {
29
29
  echo "❌ " . $this->translator->get('ERROR_API_PATH_REQUIRED') . PHP_EOL;
30
- exit(1);
30
+ return;
31
31
  }
32
32
 
33
33
  // Normalize path
@@ -42,7 +42,7 @@ class MakeApiCommand
42
42
  $apiPath = $projectRoot . '/public/api/' . $type . '/' . $target;
43
43
 
44
44
  if (!$this->safeguard->checkTarget($apiPath)) {
45
- exit(1);
45
+ return;
46
46
  }
47
47
 
48
48
  $stubName = 'api-' . $type . '.stub';
@@ -50,7 +50,7 @@ class MakeApiCommand
50
50
 
51
51
  if (!file_exists($stubPath)) {
52
52
  echo "❌ " . $this->translator->get('ERROR_STUB_NOT_FOUND', ['path' => $stubPath]) . PHP_EOL;
53
- exit(1);
53
+ return;
54
54
  }
55
55
 
56
56
  // Generate File
@@ -22,17 +22,13 @@ class MakeClassCommand
22
22
  if (!$target || strpos($target, '/') === false && strpos($target, '\\') === false) {
23
23
  echo "❌ " . $this->translator->get('DIR_REQUIRED_ERROR') . PHP_EOL;
24
24
  echo "Example: /src/Service/PaymentService" . PHP_EOL;
25
- exit(1);
25
+ return;
26
26
  }
27
27
 
28
28
  // Normalize path
29
29
  $target = ltrim(str_replace('\\', '/', $target), '/');
30
30
 
31
- // Allowed roots
32
- if (!str_starts_with($target, 'app/') && !str_starts_with($target, 'src/')) {
33
- echo "❌ " . $this->translator->get('ERROR_CLASS_ROOT') . PHP_EOL;
34
- exit(1);
35
- }
31
+ $isCustomRoot = !str_starts_with($target, 'app/') && !str_starts_with($target, 'src/');
36
32
 
37
33
  // Ensure .php extension
38
34
  if (!str_ends_with($target, '.php')) {
@@ -43,13 +39,13 @@ class MakeClassCommand
43
39
  $classPath = $projectRoot . '/' . $target;
44
40
 
45
41
  if (!$this->safeguard->checkTarget($classPath)) {
46
- exit(1);
42
+ return;
47
43
  }
48
44
 
49
45
  $stubPath = $projectRoot . '/bin/stubs/class.stub';
50
46
  if (!file_exists($stubPath)) {
51
47
  echo "❌ " . $this->translator->get('ERROR_STUB_NOT_FOUND', ['path' => $stubPath]) . PHP_EOL;
52
- exit(1);
48
+ return;
53
49
  }
54
50
 
55
51
  // Determine Namespace and Class Name
@@ -77,6 +73,10 @@ class MakeClassCommand
77
73
 
78
74
  echo $this->translator->get('SUCCESS_CLASS', ['path' => $target]) . PHP_EOL;
79
75
  echo $this->translator->get('NAMESPACE_LABEL') . ' ' . $namespace . PHP_EOL;
76
+
77
+ if ($isCustomRoot) {
78
+ shell_exec('composer dump-autoload -q');
79
+ }
80
80
  }
81
81
 
82
82
  private function ensureDirectoryExists(string $path): void
@@ -21,7 +21,7 @@ class MakeViewCommand
21
21
 
22
22
  if (!$target) {
23
23
  echo "❌ " . $this->translator->get('ERROR_VIEW_PATH_REQUIRED') . PHP_EOL;
24
- exit(1);
24
+ return;
25
25
  }
26
26
 
27
27
  // Normalize path
@@ -36,7 +36,7 @@ class MakeViewCommand
36
36
  $viewPath = $projectRoot . '/public/' . $target;
37
37
 
38
38
  if (!$this->safeguard->checkTarget($viewPath)) {
39
- exit(1);
39
+ return;
40
40
  }
41
41
 
42
42
  // Determine hierarchy for assets
@@ -57,7 +57,7 @@ class MakeViewCommand
57
57
  if (!file_exists($stubPath)) {
58
58
  echo "❌ " . $this->translator->get('ERROR_STUB_NOT_FOUND', ['path' => $stubPath]) . PHP_EOL;
59
59
  echo $this->translator->get('ERROR_RUN_FROM_ROOT') . PHP_EOL;
60
- exit(1);
60
+ return;
61
61
  }
62
62
 
63
63
  // Generate Files