├── resources ├── js │ └── app.js ├── css │ └── app.css ├── views │ └── welcome.kita.php └── lang │ ├── en.php │ └── id.php ├── cache ├── env │ └── .gitignore ├── log │ └── .gitignore ├── queue │ └── .gitignore ├── routes │ └── .gitignore └── views │ └── .gitignore ├── shared └── .gitignore ├── public ├── robots.txt ├── kamu.png ├── favicon.ico ├── js │ └── app.js ├── index.php ├── .htaccess └── css │ └── app.css ├── .editorconfig ├── tailwind.config.js ├── .gitattributes ├── routes ├── routes.php └── api.php ├── .gitignore ├── package.json ├── app ├── Controllers │ └── WelcomeController.php ├── Middleware │ ├── GuestMiddleware.php │ ├── AuthMiddleware.php │ ├── CookieMiddleware.php │ ├── ResponseMiddleware.php │ ├── CsrfMiddleware.php │ ├── IpUserAgentMiddleware.php │ ├── CorsMiddleware.php │ └── GzipMiddleware.php ├── Providers │ ├── AppServiceProvider.php │ ├── TranslatorServiceProvide.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php ├── Models │ └── User.php ├── Error │ └── Error.php └── Kernel.php ├── .env.example ├── database ├── generator │ └── generator.php └── schema │ └── 1653666213_users.php ├── saya ├── composer.json └── README.md /resources/js/app.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cache/env/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /cache/log/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /shared/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /cache/queue/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /cache/routes/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /cache/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/kamu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dewanakl/kamu/HEAD/public/kamu.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dewanakl/kamu/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /resources/css/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./resources/**/*.{html,js,php}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | } 9 | -------------------------------------------------------------------------------- /public/js/app.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', () => { 2 | const INFO = document.getElementById('information'); 3 | INFO.innerText = 'for educational purposes || ready for production'; 4 | }); -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.php diff=php 4 | *.html diff=html 5 | *.css diff=css 6 | *.md diff=markdown 7 | 8 | /.github export-ignore 9 | CODE_OF_CONDUCT.md export-ignore 10 | SECURITY.md export-ignore 11 | -------------------------------------------------------------------------------- /routes/routes.php: -------------------------------------------------------------------------------- 1 | view('welcome', [ 13 | 'data' => 'PHP Framework' 14 | ]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Kamu 2 | APP_KEY= 3 | BASEURL=http://localhost:8000/ 4 | DEBUG=true 5 | LOG=true 6 | 7 | TIMEZONE=Asia/Jakarta 8 | GZIP=true 9 | COOKIE=true 10 | COOKIE_LIFETIME=120 11 | 12 | DB_DRIV=mysql 13 | DB_HOST=127.0.0.1 14 | DB_PORT=3306 15 | DB_NAME=kamu 16 | DB_USER=root 17 | DB_PASS= 18 | 19 | MAIL_HOST=smtp.gmail.com 20 | MAIL_PORT=587 21 | MAIL_ENCRYPTION=tcp 22 | MAIL_USERNAME= 23 | MAIL_PASSWORD= 24 | MAIL_FROM_ADDRESS= 25 | MAIL_FROM_NAME=kamu 26 | -------------------------------------------------------------------------------- /app/Middleware/GuestMiddleware.php: -------------------------------------------------------------------------------- 1 | check()) { 14 | return $next($request); 15 | } 16 | 17 | return respond()->to('/'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Middleware/AuthMiddleware.php: -------------------------------------------------------------------------------- 1 | to('/login'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /database/generator/generator.php: -------------------------------------------------------------------------------- 1 | 'User', 18 | 'email' => 'user@example.com', 19 | 'password' => Hash::make('12345678') 20 | ]); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | run(); 23 | -------------------------------------------------------------------------------- /saya: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run()); 24 | -------------------------------------------------------------------------------- /app/Providers/TranslatorServiceProvide.php: -------------------------------------------------------------------------------- 1 | get('lang', 'id')); 20 | 21 | if (!in_array($requestLang, $this->allowedLanguages, true)) { 22 | $requestLang = 'id'; 23 | } 24 | 25 | Trans::setLanguage($requestLang); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Redirect all requests to index.php 18 | RewriteCond %{REQUEST_FILENAME} !-f 19 | RewriteCond %{REQUEST_FILENAME} !-d 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /app/Middleware/CookieMiddleware.php: -------------------------------------------------------------------------------- 1 | server->get('REQUEST_URL'), RouteServiceProvider::$API_PREFIX) !== false 17 | && $request->server->get('REQUEST_URL') !== RouteServiceProvider::$API_PREFIX 18 | ) { 19 | Env::set('COOKIE', 'false'); 20 | } 21 | 22 | return $next($request); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | fake()->name(), 31 | 'email' => fake()->email(), 32 | 'password' => Hash::make(fake()->text(8)), 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/schema/1653666213_users.php: -------------------------------------------------------------------------------- 1 | id(); 18 | 19 | $table->string('nama', 50); 20 | $table->string('email', 100)->unique(); 21 | $table->string('password'); 22 | 23 | $table->timeStamp(); 24 | }); 25 | } 26 | 27 | /** 28 | * Kembalikan seperti semula. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('users'); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /app/Middleware/ResponseMiddleware.php: -------------------------------------------------------------------------------- 1 | getHeader(); 14 | $headers->set('X-Accel-Buffering', 'no'); 15 | 16 | if (!https()) { 17 | return $next($request); 18 | } 19 | 20 | $headers 21 | ->set('Referrer-Policy', 'strict-origin-when-cross-origin') 22 | ->set('Content-Security-Policy', 'upgrade-insecure-requests') 23 | ->set('X-Content-Type-Options', 'nosniff') 24 | ->set('X-Frame-Options', 'SAMEORIGIN'); 25 | 26 | return $next($request); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Providers/EventServiceProvider.php: -------------------------------------------------------------------------------- 1 | > 15 | */ 16 | protected $listen = [ 17 | // \App\Events\Registered::class => [ 18 | // \App\Listeners\SendEmailNotification::class, 19 | // ], 20 | ]; 21 | 22 | /** 23 | * Registrasi apa aja disini. 24 | * 25 | * @return void 26 | */ 27 | public function registrasi() 28 | { 29 | $this->app->bind(Dispatch::class, function (): Dispatch { 30 | return new Dispatch(new Listener($this->listen)); 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Middleware/CsrfMiddleware.php: -------------------------------------------------------------------------------- 1 | method(Request::GET) && !$request->ajax()) { 21 | $result = $this->checkToken($request->get(Session::TOKEN, Hash::rand(10))); 22 | } else if ($request->ajax()) { 23 | $result = $this->checkToken($request->ajax(), true); 24 | } 25 | 26 | if ($result) { 27 | return $result; 28 | } 29 | 30 | return $next($request); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Error/Error.php: -------------------------------------------------------------------------------- 1 | getRequestId();` untuk menelusuri error lebih lanjut. 21 | * Contoh penggunaannya: 22 | * - Cek log berdasarkan ID tersebut, misalnya di folder: cache/log/kamu.log 23 | */ 24 | 25 | // do something here, like logging the error 26 | // and return basic error response to the user 27 | } 28 | 29 | return parent::render(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kamu/kamu", 3 | "type": "project", 4 | "description": "The Kamu Framework.", 5 | "keywords": [ 6 | "framework", 7 | "kamu" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^8.1", 12 | "kamu/framework": "^3.3" 13 | }, 14 | "require-dev": { 15 | "fakerphp/faker": "^1.23", 16 | "psy/psysh": "^0.11.22" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "App\\": "app/" 21 | } 22 | }, 23 | "scripts": { 24 | "post-root-package-install": [ 25 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 26 | ], 27 | "post-create-project-cmd": [ 28 | "@php saya key" 29 | ] 30 | }, 31 | "config": { 32 | "optimize-autoloader": true, 33 | "preferred-install": "dist", 34 | "sort-packages": true 35 | }, 36 | "minimum-stability": "stable", 37 | "prefer-stable": true 38 | } 39 | -------------------------------------------------------------------------------- /app/Middleware/IpUserAgentMiddleware.php: -------------------------------------------------------------------------------- 1 | env('HTTP_CF_CONNECTING_IP') ? $request->server->get('HTTP_CF_CONNECTING_IP', $request->ip()) : $request->ip(), 17 | 'user_agent' => $request->userAgent(), 18 | ], [ 19 | 'ip' => ['required', 'str', 'trim', 'min:2', 'max:45', 'ip'], 20 | 'user_agent' => ['required', 'str', 'trim', 'min:64', 'max:512'], 21 | ]); 22 | 23 | if ($valid->fails()) { 24 | throw new Exception('Invalid IP or User Agent'); 25 | } 26 | 27 | context('ip', $valid->ip); 28 | context('user_agent', $valid->user_agent); 29 | 30 | return $next($request); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /resources/views/welcome.kita.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Kamu - PHP Framework 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |

