@artilingo/artiframe-cli 1.0.9 → 1.1.1

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/README.md +5 -3
  2. package/assets/banner.jpg +0 -0
  3. package/assets/profile.png +0 -0
  4. package/bin/artiframe.js +3 -2
  5. package/bin/artiframe.php +1 -1
  6. package/core-stubs/app/Database.php +1 -1
  7. package/core-stubs/app/DotEnv.php +1 -1
  8. package/core-stubs/app/R2Manager.php +1 -1
  9. package/core-stubs/bin/SystemMethod.php +292 -16
  10. package/core-stubs/bin/ViewMethod.php +146 -37
  11. package/core-stubs/docs/de.html +4419 -955
  12. package/core-stubs/docs/en.html +4419 -956
  13. package/core-stubs/docs/es.html +4419 -951
  14. package/core-stubs/docs/fr.html +4101 -536
  15. package/core-stubs/docs/tr.html +4978 -955
  16. package/core-stubs/stubs/service/image.stub +334 -0
  17. package/core-stubs/stubs/service/iyzico.stub +637 -0
  18. package/core-stubs/stubs/service/jwt.stub +312 -0
  19. package/core-stubs/stubs/service/pusher.stub +232 -0
  20. package/core-stubs/stubs/service/redis.stub +361 -0
  21. package/core-stubs/stubs/service/s3.stub +377 -0
  22. package/core-stubs/stubs/service/sentry.stub +139 -0
  23. package/core-stubs/stubs/service/stripe.stub +526 -0
  24. package/core-stubs/stubs/service/twilio.stub +361 -0
  25. package/package.json +4 -4
  26. package/src/App.php +69 -0
  27. package/src/Commands/AddCommand.php +392 -0
  28. package/src/Commands/GoCommand.php +48 -0
  29. package/src/Commands/ListCommand.php +67 -0
  30. package/src/Commands/NewProjectCommand.php +184 -30
  31. package/src/Commands/RemoveCommand.php +121 -0
  32. package/src/Commands/ServeCommand.php +71 -0
  33. package/src/Commands/ShowCommand.php +24 -0
  34. package/src/Lang/de.php +56 -0
  35. package/src/Lang/en.php +56 -0
  36. package/src/Lang/es.php +56 -0
  37. package/src/Lang/fr.php +56 -0
  38. package/src/Lang/tr.php +56 -0
package/README.md CHANGED
@@ -1,11 +1,13 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://raw.githubusercontent.com/artilingo/artiframe/main/assets/logo.png" alt="ArtiFrame Logo" width="180" />
3
+ <img src="https://raw.githubusercontent.com/utkuthecoder/artiframe-cli/refs/heads/main/assets/banner.jpg" alt="ArtiFrame - Open Sourced PHP Framework" width="100%" />
4
4
 
5
- # ArtiFrame
5
+ <br />
6
6
 
7
7
  **Zero-dependency · Native PHP · Multilingual CLI**
8
8
 
