@artilingo/artiframe-cli 1.0.3 → 1.0.4

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 (2) hide show
  1. package/bin/artiframe.js +248 -39
  2. package/package.json +1 -1
package/bin/artiframe.js CHANGED
@@ -3,55 +3,264 @@
3
3
  /**
4
4
  * ArtiFrame CLI — Node.js wrapper
5
5
  *
6
- * This file is the npm entry point. It checks that PHP is installed
7
- * on the system, then delegates execution to the PHP CLI bootstrap.
6
+ * Handles:
7
+ * 1. PHP 8.1+ availability check
8
+ * 2. --version / -v flag: shows current + latest version, optional self-update
9
+ * 3. Delegates all other args to the PHP bootstrap
8
10
  */
9
11
 
10
- const { execFileSync, spawnSync } = require('child_process');
11
- const path = require('path');
12
- const fs = require('fs');
12
+ const { spawnSync } = require('child_process');
13
+ const path = require('path');
14
+ const fs = require('fs');
15
+ const https = require('https');
16
+ const readline = require('readline');
13
17
 
14
- // ── 1. Verify PHP is available ──────────────────────────────────
15
- function findPhp() {
16
- const candidates = ['php', 'php8', 'php81', 'php82', 'php83', 'php84'];
17
- for (const bin of candidates) {
18
- const result = spawnSync(bin, ['--version'], { encoding: 'utf8', shell: true });
19
- if (result.status === 0) return bin;
18
+ const PACKAGE_NAME = '@artilingo/artiframe-cli';
19
+ const PKG = require(path.join(__dirname, '..', 'package.json'));
20
+ const CURRENT_VERSION = PKG.version;
21
+
22
+ // ── ANSI colour helpers ─────────────────────────────────────────
23
+ const G = '\x1b[38;2;0;157;108m'; // ArtiFrame green
24
+ const W = '\x1b[1;37m'; // white bold
25
+ const D = '\x1b[38;2;100;100;100m'; // dim gray
26
+ const Y = '\x1b[38;5;220m'; // yellow
27
+ const R = '\x1b[0m'; // reset
28
+
29
+ // ── Language detection (mirrors PHP App.php logic) ──────────────
30
+ function getLanguage() {
31
+ for (const arg of process.argv.slice(2)) {
32
+ if (arg.startsWith('--lang=')) {
33
+ const code = arg.slice(7, 9).toLowerCase();
34
+ if (['tr', 'en', 'de', 'fr', 'es'].includes(code)) return code;
35
+ }
20
36
  }
21
- return null;
37
+ const home = process.env.HOME || process.env.USERPROFILE;
38
+ const configFile = home ? path.join(home, '.artiframe_lang') : null;
39
+ if (configFile && fs.existsSync(configFile)) {
40
+ const lang = fs.readFileSync(configFile, 'utf8').trim();
41
+ if (['tr', 'en', 'de', 'fr', 'es'].includes(lang)) return lang;
42
+ }
43
+ return 'en';
22
44
  }
23
45
 
24
- const php = findPhp();
46
+ // ── Inline translations for the version/update screen ───────────
47
+ const MESSAGES = {
48
+ tr: {
49
+ currentVersion : 'Mevcut sürüm ',
50
+ latestVersion : 'Son sürüm ',
51
+ checking : 'Güncelleme kontrol ediliyor...',
52
+ upToDate : '✅ Güncel — Yeni sürüm bulunmuyor.',
53
+ updateAvail : '🔔 Güncelleme mevcut!',
54
+ updatePrompt : 'Şimdi güncellemek ister misiniz? [e/H]: ',
55
+ yesKeys : ['e', 'y'],
56
+ updating : '📦 Güncelleniyor...',
57
+ updateSuccess : '✅ Güncelleme tamamlandı! Terminali yeniden başlatın.',
58
+ updateCancelled: 'Güncelleme iptal edildi.',
59
+ updateFailed : '❌ Güncelleme başarısız oldu.',
60
+ networkError : '⚠️ Sürüm kontrolü yapılamadı (ağ hatası).',
61
+ },
62
+ en: {
63
+ currentVersion : 'Current version',
64
+ latestVersion : 'Latest version ',
65
+ checking : 'Checking for updates...',
66
+ upToDate : '✅ Up to date — No new version available.',
67
+ updateAvail : '🔔 Update available!',
68
+ updatePrompt : 'Would you like to update now? [y/N]: ',
69
+ yesKeys : ['y'],
70
+ updating : '📦 Updating...',
71
+ updateSuccess : '✅ Update complete! Please restart your terminal.',
72
+ updateCancelled: 'Update cancelled.',
73
+ updateFailed : '❌ Update failed.',
74
+ networkError : '⚠️ Could not check for updates (network error).',
75
+ },
76
+ de: {
77
+ currentVersion : 'Aktuelle Version',
78
+ latestVersion : 'Neueste Version ',
79
+ checking : 'Nach Updates suchen...',
80
+ upToDate : '✅ Aktuell — Keine neue Version verfügbar.',
81
+ updateAvail : '🔔 Update verfügbar!',
82
+ updatePrompt : 'Möchten Sie jetzt aktualisieren? [j/N]: ',
83
+ yesKeys : ['j', 'y'],
84
+ updating : '📦 Wird aktualisiert...',
85
+ updateSuccess : '✅ Update abgeschlossen! Bitte Terminal neu starten.',
86
+ updateCancelled: 'Update abgebrochen.',
87
+ updateFailed : '❌ Update fehlgeschlagen.',
88
+ networkError : '⚠️ Keine Verbindung zum Update-Server (Netzwerkfehler).',
89
+ },
90
+ fr: {
91
+ currentVersion : 'Version actuelle',
92
+ latestVersion : 'Dernière version',
93
+ checking : 'Vérification des mises à jour...',
94
+ upToDate : '✅ À jour — Aucune nouvelle version disponible.',
95
+ updateAvail : '🔔 Mise à jour disponible !',
96
+ updatePrompt : 'Mettre à jour maintenant ? [o/N] : ',
97
+ yesKeys : ['o', 'y'],
98
+ updating : '📦 Mise à jour en cours...',
99
+ updateSuccess : '✅ Mise à jour terminée ! Veuillez redémarrer votre terminal.',
100
+ updateCancelled: 'Mise à jour annulée.',
101
+ updateFailed : '❌ Échec de la mise à jour.',
102
+ networkError : '⚠️ Impossible de vérifier les mises à jour (erreur réseau).',
103
+ },
104
+ es: {
105
+ currentVersion : 'Versión actual ',
106
+ latestVersion : 'Última versión ',
107
+ checking : 'Verificando actualizaciones...',
108
+ upToDate : '✅ Al día — No hay nueva versión disponible.',
109
+ updateAvail : '🔔 ¡Actualización disponible!',
110
+ updatePrompt : '¿Actualizar ahora? [s/N]: ',
111
+ yesKeys : ['s', 'y'],
112
+ updating : '📦 Actualizando...',
113
+ updateSuccess : '✅ ¡Actualización completa! Por favor reinicie su terminal.',
114
+ updateCancelled: 'Actualización cancelada.',
115
+ updateFailed : '❌ Error en la actualización.',
116
+ networkError : '⚠️ No se pudo verificar las actualizaciones (error de red).',
117
+ },
118
+ };
25
119
 
26
- if (!php) {
27
- console.error('\n\x1b[1;31m[ArtiFrame] PHP Not Found!\x1b[0m');
28
- console.error('\x1b[33mArtiFrame CLI requires PHP 8.1 or higher.\x1b[0m\n');
29
- console.error('Install PHP:');
30
- console.error(' Windows : https://windows.php.net/download/');
31
- console.error(' macOS : brew install php');
32
- console.error(' Linux : sudo apt install php8.2-cli\n');
33
- process.exit(1);
120
+ // ── npm registry fetch ──────────────────────────────────────────
121
+ function fetchLatestVersion() {
122
+ return new Promise((resolve, reject) => {
123
+ const req = https.request({
124
+ hostname: 'registry.npmjs.org',
125
+ path : '/' + encodeURIComponent(PACKAGE_NAME) + '/latest',
126
+ method : 'GET',
127
+ headers : { Accept: 'application/json' },
128
+ timeout : 6000,
129
+ }, (res) => {
130
+ let raw = '';
131
+ res.on('data', c => raw += c);
132
+ res.on('end', () => {
133
+ try { resolve(JSON.parse(raw).version); }
134
+ catch { reject(new Error('parse')); }
135
+ });
136
+ });
137
+ req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
138
+ req.on('error', reject);
139
+ req.end();
140
+ });
34
141
  }
35
142
 
36
- // ── 2. Verify PHP version >= 8.1 ───────────────────────────────
37
- const versionResult = spawnSync(php, ['-r', 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;'], {
38
- encoding: 'utf8',
39
- shell: true
40
- });
41
-
42
- const [major, minor] = (versionResult.stdout || '0.0').split('.').map(Number);
43
- if (major < 8 || (major === 8 && minor < 1)) {
44
- console.error('\n\x1b[1;31m[ArtiFrame] PHP version too old!\x1b[0m');
45
- console.error(`\x1b[33mFound PHP ${major}.${minor} — ArtiFrame requires PHP 8.1+\x1b[0m\n`);
46
- process.exit(1);
143
+ function compareVersions(a, b) {
144
+ const pa = a.split('.').map(Number);
145
+ const pb = b.split('.').map(Number);
146
+ for (let i = 0; i < 3; i++) {
147
+ if (pa[i] > pb[i]) return 1;
148
+ if (pa[i] < pb[i]) return -1;
149
+ }
150
+ return 0;
47
151
  }
48
152
 
49
- // ── 3. Delegate to the PHP bootstrap ───────────────────────────
50
- const phpScript = path.join(__dirname, '..', 'bin', 'artiframe.php');
153
+ // ── --version handler ───────────────────────────────────────────
154
+ async function handleVersion() {
155
+ const lang = getLanguage();
156
+ const m = MESSAGES[lang] || MESSAGES.en;
157
+
158
+ console.log();
159
+ console.log(` ${W}${m.currentVersion}:${R} ${G}v${CURRENT_VERSION}${R}`);
160
+ process.stdout.write(` ${D}${m.checking}${R}`);
161
+
162
+ let latest;
163
+ try {
164
+ latest = await fetchLatestVersion();
165
+ } catch {
166
+ console.log();
167
+ console.log(` ${Y}${m.networkError}${R}`);
168
+ console.log();
169
+ process.exit(0);
170
+ }
171
+
172
+ // Clear the "checking..." line by overwriting with spaces then reprint
173
+ process.stdout.write('\r' + ' '.repeat(60) + '\r');
174
+ console.log(` ${W}${m.latestVersion}:${R} ${G}v${latest}${R}`);
175
+ console.log();
176
+
177
+ if (compareVersions(latest, CURRENT_VERSION) <= 0) {
178
+ console.log(` ${m.upToDate}`);
179
+ console.log();
180
+ process.exit(0);
181
+ }
182
+
183
+ // ── Update available ─────────────────────────────────────────
184
+ console.log(` ${Y}${m.updateAvail}${R} ${D}v${CURRENT_VERSION}${R} → ${G}v${latest}${R}`);
185
+ console.log();
186
+ process.stdout.write(` ${m.updatePrompt}`);
187
+
188
+ const rl = readline.createInterface({ input: process.stdin, terminal: false });
189
+
190
+ rl.once('line', (answer) => {
191
+ rl.close();
192
+ const yes = m.yesKeys.includes(answer.trim().toLowerCase());
193
+
194
+ if (!yes) {
195
+ console.log();
196
+ console.log(` ${D}${m.updateCancelled}${R}`);
197
+ console.log();
198
+ process.exit(0);
199
+ }
51
200
 
52
- const result = spawnSync(php, [phpScript, ...process.argv.slice(2)], {
53
- stdio: 'inherit',
54
- shell: false
55
- });
201
+ console.log();
202
+ console.log(` ${m.updating}`);
203
+ console.log();
56
204
 
57
- process.exit(result.status ?? 1);
205
+ const result = spawnSync('npm', ['install', '-g', PACKAGE_NAME], {
206
+ stdio: 'inherit',
207
+ shell: true,
208
+ });
209
+
210
+ console.log();
211
+ if (result.status === 0) {
212
+ console.log(` ${G}${m.updateSuccess}${R}`);
213
+ } else {
214
+ console.log(` ${m.updateFailed}`);
215
+ }
216
+ console.log();
217
+ process.exit(result.status ?? 1);
218
+ });
219
+ }
220
+
221
+ // ── PHP availability check ──────────────────────────────────────
222
+ function findPhp() {
223
+ for (const bin of ['php', 'php8', 'php81', 'php82', 'php83', 'php84']) {
224
+ const r = spawnSync(bin, ['--version'], { encoding: 'utf8', shell: true });
225
+ if (r.status === 0) return bin;
226
+ }
227
+ return null;
228
+ }
229
+
230
+ // ── Entry point ─────────────────────────────────────────────────
231
+ const args = process.argv.slice(2);
232
+
233
+ if (args.includes('--version') || args.includes('-v')) {
234
+ handleVersion().catch(() => process.exit(1));
235
+ } else {
236
+ // Normal PHP delegation
237
+ const php = findPhp();
238
+
239
+ if (!php) {
240
+ const lang = getLanguage();
241
+ console.error(`\n\x1b[1;31m[ArtiFrame] PHP Not Found!\x1b[0m`);
242
+ console.error(`\x1b[33mArtiFrame CLI requires PHP 8.1 or higher.\x1b[0m\n`);
243
+ console.error('Install PHP:');
244
+ console.error(' Windows : https://windows.php.net/download/');
245
+ console.error(' macOS : brew install php');
246
+ console.error(' Linux : sudo apt install php8.2-cli\n');
247
+ process.exit(1);
248
+ }
249
+
250
+ const vr = spawnSync(php, ['-r', 'echo PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;'], {
251
+ encoding: 'utf8', shell: true,
252
+ });
253
+ const [major, minor] = (vr.stdout || '0.0').split('.').map(Number);
254
+ if (major < 8 || (major === 8 && minor < 1)) {
255
+ console.error(`\n\x1b[1;31m[ArtiFrame] PHP version too old!\x1b[0m`);
256
+ console.error(`\x1b[33mFound PHP ${major}.${minor} — ArtiFrame requires PHP 8.1+\x1b[0m\n`);
257
+ process.exit(1);
258
+ }
259
+
260
+ const phpScript = path.join(__dirname, 'artiframe.php');
261
+ const result = spawnSync(php, [phpScript, ...args], {
262
+ stdio: 'inherit',
263
+ shell: false,
264
+ });
265
+ process.exit(result.status ?? 1);
266
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artilingo/artiframe-cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "ArtiFrame — Zero-dependency native PHP framework with a powerful multilingual CLI. Scaffold projects, generate views, APIs and classes instantly.",
5
5
  "main": "bin/artiframe.js",
6
6
  "bin": {