Kamu

20 |

21 | {{ $data }} 22 |

23 | 24 |
25 |
26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/Middleware/CorsMiddleware.php: -------------------------------------------------------------------------------- 1 | getHeader(); 15 | $header->set('Access-Control-Allow-Origin', '*'); 16 | $header->set('Access-Control-Expose-Headers', 'Content-Length, Content-Disposition'); 17 | 18 | $varyList = ['Accept', 'Access-Control-Request-Method', 'Access-Control-Request-Headers', 'Origin']; 19 | 20 | if ($header->has('Vary')) { 21 | $existing = preg_split('/\s*,\s*/', $header->get('Vary'), -1, PREG_SPLIT_NO_EMPTY); 22 | $varyList = array_merge($existing, $varyList); 23 | } 24 | 25 | $varyList = array_unique(array_map('trim', $varyList)); 26 | $header->set('Vary', implode(', ', $varyList)); 27 | 28 | if (!$request->method(Request::OPTIONS)) { 29 | return $next($request); 30 | } 31 | 32 | $header->unset('Content-Type'); 33 | 34 | if (!$request->server->has('HTTP_ACCESS_CONTROL_REQUEST_METHOD')) { 35 | return respond()->setCode(Respond::HTTP_NO_CONTENT); 36 | } 37 | 38 | $header->set( 39 | 'Access-Control-Allow-Methods', 40 | strtoupper($request->server->get('HTTP_ACCESS_CONTROL_REQUEST_METHOD', $request->method())) 41 | ); 42 | 43 | $header->set('Access-Control-Allow-Headers', 'Accept, Authorization, Content-Type'); 44 | 45 | return respond()->setCode(Respond::HTTP_NO_CONTENT); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /resources/lang/en.php: -------------------------------------------------------------------------------- 1 | [ 8 | 9 | 'failed' => ':email or :password incorrect.', 10 | ], 11 | 12 | /** 13 | * Time. 14 | */ 15 | \Core\Support\Time::NAME => [ 16 | 17 | 'y' => 'year', 18 | 'm' => 'month', 19 | 'd' => 'day', 20 | 'h' => 'hour', 21 | 'i' => 'minute', 22 | 's' => 'second', 23 | 24 | 'ago' => 'ago.', 25 | 'future' => 'from now.', 26 | 'recently' => 'just now.', 27 | ], 28 | 29 | /** 30 | * Validator. 31 | */ 32 | \Core\Valid\Validator::NAME => [ 33 | 34 | 'request' => [ 35 | 'required' => ':field is required!.', 36 | 'email' => ':field is invalid!.', 37 | 'dns' => ':field is invalid!.', 38 | 'url' => ':field is invalid!.', 39 | 'ip' => ':field is invalid!.', 40 | 'uuid' => ':field is not a uuid!.', 41 | 'int' => ':field must be a number!.', 42 | 'float' => ':field must be decimal!.', 43 | 'min' => ':field minimum length: :attribute', 44 | 'max' => ':field maximum length: :attribute', 45 | 'sama' => ':field does not match with :attribute', 46 | 'unik' => ':field already exists!.', 47 | ], 48 | 49 | 'file' => [ 50 | 'required' => ':field is required!.', 51 | 'min' => ':field minimum length: :attribute', 52 | 'max' => ':field maximum length: :attribute', 53 | 'mimetypes' => ':field allowed: :attribute', 54 | 'mimes' => ':field allowed: :attribute', 55 | 'unsafe' => ':field is indicated as unsafe!.', 56 | 'corrupt' => ':field was not uploaded correctly!.', 57 | ], 58 | ] 59 | ]; 60 | -------------------------------------------------------------------------------- /resources/lang/id.php: -------------------------------------------------------------------------------- 1 | [ 8 | 9 | 'failed' => ':email atau :password salah.', 10 | ], 11 | 12 | /** 13 | * Time. 14 | */ 15 | \Core\Support\Time::NAME => [ 16 | 17 | 'y' => 'tahun', 18 | 'm' => 'bulan', 19 | 'd' => 'hari', 20 | 'h' => 'jam', 21 | 'i' => 'menit', 22 | 's' => 'detik', 23 | 24 | 'ago' => 'yang lalu.', 25 | 'future' => 'ke depan.', 26 | 'recently' => 'baru saja.', 27 | ], 28 | 29 | /** 30 | * Validator. 31 | */ 32 | \Core\Valid\Validator::NAME => [ 33 | 34 | 'request' => [ 35 | 'required' => ':field dibutuhkan!.', 36 | 'email' => ':field tidak valid!.', 37 | 'dns' => ':field tidak valid!.', 38 | 'url' => ':field tidak valid!.', 39 | 'ip' => ':field tidak valid!.', 40 | 'uuid' => ':field bukan uuid!.', 41 | 'int' => ':field harus angka!.', 42 | 'float' => ':field harus desimal!.', 43 | 'min' => ':field panjang minimal: :attribute', 44 | 'max' => ':field panjang maxsimal: :attribute', 45 | 'sama' => ':field tidak sama dengan :attribute', 46 | 'unik' => ':field sudah ada!.', 47 | ], 48 | 49 | 'file' => [ 50 | 'required' => ':field dibutuhkan!.', 51 | 'min' => ':field panjang minimal: :attribute', 52 | 'max' => ':field panjang maxsimal: :attribute', 53 | 'mimetypes' => ':field diperbolehkan: :attribute', 54 | 'mimes' => ':field diperbolehkan: :attribute', 55 | 'unsafe' => ':field terindikasi tidak aman!.', 56 | 'corrupt' => ':field tidak terupload dengan benar!.', 57 | ], 58 | ] 59 | ]; 60 | -------------------------------------------------------------------------------- /app/Kernel.php: -------------------------------------------------------------------------------- 1 | path = dirname(__DIR__); 29 | } 30 | 31 | /** 32 | * Dapatkan lokasi dari app. 33 | * 34 | * @return string 35 | */ 36 | public function path(): string 37 | { 38 | return $this->path; 39 | } 40 | 41 | /** 42 | * Kirim errornya lewat class. 43 | * 44 | * @return string 45 | */ 46 | public function error(): string 47 | { 48 | return \App\Error\Error::class; 49 | } 50 | 51 | /** 52 | * Kumpulan middleware yang dijalankan lebih awal. 53 | * 54 | * @return array 55 | */ 56 | public function middlewares(): array 57 | { 58 | return [ 59 | \App\Middleware\CorsMiddleware::class, 60 | \App\Middleware\ResponseMiddleware::class, 61 | \App\Middleware\GzipMiddleware::class, 62 | \App\Middleware\IpUserAgentMiddleware::class, 63 | ]; 64 | } 65 | 66 | /** 67 | * Registrasi service agar bisa dijalankan. 68 | * 69 | * @return array 70 | */ 71 | public function services(): array 72 | { 73 | return [ 74 | \App\Providers\AppServiceProvider::class, 75 | \App\Providers\RouteServiceProvider::class, 76 | \App\Providers\EventServiceProvider::class, 77 | \App\Providers\TranslatorServiceProvide::class, 78 | ]; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/Middleware/GzipMiddleware.php: -------------------------------------------------------------------------------- 1 | getCode() < 400 && $response->getCode() >= 300) { 23 | return $response; 24 | } 25 | 26 | $response = respond()->transform($response); 27 | 28 | if (env('GZIP', 'true') != 'true') { 29 | return $response; 30 | } 31 | 32 | if (!str_contains($request->server->get('HTTP_ACCEPT_ENCODING', ''), 'gzip')) { 33 | return $response; 34 | } 35 | 36 | if (!$response->getContent()) { 37 | return $response; 38 | } 39 | 40 | $compressed = gzencode($response->getContent(), 3); 41 | 42 | if ($compressed === false) { 43 | return $response; 44 | } 45 | 46 | $response->setContent($compressed); 47 | 48 | $varyList = ['Accept-Encoding']; 49 | 50 | if ($response->headers->has('Vary')) { 51 | $existing = preg_split('/\s*,\s*/', $response->headers->get('Vary'), -1, PREG_SPLIT_NO_EMPTY); 52 | $varyList = array_merge($existing, $varyList); 53 | } 54 | 55 | $varyList = array_unique(array_map('trim', $varyList)); 56 | $response->headers->set('Vary', implode(', ', $varyList)); 57 | 58 | $response->headers->set('Content-Encoding', 'gzip'); 59 | 60 | return $response; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