9
+ <br />
10
+
9
11
  [![npm version](https://img.shields.io/npm/v/@artilingo/artiframe-cli?color=00c88c&style=flat-square)](https://www.npmjs.com/package/@artilingo/artiframe-cli)
10
12
  [![npm downloads](https://img.shields.io/npm/dm/@artilingo/artiframe-cli?color=58a6ff&style=flat-square)](https://www.npmjs.com/package/@artilingo/artiframe-cli)
11
13
  [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-bc8cff?style=flat-square)](https://www.gnu.org/licenses/agpl-3.0)
@@ -230,7 +232,7 @@ artiframe> version upgrade minor
230
232
 
231
233
  <div align="center">
232
234
 
233
- **[artiframe.org](https://artiframe.org)** · **[npmjs.com/package/@artilingo/artiframe-cli](https://www.npmjs.com/package/@artilingo/artiframe-cli)** · **[GitHub](https://github.com/artilingo/artiframe)**
235
+ **[artiframe.artilingo.com](https://artiframe.artilingo.com)** · **[npmjs.com/package/@artilingo/artiframe-cli](https://www.npmjs.com/package/@artilingo/artiframe-cli)** · **[GitHub](https://github.com/utkuthecoder/artiframe-cli)**
234
236
 
235
237
  © Artilingo — Licensed under [AGPLv3](https://www.gnu.org/licenses/agpl-3.0)
236
238
 
Binary file
Binary file
package/bin/artiframe.js CHANGED
@@ -220,8 +220,9 @@ async function handleVersion() {
220
220
 
221
221
  // ── PHP availability check ──────────────────────────────────────
222
222
  function findPhp() {
223
- for (const bin of ['php', 'php8', 'php81', 'php82', 'php83', 'php84']) {
224
- const r = spawnSync(bin, ['--version'], { encoding: 'utf8', shell: true });
223
+ const bins = ['php', 'php8', 'php8.1', 'php8.2', 'php8.3', 'php8.4', 'php81', 'php82', 'php83', 'php84'];
224
+ for (const bin of bins) {
225
+ const r = spawnSync(bin, ['--version'], { encoding: 'utf8', shell: false });
225
226
  if (r.status === 0) return bin;
226
227
  }
227
228
  return null;
package/bin/artiframe.php CHANGED
@@ -6,7 +6,7 @@
6
6
  * @package ArtiFrame
7
7
  * @author Artilingo
8
8
  * @license AGPLv3 (Attribution-ShareAlike Required)
9
- * @link https://artiframe.org
9
+ * @link https://artiframe.artilingo.com
10
10
  */
11
11
 
12
12
  // Define constants
@@ -5,7 +5,7 @@
5
5
  * @package ArtiFrame
6
6
  * @author Artilingo
7
7
  * @license AGPLv3 (Attribution-ShareAlike Required)
8
- * @link https://artiframe.org
8
+ * @link https://artiframe.artilingo.com
9
9
  *
10
10
  * NOTICE: This file is part of the ArtiFrame ecosystem.
11
11
  * Any derivative works or patches MUST retain this original copyright notice
@@ -5,7 +5,7 @@
5
5
  * @package ArtiFrame
6
6
  * @author Artilingo
7
7
  * @license AGPLv3 (Attribution-ShareAlike Required)
8
- * @link https://artiframe.org
8
+ * @link https://artiframe.artilingo.com
9
9
  *
10
10
  * NOTICE: This file is part of the ArtiFrame ecosystem.
11
11
  * Any derivative works or patches MUST retain this original copyright notice
@@ -5,7 +5,7 @@
5
5
  * @package ArtiFrame
6
6
  * @author Artilingo
7
7
  * @license AGPLv3 (Attribution-ShareAlike Required)
8
- * @link https://artiframe.org
8
+ * @link https://artiframe.artilingo.com
9
9
  *
10
10
  * NOTICE: This file is part of the ArtiFrame ecosystem.
11
11
  * Any derivative works or patches MUST retain this original copyright notice
@@ -5,7 +5,7 @@
5
5
  * @package ArtiFrame
6
6
  * @author Artilingo
7
7
  * @license AGPLv3 (Attribution-ShareAlike Required)
8
- * @link https://artiframe.org
8
+ * @link https://artiframe.artilingo.com
9
9
  *
10
10
  * NOTICE: This file is part of the ArtiFrame ecosystem.
11
11
  * Any derivative works or patches MUST retain this original copyright notice
@@ -111,6 +111,29 @@ class SystemMethod
111
111
  echo json_encode($data, JSON_UNESCAPED_UNICODE);
112
112
  exit;
113
113
  }
114
+
115
+ /**
116
+ * Standart API yanıtı (JSON) oluşturur.
117
+ * APP_ENV = 1 (Debug) ise Exception detaylarını mesaja yazar.
118
+ * APP_ENV = 0 (Prod) ise kullanıcının girdiği temiz mesajı gösterir.
119
+ */
120
+ public static function apiResponse(string $status, string $message, array $data = [], \Throwable $exception = null): void
121
+ {
122
+ // Debug modundaysak ve bir exception geldiyse, mesajı ezip sistem hatasını basıyoruz
123
+ if (defined('APP_ENV') && APP_ENV === 1 && $exception !== null) {
124
+ $message = $exception->getMessage() . ' (Dosya: ' . $exception->getFile() . ' Satır: ' . $exception->getLine() . ')';
125
+ }
126
+
127
+ $response = [
128
+ 'status' => $status,
129
+ 'message' => $message,
130
+ 'data' => $data
131
+ ];
132
+
133
+ $statusCode = ($status === 'success') ? 200 : 400;
134
+ self::jsonResponse($response, $statusCode);
135
+ }
136
+
114
137
  /**
115
138
  * Sayfaya gelen isteğin GET olup olmadığını kontrol eder.
116
139
  */
@@ -170,6 +193,31 @@ class SystemMethod
170
193
  return bin2hex(random_bytes($length));
171
194
  }
172
195
 
196
+ /**
197
+ * Şifreyi bcrypt algoritmasıyla güvenli bir şekilde hash'ler.
198
+ * Boş veya null gelirse güvenliği sağlamak adına exception fırlatır.
199
+ */
200
+ public static function hashPassword(?string $password): string
201
+ {
202
+ if (empty($password)) {
203
+ throw new \Exception('Password cannot be empty or null.');
204
+ }
205
+ return password_hash($password, PASSWORD_BCRYPT);
206
+ }
207
+
208
+ /**
209
+ * Düz metin şifreyi veritabanındaki hash ile karşılaştırır.
210
+ * Herhangi biri null veya boşsa her zaman false döner.
211
+ */
212
+ public static function verifyPassword(?string $password, ?string $hash): bool
213
+ {
214
+ if (empty($password) || empty($hash)) {
215
+ return false;
216
+ }
217
+ return password_verify($password, $hash);
218
+ }
219
+
220
+
173
221
  /**
174
222
  * E-posta adresini zararlı karakterlerden temizler.
175
223
  */
@@ -177,95 +225,323 @@ class SystemMethod
177
225
  {
178
226
  return filter_var($email, FILTER_SANITIZE_EMAIL);
179
227
  }
228
+
229
+ /**
230
+ * Gelen veriyi güvenli bir ondalıklı (float) sayıya dönüştürür.
231
+ * Fiyat ve oran hesaplamalarında kullanılır.
232
+ */
233
+ public static function sanitizeFloat($value): float
234
+ {
235
+ return (float) filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
236
+ }
237
+
238
+ /**
239
+ * Bir diziden sadece belirtilen anahtarlara (keys) sahip olanları seçer.
240
+ * Güvenli mass-assignment (toplu atama) için kullanılır.
241
+ */
242
+ public static function arrayOnly(array $source, array $keys): array
243
+ {
244
+ return array_intersect_key($source, array_flip($keys));
245
+ }
246
+
247
+ /**
248
+ * Hızlı hata ayıklama aracı. (Dump & Die)
249
+ */
250
+ public static function dd(...$vars): void
251
+ {
252
+ echo '<pre style="background:#1d232a;color:#a6adbb;padding:16px;border-radius:8px;font-size:14px;overflow-x:auto;z-index:9999;position:relative;">';
253
+ foreach ($vars as $var) {
254
+ var_dump($var);
255
+ }
256
+ echo '</pre>';
257
+ exit;
258
+ }
259
+
260
+ /**
261
+ * Metni URL dostu bir slug'a çevirir (Örn: "Utku", "Egemen" -> "utku-egemen")
262
+ * (SystemMethod için global kullanılabilir versiyon)
263
+ */
264
+ public static function slugify(string ...$texts): string
265
+ {
266
+ $text = implode('-', $texts);
267
+ $text = mb_strtolower($text, 'UTF-8');
268
+
269
+ $search = [
270
+ 'ç', 'ğ', 'ı', 'ö', 'ş', 'ü', // TR
271
+ 'ä', 'ß', // DE
272
+ 'ñ', // ES
273
+ 'é', 'è', 'ê', 'ë', 'à', 'á', 'â', 'î', 'ï', 'í', 'ô', 'ó', 'ú', 'û', 'ù', 'æ', 'œ' // FR & ES
274
+ ];
275
+ $replace = [
276
+ 'c', 'g', 'i', 'o', 's', 'u',
277
+ 'ae', 'ss',
278
+ 'n',
279
+ 'e', 'e', 'e', 'e', 'a', 'a', 'a', 'i', 'i', 'i', 'o', 'o', 'u', 'u', 'u', 'ae', 'oe'
280
+ ];
281
+
282
+ $text = str_replace($search, $replace, $text);
283
+ $text = preg_replace('/[^a-z0-9\-]/', '-', $text);
284
+ $text = preg_replace('/-+/', '-', $text);
285
+ return trim($text, '-');
286
+ }
287
+
288
+ /**
289
+ * Natively generates a raw 16-byte binary UUIDv7.
290
+ * Ideal for BINARY(16) database columns (High performance indexing).
291
+ *
292
+ * @return string 16-byte raw binary string
293
+ */
294
+ public static function byteId(): string
295
+ {
296
+ // Get current timestamp in milliseconds (48-bit)
297
+ $ts = (int)(microtime(true) * 1000);
298
+ $timeHex = str_pad(dechex($ts), 12, '0', STR_PAD_LEFT);
299
+ $timeBin = hex2bin($timeHex);
300
+
301
+ // Generate 10 bytes of randomness
302
+ $rand = random_bytes(10);
303
+
304
+ // Set UUID Version (7) -> 4 bits of the 7th byte
305
+ $rand[0] = chr((ord($rand[0]) & 0x0F) | 0x70);
306
+
307
+ // Set UUID Variant (10) -> 2 bits of the 9th byte
308
+ $rand[2] = chr((ord($rand[2]) & 0x3F) | 0x80);
309
+
310
+ // Return exactly 16 bytes (6 bytes time + 10 bytes rand)
311
+ return $timeBin . $rand;
312
+ }
313
+
314
+ /**
315
+ * Converts a raw 16-byte binary UUID into its standard string representation.
316
+ * (e.g. 0190ed84-3f12-7a91-8bc4-91823741abcd)
317
+ *
318
+ * @param string $binaryUuid 16-byte binary string
319
+ * @return string 36-character hyphenated UUID string
320
+ */
321
+ public static function formatId(string $binaryUuid): string
322
+ {
323
+ if (strlen($binaryUuid) !== 16) {
324
+ throw new \InvalidArgumentException("Invalid binary UUID length. Expected 16 bytes.");
325
+ }
326
+
327
+ $hex = bin2hex($binaryUuid);
328
+
329
+ return sprintf(
330
+ '%s-%s-%s-%s-%s',
331
+ substr($hex, 0, 8),
332
+ substr($hex, 8, 4),
333
+ substr($hex, 12, 4),
334
+ substr($hex, 16, 4),
335
+ substr($hex, 20, 12)
336
+ );
337
+ }
338
+
339
+ /**
340
+ * Generates a standard formatted UUIDv7 string.
341
+ *
342
+ * @return string 36-character hyphenated UUID string
343
+ */
344
+ public static function makeId(): string
345
+ {
346
+ return self::formatId(self::byteId());
347
+ }
348
+
349
+ /**
350
+ * Rastgele Integer ID üretir. (Max 9 hane - MySQL INT sınırı)
351
+ */
352
+ public static function intId(int $length = 8): int
353
+ {
354
+ if ($length > 9) $length = 9;
355
+ if ($length < 1) $length = 1;
356
+
357
+ $min = (int) str_pad('1', $length, '0');
358
+ $max = (int) str_pad('9', $length, '9');
359
+
360
+ return random_int($min, $max);
361
+ }
362
+
363
+ /**
364
+ * Rastgele BigInt ID üretir.
365
+ * Javascript MAX_SAFE_INTEGER (15 hane) sınırını aşmamak için varsayılan 15'tir.
366
+ * 16-18 hane istenirse veri kaybını önlemek için asString = true önerilir.
367
+ */
368
+ public static function bigintId(int $length = 15, bool $asString = false)
369
+ {
370
+ if ($length > 18) $length = 18;
371
+ if ($length < 1) $length = 1;
372
+
373
+ $min = str_pad('1', $length, '0');
374
+ $max = str_pad('9', $length, '9');
375
+
376
+ $result = random_int((int)$min, (int)$max);
377
+
378
+ return $asString ? (string) $result : $result;
379
+ }
380
+
381
+ /**
382
+ * Gelen veriyi (özellikle BigInt ID'leri) güvenli bir şekilde string'e çevirir.
383
+ * Javascript'te 15 haneyi aşan sayılardaki veri kaybını engellemek için
384
+ * View dosyalarında data-id=<?= stringer($id) ?> şeklinde kullanılır.
385
+ */
386
+ public static function stringer($value): string
387
+ {
388
+ return (string) $value;
389
+ }
180
390
  }
181
391
 
182
392
  // Global helper functions for backend methods
183
- if (!function_exists('verifyEmail')) {
393
+ if (!function_exists(__NAMESPACE__ . '\\verifyEmail')) {
184
394
  function verifyEmail(string $email): bool {
185
395
  return \Bin\SystemMethod::verifyEmail($email);
186
396
  }
187
397
  }
188
398
 
189
- if (!function_exists('sanitizeInt')) {
399
+ if (!function_exists(__NAMESPACE__ . '\\sanitizeInt')) {
190
400
  function sanitizeInt($value): int {
191
401
  return \Bin\SystemMethod::sanitizeInt($value);
192
402
  }
193
403
  }
194
404
 
195
- if (!function_exists('sanitizeString')) {
405
+ if (!function_exists(__NAMESPACE__ . '\\sanitizeString')) {
196
406
  function sanitizeString(string $value): string {
197
407
  return \Bin\SystemMethod::sanitizeString($value);
198
408
  }
199
409
  }
200
410
 
201
- if (!function_exists('isPost')) {
411
+ if (!function_exists(__NAMESPACE__ . '\\isPost')) {
202
412
  function isPost(): bool {
203
413
  return \Bin\SystemMethod::isPost();
204
414
  }
205
415
  }
206
416
 
207
- if (!function_exists('jsonResponse')) {
417
+ if (!function_exists(__NAMESPACE__ . '\\jsonResponse')) {
208
418
  function jsonResponse(array $data, int $statusCode = 200): void {
209
419
  \Bin\SystemMethod::jsonResponse($data, $statusCode);
210
420
  }
211
421
  }
212
422
 
213
- if (!function_exists('generateCsrf')) {
423
+ if (!function_exists(__NAMESPACE__ . '\\apiResponse')) {
424
+ function apiResponse(string $status, string $message, array $data = [], \Throwable $exception = null): void {
425
+ \Bin\SystemMethod::apiResponse($status, $message, $data, $exception);
426
+ }
427
+ }
428
+
429
+ if (!function_exists(__NAMESPACE__ . '\\generateCsrf')) {
214
430
  function generateCsrf(): string {
215
431
  return \Bin\SystemMethod::generateCsrf();
216
432
  }
217
433
  }
218
434
 
219
- if (!function_exists('verifyCsrf')) {
435
+ if (!function_exists(__NAMESPACE__ . '\\verifyCsrf')) {
220
436
  function verifyCsrf(?string $token): bool {
221
437
  return \Bin\SystemMethod::verifyCsrf($token);
222
438
  }
223
439
  }
224
440
 
225
- if (!function_exists('isAjax')) {
441
+ if (!function_exists(__NAMESPACE__ . '\\isAjax')) {
226
442
  function isAjax(): bool {
227
443
  return \Bin\SystemMethod::isAjax();
228
444
  }
229
445
  }
230
446
 
231
- if (!function_exists('isGet')) {
447
+ if (!function_exists(__NAMESPACE__ . '\\isGet')) {
232
448
  function isGet(): bool {
233
449
  return \Bin\SystemMethod::isGet();
234
450
  }
235
451
  }
236
452
 
237
- if (!function_exists('isPut')) {
453
+ if (!function_exists(__NAMESPACE__ . '\\isPut')) {
238
454
  function isPut(): bool {
239
455
  return \Bin\SystemMethod::isPut();
240
456
  }
241
457
  }
242
458
 
243
- if (!function_exists('isDelete')) {
459
+ if (!function_exists(__NAMESPACE__ . '\\isDelete')) {
244
460
  function isDelete(): bool {
245
461
  return \Bin\SystemMethod::isDelete();
246
462
  }
247
463
  }
248
464
 
249
- if (!function_exists('getClientIp')) {
465
+ if (!function_exists(__NAMESPACE__ . '\\getClientIp')) {
250
466
  function getClientIp(): string {
251
467
  return \Bin\SystemMethod::getClientIp();
252
468
  }
253
469
  }
254
470
 
255
- if (!function_exists('redirect')) {
471
+ if (!function_exists(__NAMESPACE__ . '\\redirect')) {
256
472
  function redirect(string $url): void {
257
473
  \Bin\SystemMethod::redirect($url);
258
474
  }
259
475
  }
260
476
 
261
- if (!function_exists('generateToken')) {
477
+ if (!function_exists(__NAMESPACE__ . '\\generateToken')) {
262
478
  function generateToken(int $length = 32): string {
263
479
  return \Bin\SystemMethod::generateToken($length);
264
480
  }
265
481
  }
266
482
 
267
- if (!function_exists('sanitizeEmail')) {
483
+ if (!function_exists(__NAMESPACE__ . '\\sanitizeEmail')) {
268
484
  function sanitizeEmail(string $email): string {
269
485
  return \Bin\SystemMethod::sanitizeEmail($email);
270
486
  }
271
487
  }
488
+
489
+ if (!function_exists(__NAMESPACE__ . '\\sanitizeFloat')) {
490
+ function sanitizeFloat($value): float {
491
+ return \Bin\SystemMethod::sanitizeFloat($value);
492
+ }
493
+ }
494
+
495
+ if (!function_exists(__NAMESPACE__ . '\\arrayOnly')) {
496
+ function arrayOnly(array $source, array $keys): array {
497
+ return \Bin\SystemMethod::arrayOnly($source, $keys);
498
+ }
499
+ }
500
+
501
+ if (!function_exists(__NAMESPACE__ . '\\dd')) {
502
+ function dd(...$vars): void {
503
+ \Bin\SystemMethod::dd(...$vars);
504
+ }
505
+ }
506
+
507
+ if (!function_exists(__NAMESPACE__ . '\\slugify')) {
508
+ function slugify(string ...$texts): string {
509
+ return \Bin\SystemMethod::slugify(...$texts);
510
+ }
511
+ }
512
+
513
+ if (!function_exists(__NAMESPACE__ . '\\byteId')) {
514
+ function byteId(): string {
515
+ return \Bin\SystemMethod::byteId();
516
+ }
517
+ }
518
+
519
+ if (!function_exists(__NAMESPACE__ . '\\formatId')) {
520
+ function formatId(string $binaryUuid): string {
521
+ return \Bin\SystemMethod::formatId($binaryUuid);
522
+ }
523
+ }
524
+
525
+ if (!function_exists(__NAMESPACE__ . '\\makeId')) {
526
+ function makeId(): string {
527
+ return \Bin\SystemMethod::makeId();
528
+ }
529
+ }
530
+
531
+ if (!function_exists(__NAMESPACE__ . '\\intId')) {
532
+ function intId(int $length = 8): int {
533
+ return \Bin\SystemMethod::intId($length);
534
+ }
535
+ }
536
+
537
+ if (!function_exists(__NAMESPACE__ . '\\bigintId')) {
538
+ function bigintId(int $length = 15, bool $asString = false) {
539
+ return \Bin\SystemMethod::bigintId($length, $asString);
540
+ }
541
+ }
542
+
543
+ if (!function_exists(__NAMESPACE__ . '\\stringer')) {
544
+ function stringer($value): string {
545
+ return \Bin\SystemMethod::stringer($value);
546
+ }
547
+ }