@artilingo/artiframe-cli 1.4.0 → 2.0.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 (38) hide show
  1. package/core-stubs/bin/SystemMethod.php +600 -521
  2. package/core-stubs/bin/ViewMethod.php +591 -393
  3. package/core-stubs/docs/de.html +4347 -4390
  4. package/core-stubs/docs/en.html +4347 -4389
  5. package/core-stubs/docs/es.html +4347 -4390
  6. package/core-stubs/docs/fr.html +4347 -4389
  7. package/core-stubs/docs/tr.html +138 -109
  8. package/package.json +1 -1
  9. package/src/App.php +8 -0
  10. package/src/Commands/AddCommand.php +1 -1
  11. package/src/Commands/ListCommand.php +2 -1
  12. package/src/Commands/MakeApiCommand.php +1 -1
  13. package/src/Commands/MakeClassCommand.php +1 -1
  14. package/src/Commands/MakeViewCommand.php +1 -1
  15. package/src/Commands/NewProjectCommand.php +37 -25
  16. package/src/Commands/RemoveCommand.php +21 -10
  17. package/src/Commands/ServeCommand.php +29 -9
  18. package/src/Commands/TableCommand.php +2 -1
  19. package/src/Commands/UpgradeCommand.php +209 -0
  20. package/src/Commands/VersionCommand.php +2 -1
  21. package/src/Lang/de.php +7 -1
  22. package/src/Lang/en.php +6 -0
  23. package/src/Lang/es.php +7 -1
  24. package/src/Lang/fr.php +6 -0
  25. package/src/Lang/tr.php +7 -1
  26. package/src/Services/Safeguard.php +25 -0
  27. package/stubs/service/image.stub +334 -334
  28. package/stubs/service/iyzico.stub +637 -637
  29. package/stubs/service/jwt.stub +312 -312
  30. package/stubs/service/phpmailer.stub +143 -143
  31. package/stubs/service/pusher.stub +232 -232
  32. package/stubs/service/qrcode.stub +169 -169
  33. package/stubs/service/redis.stub +361 -361
  34. package/stubs/service/s3.stub +377 -377
  35. package/stubs/service/sentry.stub +76 -106
  36. package/stubs/service/stripe.stub +526 -526
  37. package/stubs/service/twilio.stub +361 -361
  38. package/core-stubs/app/R2Manager.php +0 -130
@@ -1,4 +1,4 @@
1
- <?php
1
+ <?php
2
2
  namespace ArtiFrame\Cli\Commands;
3
3
 
4
4
  use ArtiFrame\Cli\Services\Translator;
@@ -24,7 +24,7 @@ class RemoveCommand
24
24
  return;
25
25
  }
26
26
 
27
- $projectRoot = getcwd();
27
+ $projectRoot = $this->safeguard->getProjectRoot();
28
28
 
29
29
  $targetPath = $target;