kamu

2 | 3 |

4 | PHP Programming Language 5 | Total Downloads 6 | repo size 7 | Latest Stable Version 8 | License 9 |

10 | 11 | ## 📖 About Kamu 12 | 13 | "Kamu" merupakan PHP framework yang sangat simpel, memberikan pengalaman seolah-olah berada di localhost meskipun dalam mode production. Dibantu dengan "Saya" konsol yang membantu pengembangan aplikasi secara efisien. 14 | 15 | ## 🚀 Get Started Project 16 | - Create a project with composer 17 | ```bash 18 | composer create-project kamu/kamu coba-app 19 | ``` 20 | - Move the folder 21 | ```bash 22 | cd coba-app 23 | ``` 24 | - Run in development server 25 | ```bash 26 | php saya coba 27 | ``` 28 | 29 | ## 🤝 Contributing 30 | 31 | I'm very open to those of you who want to contribute to the Kamu framework! 32 | 33 | ## 🐞 Security Vulnerabilities 34 | 35 | If you find any security vulnerabilities in this Kamu framework, please email DKL via [dewanakretarta29@gmail.com](mailto:dewanakretarta29@gmail.com). 36 | 37 | ## 📜 License 38 | 39 | Kamu framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). 40 | -------------------------------------------------------------------------------- /public/css/app.css: -------------------------------------------------------------------------------- 1 | /*! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.m-0{margin:0}.mr-1{margin-right:.25rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.h-screen{height:100vh}.items-center{align-items:center}.justify-center{justify-content:center}.rounded-xl{border-radius:.75rem}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-indigo-300{--tw-gradient-from:#a5b4fc;--tw-gradient-to:#a5b4fc00;--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-purple-400{--tw-gradient-to:#c084fc}.p-8{padding:2rem}.text-center{text-align:center}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.font-medium{font-weight:500}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity))}.drop-shadow-2xl{--tw-drop-shadow:drop-shadow(0 25px 25px #00000026);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)} -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton(Router::class); 30 | 31 | if (!Route::setRouteFromCacheIfExist()) { 32 | Route::middleware(CsrfMiddleware::class)->group(function () { 33 | Route::setRouteFromFile(); 34 | }); 35 | 36 | Route::prefix(static::$API_PREFIX)->middleware(CookieMiddleware::class)->group(function () { 37 | Route::get('/health', [static::class, 'health']); 38 | require_once base_path('/routes/api.php'); 39 | }); 40 | } 41 | } 42 | 43 | /** 44 | * Get health this application. 45 | * 46 | * @return \Core\Http\Respond 47 | */ 48 | public function health(): \Core\Http\Respond 49 | { 50 | $data = [ 51 | 'status' => true 52 | ]; 53 | 54 | if (!hash_equals(hash('sha3-512', env('APP_KEY')), request()->get('hash', ''))) { 55 | return respond()->setContent(json($data, 200)); 56 | } 57 | 58 | $data['system'] = [ 59 | 'php_version' => PHP_VERSION, 60 | 'execute_time' => execute_time(), 61 | 'memory_peak_usage' => format_bytes(memory_get_peak_usage(true)), 62 | ]; 63 | 64 | $data['system']['opcache'] = [ 65 | 'opcache_enabled' => false, 66 | 'opcache_used_memory' => format_bytes(0), 67 | 'opcache_free_memory' => format_bytes(0), 68 | 'jit' => [ 69 | 'enabled' => false, 70 | 'buffer_size' => format_bytes(0), 71 | 'buffer_free' => format_bytes(0), 72 | ] 73 | ]; 74 | 75 | if (function_exists('opcache_get_status')) { 76 | $opcache = opcache_get_status(); 77 | $data['system']['opcache'] = [ 78 | 'opcache_enabled' => $opcache['opcache_enabled'], 79 | 'opcache_used_memory' => format_bytes($opcache['memory_usage']['used_memory']), 80 | 'opcache_free_memory' => format_bytes($opcache['memory_usage']['free_memory']), 81 | 'jit' => [ 82 | 'enabled' => $opcache['jit']['enabled'], 83 | 'buffer_size' => format_bytes($opcache['jit']['buffer_size']), 84 | 'buffer_free' => format_bytes($opcache['jit']['buffer_free']), 85 | ], 86 | ]; 87 | } 88 | 89 | $data['database'] = [ 90 | 'server_version' => null, 91 | 'client_version' => null, 92 | 'connection_status' => null, 93 | 'server_info' => null, 94 | 'error' => null, 95 | ]; 96 | 97 | if ( 98 | env('DB_DRIV') && 99 | env('DB_HOST') && 100 | env('DB_NAME') && 101 | env('DB_PORT') && 102 | env('DB_USER') 103 | ) { 104 | try { 105 | $database = DB::getInfoDriver(); 106 | $data['database'] = [ 107 | 'server_version' => $database['SERVER_VERSION'], 108 | 'client_version' => $database['CLIENT_VERSION'], 109 | 'connection_status' => $database['CONNECTION_STATUS'], 110 | 'server_info' => $database['SERVER_INFO'], 111 | 'error' => null, 112 | ]; 113 | 114 | $data['system']['execute_time'] = execute_time(); 115 | } catch (Exception $e) { 116 | $data['status'] = false; 117 | $data['database'] = [ 118 | 'server_version' => null, 119 | 'client_version' => null, 120 | 'connection_status' => null, 121 | 'server_info' => null, 122 | 'error' => $e->getMessage(), 123 | ]; 124 | 125 | return respond()->setContent(json($data, 500)); 126 | } 127 | } 128 | 129 | return respond()->setContent(json($data, 200)); 130 | } 131 | } 132 | --------------------------------------------------------------------------------