├── .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 |

2 |
3 |
4 |
5 |
6 |
7 |
8 |
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 |
--------------------------------------------------------------------------------