30
30
  if (!file_exists($targetPath)) {
@@ -52,15 +52,26 @@ class RemoveCommand
52
52
  $isClass = strpos($normalizedPath, '/src/') !== false || strpos($normalizedPath, '/app/') !== false;
53
53
 
54
54
  if ($isView) {
55
- $relPath = str_replace(str_replace('\\', '/', $projectRoot) . '/public/', '', $normalizedPath);
56
- $relPath = preg_replace('/\.php$/', '', $relPath);
57
-
58
- $cssPath = $projectRoot . '/public/assets/css/' . $relPath . '.css';
59
- $jsPath = $projectRoot . '/public/assets/js/' . $relPath . '.js';
60
-
61
55
  $assetsFound = [];
62
- if (file_exists($cssPath)) $assetsFound[] = $cssPath;
63
- if (file_exists($jsPath)) $assetsFound[] = $jsPath;
56
+ $content = file_get_contents($targetPath);
57
+
58
+ // Extract CSS path from href="/assets/css/...css"
59
+ if (preg_match('/href="(\/assets\/css\/[^"]+\.css)(?:\?[^"]*)?"/i', $content, $matches)) {
60
+ $cssRelative = ltrim($matches[1], '/');
61
+ $cssPath = rtrim($projectRoot, '/') . '/public/' . $cssRelative;
62
+ if (file_exists($cssPath)) {
63
+ $assetsFound[] = $cssPath;
64
+ }
65
+ }
66
+
67
+ // Extract JS path from src="/assets/js/...js"
68
+ if (preg_match('/src="(\/assets\/js\/[^"]+\.js)(?:\?[^"]*)?"/i', $content, $matches)) {
69
+ $jsRelative = ltrim($matches[1], '/');
70
+ $jsPath = rtrim($projectRoot, '/') . '/public/' . $jsRelative;
71
+ if (file_exists($jsPath)) {
72
+ $assetsFound[] = $jsPath;
73
+ }
74
+ }
64
75
 
65
76
  if (!empty($assetsFound)) {
66
77
  echo "\n⚠️ " . $this->translator->get('REMOVE_CONFIRM_ASSETS') . " [y/N]: ";
@@ -14,7 +14,8 @@ class ServeCommand
14
14
 
15
15
  public function execute(array $args): void
16
16
  {
17
- $projectRoot = getcwd();
17
+ $safeguard = new \ArtiFrame\Cli\Services\Safeguard($this->translator);
18
+ $projectRoot = $safeguard->getProjectRoot();
18
19
  $publicDir = $projectRoot . '/public';
19
20
 
20
21
  if (!is_dir($publicDir) || !file_exists($publicDir . '/index.php')) {
@@ -32,34 +33,53 @@ class ServeCommand
32
33
  $port = $args[0];
33
34
  }
34
35
 
35
- $url = "http://{$host}:{$port}";
36
+ // Detect Local IP
37
+ $localIp = 'Unknown';
38
+ $sock = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
39
+ if ($sock) {
40
+ @socket_connect($sock, "8.8.8.8", 53);
41
+ @socket_getsockname($sock, $localIp);
42
+ @socket_close($sock);
43
+ }
44
+ if ($localIp === 'Unknown' || $localIp === '127.0.0.1' || $localIp === '::1' || empty($localIp)) {
45
+ $localIp = getHostByName(getHostName());
46
+ }
47
+
48
+ $localUrl = "http://localhost:{$port}";
49
+ $networkUrl = "http://{$localIp}:{$port}";
36
50
 
37
51
  echo "
38
- 🚀 " . $this->translator->get('SERVE_STARTING', ['url' => $url]) . "
52
+ 🚀 " . $this->translator->get('SERVE_STARTING', ['url' => "0.0.0.0:{$port}"]) . "
39
53
  ";
40
54
  echo " " . $this->translator->get('SERVE_STOP_INFO') . "
41
55
 
42
- ";
56
+ Local: {$localUrl}";
57
+
58
+ if ($localIp && $localIp !== '127.0.0.1' && $localIp !== 'Unknown') {
59
+ echo "
60
+ Network: {$networkUrl}";
61
+ }
62
+ echo "\n\n";
43
63
 
44
64
  $os = PHP_OS_FAMILY;
45
65
 
46
- // Command to start PHP built-in server
47
- $phpCmd = sprintf('php -S %s:%s -t %s', $host, $port, escapeshellarg($publicDir));
66
+ // Command to start PHP built-in server on all interfaces (0.0.0.0)
67
+ $phpCmd = sprintf('php -S 0.0.0.0:%s -t %s', $port, escapeshellarg($publicDir));
48
68
 
49
69
  if ($os === 'Windows') {
50
70
  // Open Browser
51
- pclose(popen("start {$url}", "r"));
71
+ pclose(popen("start {$localUrl}", "r"));
52
72
  // Start Server in new visible CMD window
53
73
  pclose(popen("start \"ArtiFrame Server\" cmd /k \"{$phpCmd}\"", "r"));
54
74
  } elseif ($os === 'Darwin') {
55
75
  // Open Browser
56
- exec("open {$url} > /dev/null 2>&1 &");
76
+ exec("open {$localUrl} > /dev/null 2>&1 &");
57
77
  // Start Server in new Terminal window
58
78
  $appleScript = 'tell app "Terminal" to do script "' . escapeshellcmd($phpCmd) . '"';
59
79
  exec("osascript -e " . escapeshellarg($appleScript));
60
80
  } else {
61
81
  // Open Browser
62
- exec("xdg-open {$url} > /dev/null 2>&1 &");
82
+ exec("xdg-open {$localUrl} > /dev/null 2>&1 &");
63
83
  // Linux: Try common terminals, fallback to background process
64
84
  $linuxCmd = sprintf(
65
85
  'gnome-terminal -- bash -c "%s" || xterm -e "%s" || konsole -e "%s" || %s > /dev/null 2>&1 &',
@@ -69,7 +69,8 @@ class TableCommand
69
69
  return;
70
70
  }
71
71
 
72
- $schemaPath = getcwd() . '/schema.sql';
72
+ $safeguard = new \ArtiFrame\Cli\Services\Safeguard($this->translator);
73
+ $schemaPath = $safeguard->getProjectRoot() . '/schema.sql';
73
74
 
74
75
  if (!file_exists($schemaPath)) {
75
76
  file_put_contents($schemaPath, "-- ArtiFrame DB Schema\n-- Created: " . date('Y-m-d') . "\n");
@@ -0,0 +1,209 @@
1
+ <?php
2
+ namespace ArtiFrame\Cli\Commands;
3
+
4
+ use ArtiFrame\Cli\Services\Translator;
5
+
6
+ class UpgradeCommand
7
+ {
8
+ private Translator $translator;
9
+ private array $changes = [
10
+ 'added' => [],
11
+ 'modified' => []
12
+ ];
13
+
14
+ public function __construct(Translator $translator)
15
+ {
16
+ $this->translator = $translator;
17
+ }
18
+
19
+ public function execute(array $args): void
20
+ {
21
+ $targetDir = getcwd();
22
+
23
+ if (!file_exists($targetDir . '/composer.json') || !is_dir($targetDir . '/app') || !is_dir($targetDir . '/bin')) {
24
+ echo "❌ " . $this->translator->get('ERROR_RUN_FROM_ROOT') . PHP_EOL;
25
+ return;
26
+ }
27
+
28
+ // ── KURAL 1: INDEX.PHP KORUMASI ────────────────────────────────
29
+ $indexFile = $targetDir . '/public/index.php';
30
+ if (file_exists($indexFile)) {
31
+ $indexContent = file_get_contents($indexFile);
32
+ if (strpos($indexContent, 'routeLink(') === false) {
33
+ echo PHP_EOL . "❌ " . $this->translator->get('UPGRADE_INDEX_ABORT') . PHP_EOL;
34
+ return;
35
+ }
36
+ }
37
+
38
+ // ── KURAL 2: ÇEKİRDEK (BIN) DEĞİŞİKLİK KONTROLÜ ────────────────
39
+ $coreStubsBinDir = \ARTIFRAME_CLI_ROOT . '/core-stubs/bin';
40
+ $projectBinDir = $targetDir . '/bin';
41
+
42
+ $isCoreModified = false;
43
+ $filesToCheck = ['SystemMethod.php', 'ViewMethod.php'];
44
+
45
+ foreach ($filesToCheck as $file) {
46
+ $stubPath = $coreStubsBinDir . '/' . $file;
47
+ $projPath = $projectBinDir . '/' . $file;
48
+
49
+ if (file_exists($stubPath) && file_exists($projPath)) {
50
+ if (md5_file($stubPath) !== md5_file($projPath)) {
51
+ $isCoreModified = true;
52
+ break;
53
+ }
54
+ }
55
+ }
56
+
57
+ if ($isCoreModified) {
58
+ echo PHP_EOL . "⚠️ " . $this->translator->get('UPGRADE_CORE_WARNING') . PHP_EOL;
59
+ // The prompt asks to press Enter to continue.
60
+ $choice = trim(fgets(STDIN));
61
+ if (strtolower($choice) === 'n' || strtolower($choice) === 'h') {
62
+ echo $this->translator->get('ABORTED') . PHP_EOL;
63
+ return;
64
+ }
65
+ }
66
+
67
+ echo PHP_EOL . "🚀 " . $this->translator->get('PHASE_COPYING') . PHP_EOL;
68
+
69
+ // ── KURAL 3 & ANA İŞLEM: KOPYALAMA ──────────────────────────────
70
+ $this->copyDirectory(\ARTIFRAME_CLI_ROOT . '/core-stubs/app', $targetDir . '/app');
71
+ $this->copyDirectory(\ARTIFRAME_CLI_ROOT . '/core-stubs/bin', $targetDir . '/bin');
72
+
73
+ // Docs
74
+ $docsSource = \ARTIFRAME_CLI_ROOT . '/core-stubs/docs';
75
+ $docsTarget = $targetDir . '/public/docs';
76
+ if (is_dir($docsSource)) {
77
+ if (!is_dir($docsTarget)) {
78
+ mkdir($docsTarget, 0755, true);
79
+ }
80
+ $this->copyDirectory($docsSource, $docsTarget);
81
+ }
82
+
83
+ // ── KURAL 4: SERVICE STUB EZİLMESİ ──────────────────────────────
84
+ $servicesDir = $targetDir . '/src/Service';
85
+ $stubsServicesDir = \ARTIFRAME_CLI_ROOT . '/stubs/services';
86
+
87
+ if (is_dir($servicesDir) && is_dir($stubsServicesDir)) {
88
+ $iterator = new \DirectoryIterator($servicesDir);
89
+ foreach ($iterator as $fileinfo) {
90
+ if ($fileinfo->isFile() && $fileinfo->getExtension() === 'php') {
91
+ $filename = $fileinfo->getFilename();
92
+
93
+ $stubIterator = new \DirectoryIterator($stubsServicesDir);
94
+ foreach ($stubIterator as $stubInfo) {
95
+ if ($stubInfo->isFile() && $stubInfo->getExtension() === 'stub') {
96
+ $stubName = $stubInfo->getBasename('.stub');
97
+ $expectedServiceName = ucfirst($stubName) . 'Service.php';
98
+
99
+ if ($filename === $expectedServiceName) {
100
+ $oldContent = file_get_contents($fileinfo->getPathname());
101
+ $content = file_get_contents($stubInfo->getPathname());
102
+ if (md5($oldContent) !== md5($content)) {
103
+ $oldFunctions = $this->getFunctionsFromFile($fileinfo->getPathname());
104
+ $newFunctions = $this->getFunctionsFromFile($stubInfo->getPathname());
105
+ $addedFunctions = array_values(array_diff($newFunctions, $oldFunctions));
106
+
107
+ file_put_contents($fileinfo->getPathname(), $content);
108
+ $this->changes['modified']['src/Service/' . $filename] = [
109
+ 'added_functions' => $addedFunctions
110
+ ];
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ if (empty($this->changes['added']) && empty($this->changes['modified'])) {
120
+ echo PHP_EOL . "✅ " . $this->translator->get('UPGRADE_SUCCESS') . " (Sistem zaten güncel)" . PHP_EOL . PHP_EOL;
121
+ } else {
122
+ echo PHP_EOL . "✅ " . $this->translator->get('UPGRADE_SUCCESS') . PHP_EOL . PHP_EOL;
123
+
124
+ echo "📊 Değişiklik Raporu:" . PHP_EOL;
125
+ echo str_repeat('-', 40) . PHP_EOL;
126
+
127
+ if (!empty($this->changes['added'])) {
128
+ echo "\e[32m[EKLENDİ]\e[0m" . PHP_EOL;
129
+ foreach ($this->changes['added'] as $add) {
130
+ echo " + $add" . PHP_EOL;
131
+ }
132
+ echo PHP_EOL;
133
+ }
134
+
135
+ if (!empty($this->changes['modified'])) {
136
+ echo "\e[33m[GÜNCELLENDİ]\e[0m" . PHP_EOL;
137
+ foreach ($this->changes['modified'] as $mod => $details) {
138
+ echo " ~ $mod" . PHP_EOL;
139
+ if (!empty($details['added_functions'])) {
140
+ foreach ($details['added_functions'] as $func) {
141
+ echo " \e[36m[YENİ FONKSİYON]\e[0m $func() - Lütfen dokümantasyonu inceleyin." . PHP_EOL;
142
+ }
143
+ }
144
+ }
145
+ echo PHP_EOL;
146
+ }
147
+ }
148
+ }
149
+
150
+ private function copyDirectory(string $source, string $target): void
151
+ {
152
+ if (!is_dir($target)) {
153
+ mkdir($target, 0755, true);
154
+ }
155
+
156
+ $dir = opendir($source);
157
+ while (($file = readdir($dir)) !== false) {
158
+ if ($file === '.' || $file === '..') {
159
+ continue;
160
+ }
161
+ $srcFile = $source . '/' . $file;
162
+ $tgtFile = $target . '/' . $file;
163
+
164
+ if (is_dir($srcFile)) {
165
+ $this->copyDirectory($srcFile, $tgtFile);
166
+ } else {
167
+ $isNew = !file_exists($tgtFile);
168
+ $isModified = !$isNew && (md5_file($srcFile) !== md5_file($tgtFile));
169
+
170
+ if ($isNew || $isModified) {
171
+ $addedFunctions = [];
172
+ if ($isModified && pathinfo($srcFile, PATHINFO_EXTENSION) === 'php') {
173
+ $oldFunctions = $this->getFunctionsFromFile($tgtFile);
174
+ $newFunctions = $this->getFunctionsFromFile($srcFile);
175
+ $addedFunctions = array_values(array_diff($newFunctions, $oldFunctions));
176
+ }
177
+
178
+ copy($srcFile, $tgtFile);
179
+
180
+ $normalizedTarget = str_replace('\\', '/', $tgtFile);
181
+ $normalizedCwd = str_replace('\\', '/', getcwd()) . '/';
182
+ $relativePath = str_replace($normalizedCwd, '', $normalizedTarget);
183
+
184
+ if ($isNew) {
185
+ $this->changes['added'][] = $relativePath;
186
+ } else {
187
+ $this->changes['modified'][$relativePath] = [
188
+ 'added_functions' => $addedFunctions
189
+ ];
190
+ }
191
+ }
192
+ }
193
+ }
194
+ closedir($dir);
195
+ }
196
+
197
+ private function getFunctionsFromFile(string $filepath): array
198
+ {
199
+ if (!file_exists($filepath)) {
200
+ return [];
201
+ }
202
+ $content = file_get_contents($filepath);
203
+ $functions = [];
204
+ if (preg_match_all('/function\s+([a-zA-Z0-9_]+)\s*\(/i', $content, $matches)) {
205
+ $functions = $matches[1];
206
+ }
207
+ return $functions;
208
+ }
209
+ }
@@ -27,7 +27,8 @@ class VersionCommand
27
27
  return;
28
28
  }
29
29
 
30
- $projectRoot = getcwd();
30
+ $safeguard = new \ArtiFrame\Cli\Services\Safeguard($this->translator);
31
+ $projectRoot = $safeguard->getProjectRoot();
31
32
  $versionFile = $projectRoot . '/config/app-version.php';
32
33
 
33
34
  if (!file_exists($versionFile)) {
package/src/Lang/de.php CHANGED
@@ -59,6 +59,7 @@ return [
59
59
  // Help screen
60
60
  'HELP_COMMANDS' => 'BEFEHLE',
61
61
  'HELP_NEW_DESC' => 'Erstellt ein neues ArtiFrame-Projekt von Grund auf.',
62
+ 'HELP_UPGRADE_DESC' => 'Wendet aktualisierte CLI-Kernfunktionen (app, bin) von NPM auf Ihr Projekt an.',
62
63
  'HELP_MAKEVIEW_DESC1' => 'Erstellt eine neue View-Datei mit CSS- und JS-Assets.',
63
64
  'HELP_MAKEVIEW_DESC2' => 'Der Pfad kann Unterverzeichnisse enthalten (automatisch erstellt).',
64
65
  'HELP_MAKEAPI_DESC' => 'Erstellt eine neue API-Endpunkt-Datei.',
@@ -178,6 +179,11 @@ return [
178
179
  'TABLE_LIST_HEADER' => 'Unterstützte Tabellen:',
179
180
  'TABLE_DESC_USERS' => 'Basis-Benutzer- und Autorisierungstabelle (UUID).',
180
181
  'TABLE_DESC_USER_SESSIONS' => 'Benutzersitzungen (IP, Gerät, Token) verfolgen.',
181
- 'TABLE_DESC_USER_PREFERENCES' => 'Benutzereinstellungen (Sprache, Thema, Benachrichtigungen).',
182
+ 'TABLE_DESC_USER_PREFERENCES' => 'Benutzereinstellungen (Sprache, Design, Benachrichtigungen).',
183
+
184
+ // Upgrade
185
+ 'UPGRADE_INDEX_ABORT' => 'public/index.php Datei erkannt! In der neuen Version fungiert diese Datei als Router. Um das Upgrade fortzusetzen, benennen Sie bitte Ihre bestehende index.php in landing.php (oder einen anderen Namen) um und führen Sie den Befehl erneut aus.',
186
+ 'UPGRADE_CORE_WARNING' => 'Ihr Projektkern unterscheidet sich von der Originalversion. Wenn Sie manuell Funktionen hinzugefügt haben, sichern Sie diese bitte vor dem Upgrade, um Datenverlust zu vermeiden. Drücken Sie die Eingabetaste, um nach der Sicherung fortzufahren.',
187
+ 'UPGRADE_SUCCESS' => 'Kern (app/ und bin/) und Service-Stubs erfolgreich aktualisiert!',
182
188
 
183
189
  ];
package/src/Lang/en.php CHANGED
@@ -59,6 +59,7 @@ return [
59
59
  // Help screen
60
60
  'HELP_COMMANDS' => 'COMMANDS',
61
61
  'HELP_NEW_DESC' => 'Create a new ArtiFrame project from scratch.',
62
+ 'HELP_UPGRADE_DESC' => 'Applies updated core features (app, bin) from NPM to the current project.',
62
63
  'HELP_MAKEVIEW_DESC1' => 'Generate a new view file with its paired CSS and JS assets.',
63
64
  'HELP_MAKEVIEW_DESC2' => 'The path can use subdirectories (auto-created).',
64
65
  'HELP_MAKEAPI_DESC' => 'Generate a new API endpoint file.',
@@ -180,4 +181,9 @@ return [
180
181
  'TABLE_DESC_USER_SESSIONS' => 'User sessions (IP, device, token) tracking.',
181
182
  'TABLE_DESC_USER_PREFERENCES' => 'User preferences (language, theme, notifications).',
182
183
 
184
+ // Upgrade
185
+ 'UPGRADE_INDEX_ABORT' => 'public/index.php file detected! In the new version, this file acts as a router. To continue the upgrade, please rename your existing index.php to landing.php (or any other name) and run the command again.',
186
+ 'UPGRADE_CORE_WARNING' => 'Your project core is different from the original version. If you have manually added functions, please back them up before upgrading to prevent data loss. Press Enter to continue after backing up.',
187
+ 'UPGRADE_SUCCESS' => 'Core (app/ and bin/) and service stubs updated successfully!',
188
+
183
189
  ];
package/src/Lang/es.php CHANGED
@@ -59,6 +59,7 @@ return [
59
59
  // Help screen
60
60
  'HELP_COMMANDS' => 'COMANDOS',
61
61
  'HELP_NEW_DESC' => 'Crea un nuevo proyecto ArtiFrame desde cero.',
62
+ 'HELP_UPGRADE_DESC' => 'Aplica las características actualizadas del núcleo CLI (app, bin) desde NPM al proyecto.',
62
63
  'HELP_MAKEVIEW_DESC1' => 'Genera un nuevo archivo de vista con sus recursos CSS y JS.',
63
64
  'HELP_MAKEVIEW_DESC2' => 'La ruta puede usar subdirectorios (creados automáticamente).',
64
65
  'HELP_MAKEAPI_DESC' => 'Genera un nuevo archivo de punto de conexión API.',
@@ -178,6 +179,11 @@ return [
178
179
  'TABLE_LIST_HEADER' => 'Tablas compatibles:',
179
180
  'TABLE_DESC_USERS' => 'Tabla básica de usuarios y autorización (UUID).',
180
181
  'TABLE_DESC_USER_SESSIONS' => 'Seguimiento de sesiones de usuario (IP, dispositivo, token).',
181
- 'TABLE_DESC_USER_PREFERENCES' => 'Preferencias de usuario (idioma, tema, notificaciones).',
182
+ 'TABLE_DESC_USER_PREFERENCES' => 'Preferencias del usuario (idioma, tema, notificaciones).',
183
+
184
+ // Upgrade
185
+ 'UPGRADE_INDEX_ABORT' => '¡Archivo public/index.php detectado! En la nueva versión, este archivo actúa como un enrutador. Para continuar con la actualización, cambie el nombre de su index.php existente a landing.php (o cualquier otro nombre) y vuelva a ejecutar el comando.',
186
+ 'UPGRADE_CORE_WARNING' => 'El núcleo de su proyecto es diferente de la versión original. Si ha agregado funciones manualmente, haga una copia de seguridad antes de actualizar para evitar la pérdida de datos. Presione Entrar para continuar después de hacer la copia de seguridad.',
187
+ 'UPGRADE_SUCCESS' => '¡Núcleo (app/ y bin/) y stubs de servicio actualizados con éxito!',
182
188
 
183
189
  ];
package/src/Lang/fr.php CHANGED
@@ -59,6 +59,7 @@ return [
59
59
  // Help screen
60
60
  'HELP_COMMANDS' => 'COMMANDES',
61
61
  'HELP_NEW_DESC' => 'Crée un nouveau projet ArtiFrame de zéro.',
62
+ 'HELP_UPGRADE_DESC' => 'Applique les fonctionnalités principales mises à jour du CLI (app, bin) depuis NPM au projet.',
62
63
  'HELP_MAKEVIEW_DESC1' => 'Génère un nouveau fichier vue avec ses assets CSS et JS.',
63
64
  'HELP_MAKEVIEW_DESC2' => 'Le chemin peut utiliser des sous-répertoires (créés automatiquement).',
64
65
  'HELP_MAKEAPI_DESC' => 'Génère un nouveau fichier de point de terminaison API.',
@@ -180,4 +181,9 @@ return [
180
181
  'TABLE_DESC_USER_SESSIONS' => 'Suivi des sessions utilisateur (IP, appareil, token).',
181
182
  'TABLE_DESC_USER_PREFERENCES' => 'Préférences de l\'utilisateur (langue, thème, notifications).',
182
183
 
184
+ // Upgrade
185
+ 'UPGRADE_INDEX_ABORT' => 'Fichier public/index.php détecté ! Dans la nouvelle version, ce fichier agit comme un routeur. Pour continuer la mise à jour, veuillez renommer votre index.php existant en landing.php (ou tout autre nom) et relancez la commande.',
186
+ 'UPGRADE_CORE_WARNING' => 'Le cœur de votre projet diffère de la version originale. Si vous avez ajouté manuellement des fonctions, veuillez les sauvegarder avant la mise à jour pour éviter toute perte de données. Appuyez sur Entrée pour continuer après la sauvegarde.',
187
+ 'UPGRADE_SUCCESS' => 'Cœur (app/ et bin/) et stubs de services mis à jour avec succès !',
188
+
183
189
  ];
package/src/Lang/tr.php CHANGED
@@ -59,6 +59,7 @@ return [
59
59
  // Help screen
60
60
  'HELP_COMMANDS' => 'KOMUTLAR',
61
61
  'HELP_NEW_DESC' => 'Sıfırdan yeni bir ArtiFrame projesi oluşturur.',
62
+ 'HELP_UPGRADE_DESC' => 'NPM üzerinden güncellenen çekirdek özellikleri (app, bin) mevcut projeye uygular.',
62
63
  'HELP_MAKEVIEW_DESC1' => 'CSS ve JS varlıklarıyla birlikte yeni bir view dosyası oluşturur.',
63
64
  'HELP_MAKEVIEW_DESC2' => 'Yol alt dizinleri içerebilir (otomatik oluşturulur).',
64
65
  'HELP_MAKEAPI_DESC' => 'Yeni bir API endpoint dosyası oluşturur.',
@@ -158,7 +159,7 @@ return [
158
159
  'SERVE_NOT_PROJECT' => 'Bu dizin geçerli bir ArtiFrame projesi değil (public/index.php bulunamadı).',
159
160
  'SERVE_STARTING' => 'Geliştirme sunucusu başlatılıyor: :url',
160
161
  'SERVE_STOP_INFO' => 'Durdurmak için CTRL+C tuşlarına basın.',
161
- 'HELP_SERVE_DESC' => 'Lokal geliştirme sunucusunu başlatır.',
162
+ 'HELP_SERVE_DESC' => 'Geliştirme sunucusunu başlatır ve yerel ağa açar.',
162
163
 
163
164
  'INVALID_PACKAGE_NAME' => 'Geçersiz paket adı. Format şuna benzemeli: vendor/project',
164
165
 
@@ -180,4 +181,9 @@ return [
180
181
  'TABLE_DESC_USER_SESSIONS' => 'Kullanıcı oturumları (IP, cihaz, token) takibi.',
181
182
  'TABLE_DESC_USER_PREFERENCES' => 'Kullanıcı tercihleri (dil, tema, bildirimler).',
182
183
 
184
+ // Upgrade
185
+ 'UPGRADE_INDEX_ABORT' => 'public/index.php dosyası tespit edildi! Yeni sürümde bu dosya artık bir router\'dır. Güncellemeye devam edebilmek için lütfen mevcut index.php\'nizin adını landing.php (veya istediğiniz başka bir isim) olarak değiştirin ve komutu tekrar çalıştırın.',
186
+ 'UPGRADE_CORE_WARNING' => 'Proje çekirdeğiniz orijinal sürümden farklı. Manuel olarak eklediğiniz fonksiyonlar varsa kayba uğramamak için güncellemeden önce lütfen kopyalarını alın. Kopyalarını aldıktan sonra Enter tuşuna basarak devam edebilirsiniz.',
187
+ 'UPGRADE_SUCCESS' => 'Çekirdek (app/ ve bin/) ile servis şablonları başarıyla güncellendi!',
188
+
183
189
  ];
@@ -45,4 +45,29 @@ class Safeguard
45
45
 
46
46
  return true;
47
47
  }
48
+
49
+ /**
50
+ * Attempts to find the project root by recursively looking up for composer.json or app/public dirs.
51
+ */
52
+ public function getProjectRoot(): string
53
+ {
54
+ $dir = rtrim(str_replace('\\', '/', getcwd()), '/');
55
+ $current = $dir;
56
+
57
+ while (true) {
58
+ if (file_exists($current . '/composer.json') || (is_dir($current . '/app') && is_dir($current . '/public'))) {
59
+ return $current;
60
+ }
61
+
62
+ $parent = dirname($current);
63
+ if ($parent === $current || $parent === '.' || $parent === '') {
64
+ // Reached the filesystem root without finding project root
65
+ break;
66
+ }
67
+ $current = $parent;
68
+ }
69
+
70
+ // Fallback to getcwd() if we couldn't detect the root
71
+ return $dir;
72
+ }
48
73
  }