├── .editorconfig ├── .env.example ├── .gitattributes ├── .gitignore ├── README.md ├── app ├── Controllers │ └── WelcomeController.php ├── Error │ └── Error.php ├── Kernel.php ├── Middleware │ ├── AuthMiddleware.php │ ├── CookieMiddleware.php │ ├── CorsMiddleware.php │ ├── CsrfMiddleware.php │ ├── GuestMiddleware.php │ ├── GzipMiddleware.php │ └── XSSMiddleware.php ├── Models │ └── User.php └── Providers │ ├── AppServiceProvider.php │ ├── EventServiceProvider.php │ ├── RouteServiceProvider.php │ └── TranslatorServiceProvide.php ├── cache ├── env │ └── .gitignore ├── log │ └── .gitignore ├── queue │ └── .gitignore ├── routes │ └── .gitignore └── views │ └── .gitignore ├── composer.json ├── database ├── generator │ └── generator.php └── schema │ └── 1653666213_users.php ├── package.json ├── public ├── .htaccess ├── css │ └── app.css ├── favicon.ico ├── index.php ├── js │ └── app.js ├── kamu.png └── robots.txt ├── resources ├── css │ └── app.css ├── js │ └── app.js ├── lang │ ├── en.php │ └── id.php └── views │ └── welcome.kita.php ├── routes ├── api.php └── routes.php ├── saya ├── shared └── .gitignore └── tailwind.config.js /.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 | -------------------------------------------------------------------------------- /.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 | COOKIE=true 9 | COOKIE_LIFETIME=120 10 | 11 | DB_DRIV=mysql 12 | DB_HOST=127.0.0.1 13 | DB_PORT=3306 14 | DB_NAME=kamu 15 | DB_USER=root 16 | DB_PASS= 17 | 18 | MAIL_HOST=smtp.gmail.com 19 | MAIL_PORT=587 20 | MAIL_ENCRYPTION=tcp 21 | MAIL_USERNAME= 22 | MAIL_PASSWORD= 23 | MAIL_FROM_ADDRESS= 24 | MAIL_FROM_NAME=kamu 25 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /cache/env/*.key 2 | /cache/log/*.key 3 | /cache/queue/*.key 4 | /cache/routes/*.key 5 | /cache/views/*.key 6 | /node_modules 7 | /shared/*.key 8 | /vendor 9 | .env 10 | npm-debug.log 11 | yarn-error.log 12 | .idea 13 | .vscode 14 | CODE_OF_CONDUCT.md 15 | SECURITY.md 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/Controllers/WelcomeController.php: -------------------------------------------------------------------------------- 1 | view('welcome', [ 13 | 'data' => 'PHP Framework' 14 | ]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Error/Error.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\XSSMiddleware::class, 61 | \App\Middleware\GzipMiddleware::class, 62 | ]; 63 | } 64 | 65 | /** 66 | * Registrasi service agar bisa dijalankan. 67 | * 68 | * @return array 69 | */ 70 | public function services(): array 71 | { 72 | return [ 73 | \App\Providers\AppServiceProvider::class, 74 | \App\Providers\RouteServiceProvider::class, 75 | \App\Providers\EventServiceProvider::class, 76 | \App\Providers\TranslatorServiceProvide::class, 77 | ]; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/Middleware/AuthMiddleware.php: -------------------------------------------------------------------------------- 1 | to('/login'); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /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/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 | $vary = $header->has('Vary') ? explode(', ', $header->get('Vary')) : []; 19 | $vary = array_unique([...$vary, 'Accept', 'Access-Control-Request-Method', 'Access-Control-Request-Headers', 'Origin']); 20 | $header->set('Vary', join(', ', $vary)); 21 | 22 | if (!$request->method(Request::OPTIONS)) { 23 | return $next($request); 24 | } 25 | 26 | $header->unset('Content-Type'); 27 | 28 | if (!$request->server->has('HTTP_ACCESS_CONTROL_REQUEST_METHOD')) { 29 | return respond()->setCode(Respond::HTTP_NO_CONTENT); 30 | } 31 | 32 | $header->set( 33 | 'Access-Control-Allow-Methods', 34 | strtoupper($request->server->get('HTTP_ACCESS_CONTROL_REQUEST_METHOD', $request->method())) 35 | ); 36 | 37 | $header->set('Access-Control-Allow-Headers', 'Accept, Authorization, Content-Type'); 38 | 39 | return respond()->setCode(Respond::HTTP_NO_CONTENT); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /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/Middleware/GuestMiddleware.php: -------------------------------------------------------------------------------- 1 | check()) { 14 | return $next($request); 15 | } 16 | 17 | return respond()->to('/'); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Middleware/GzipMiddleware.php: -------------------------------------------------------------------------------- 1 | getCode() < 400 && $response->getCode() >= 300) { 22 | return $response; 23 | } 24 | 25 | $response = respond()->transform($response); 26 | 27 | if (env('GZIP', 'true') != 'true') { 28 | return $response; 29 | } 30 | 31 | if (!str_contains($request->server->get('HTTP_ACCEPT_ENCODING', ''), 'gzip')) { 32 | return $response; 33 | } 34 | 35 | $compressed = gzencode($response->getContent(false), 3); 36 | 37 | if ($compressed === false) { 38 | return $response; 39 | } 40 | 41 | $response->setContent($compressed); 42 | 43 | $vary = $response->headers->has('Vary') ? explode(', ', $response->headers->get('Vary')) : []; 44 | $vary = array_unique([...$vary, 'Accept-Encoding']); 45 | 46 | $response->headers 47 | ->set('Vary', join(', ', $vary)) 48 | ->set('Content-Encoding', 'gzip'); 49 | 50 | return $response; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/Middleware/XSSMiddleware.php: -------------------------------------------------------------------------------- 1 | getHeader() 18 | ->set('Referrer-Policy', 'strict-origin-when-cross-origin') 19 | ->set('Content-Security-Policy', 'upgrade-insecure-requests') 20 | ->set('X-Content-Type-Options', 'nosniff') 21 | ->set('X-Frame-Options', 'SAMEORIGIN'); 22 | 23 | return $next($request); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Models/User.php: -------------------------------------------------------------------------------- 1 | fake()->name(), 31 | 'email' => fake()->email(), 32 | 'password' => Hash::make(fake()->text(8)), 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.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/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 | -------------------------------------------------------------------------------- /app/Providers/TranslatorServiceProvide.php: -------------------------------------------------------------------------------- 1 | 'User', 18 | 'email' => 'user@example.com', 19 | 'password' => Hash::make('12345678') 20 | ]); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npx tailwindcss -i ./resources/css/app.css -o ./public/css/app.css --watch", 5 | "build": "npx tailwindcss build -i ./resources/css/app.css -o ./public/css/app.css --minify" 6 | }, 7 | "devDependencies": { 8 | "tailwindcss": "^3.2.7" 9 | } 10 | } -------------------------------------------------------------------------------- /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 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^(.+)$ index.php/$1 [L] 21 | -------------------------------------------------------------------------------- /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)} -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dewanakl/kamu/8afcd4168aeb33aff5a9937b925d4f0f2baf8632/public/favicon.ico -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | run(); 23 | -------------------------------------------------------------------------------- /public/js/app.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', () => { 2 | const INFO = document.getElementById('information'); 3 | INFO.innerText = 'for educational purposes || ready for production'; 4 | }); -------------------------------------------------------------------------------- /public/kamu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dewanakl/kamu/8afcd4168aeb33aff5a9937b925d4f0f2baf8632/public/kamu.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /resources/css/app.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /resources/js/app.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dewanakl/kamu/8afcd4168aeb33aff5a9937b925d4f0f2baf8632/resources/js/app.js -------------------------------------------------------------------------------- /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 | 'uuid' => ':field is not a uuid!.', 40 | 'int' => ':field must be a number!.', 41 | 'float' => ':field must be decimal!.', 42 | 'min' => ':field minimum length: :attribute', 43 | 'max' => ':field maximum length: :attribute', 44 | 'sama' => ':field does not match with :attribute', 45 | 'unik' => ':field already exists!.', 46 | ], 47 | 48 | 'file' => [ 49 | 'required' => ':field is required!.', 50 | 'min' => ':field minimum length: :attribute', 51 | 'max' => ':field maximum length: :attribute', 52 | 'mimetypes' => ':field allowed: :attribute', 53 | 'mimes' => ':field allowed: :attribute', 54 | 'unsafe' => ':field is indicated as unsafe!.', 55 | 'corrupt' => ':field was not uploaded correctly!.', 56 | ], 57 | ] 58 | ]; 59 | -------------------------------------------------------------------------------- /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 | 'uuid' => ':field bukan uuid!.', 40 | 'int' => ':field harus angka!.', 41 | 'float' => ':field harus desimal!.', 42 | 'min' => ':field panjang minimal: :attribute', 43 | 'max' => ':field panjang maxsimal: :attribute', 44 | 'sama' => ':field tidak sama dengan :attribute', 45 | 'unik' => ':field sudah ada!.', 46 | ], 47 | 48 | 'file' => [ 49 | 'required' => ':field dibutuhkan!.', 50 | 'min' => ':field panjang minimal: :attribute', 51 | 'max' => ':field panjang maxsimal: :attribute', 52 | 'mimetypes' => ':field diperbolehkan: :attribute', 53 | 'mimes' => ':field diperbolehkan: :attribute', 54 | 'unsafe' => ':field terindikasi tidak aman!.', 55 | 'corrupt' => ':field tidak terupload dengan benar!.', 56 | ], 57 | ] 58 | ]; 59 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | run()); 24 | -------------------------------------------------------------------------------- /shared/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------