base-api-scramble-mcp 1.0.0

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.
@@ -0,0 +1,423 @@
1
+ # Starting Point - Base API Scramble
2
+
3
+ > Kickoff guide untuk clone base project dan memulai development baru.
4
+ > Optimized agar AI (Claude, Cursor, dll) langsung paham arsitektur dan konvensi project.
5
+
6
+ ---
7
+
8
+ ## Quick Start (5 Menit)
9
+
10
+ ```bash
11
+ # 1. Clone & masuk
12
+ git clone <repo-url> nama-project
13
+ cd nama-project
14
+
15
+ # 2. Install dependencies
16
+ composer install
17
+
18
+ # 3. Setup environment
19
+ cp .env.example .env
20
+ php artisan key:generate
21
+
22
+ # 4. Konfigurasi database di .env
23
+ DB_CONNECTION=mysql
24
+ DB_HOST=127.0.0.1
25
+ DB_PORT=3306
26
+ DB_DATABASE=nama_database
27
+ DB_USERNAME=root
28
+ DB_PASSWORD=
29
+
30
+ # 5. Migrasi & seed
31
+ php artisan migrate
32
+ php artisan db:seed
33
+
34
+ # 6. Jalankan server
35
+ php artisan serve
36
+ ```
37
+
38
+ **Default Login:**
39
+ | Email | Password |
40
+ |---|---|
41
+ | `admin@gmail.com` | `password` |
42
+ | `dev@gotrasoft.com` | `gotradev` |
43
+
44
+ **Base URL:** `http://localhost:8000/api/v1`
45
+ **API Docs:** `http://localhost:8000/docs/api` (Scramble)
46
+
47
+ ---
48
+
49
+ ## Tech Stack
50
+
51
+ | Komponen | Package | Versi |
52
+ |---|---|---|
53
+ | Framework | Laravel | ^10.10 |
54
+ | PHP | | ^8.1 |
55
+ | Auth | Laravel Sanctum | ^3.3 |
56
+ | API Docs | Scramble (auto-docs) | ^1.0 |
57
+ | Query Builder | Spatie Query Builder | ^6.3 |
58
+ | Role & Permission | Spatie Permission | ^6.13 |
59
+ | Activity Log | Spatie Activity Log | ^4.9 |
60
+ | Excel Export | PhpSpreadsheet | ^5.4 |
61
+
62
+ ---
63
+
64
+ ## Arsitektur & Pola Utama
65
+
66
+ ### Flow Request
67
+
68
+ ```
69
+ Request → Route → FormRequest (validasi) → Controller → Query/Model → Response (ApiResponse trait)
70
+ ```
71
+
72
+ ### Struktur Direktori Penting
73
+
74
+ ```
75
+ app/
76
+ ├── Console/Commands/
77
+ │ ├── GC.php # CRUD Generator (artisan gc)
78
+ │ └── GCFromMigration.php # Generate dari migration existing
79
+ ├── Exports/ # Excel export system
80
+ │ ├── BaseExport.php # Abstract base export
81
+ │ └── ...DataProvider.php # Interface-based data providers
82
+ ├── Helpers/
83
+ │ ├── ApiResponse.php # Trait: responseSuccess/Data/Created/Deleted/Error
84
+ │ └── FileManagerHelper.php # File management utilities
85
+ ├── Http/
86
+ │ ├── Controllers/Api/V1/ # Semua controller API v1
87
+ │ ├── Middleware/ # Standard Laravel middleware
88
+ │ └── Requests/Api/V1/ # Form Request validasi per-endpoint
89
+ ├── Models/ # Eloquent models (semua pakai UUID + Queryable trait)
90
+ ├── Observers/ # Activity log observers (User, Role, Permission)
91
+ ├── Queries/ # Query classes (Spatie QueryBuilder)
92
+ ├── Services/ # Business logic (FileService, Payment gateways)
93
+ └── Traits/
94
+ └── Queryable.php # Trait utama: filter, sort, search, include
95
+
96
+ routes/
97
+ ├── api.php # Base API routing
98
+ └── api_v1.php # Semua route v1 (prefix /api/v1)
99
+
100
+ config/
101
+ ├── export_info.php # Custom: konfigurasi Excel export
102
+ ├── services.php # Payment gateway credentials (Midtrans, Xendit, PayPal, Doku)
103
+ └── ... # Standard Laravel configs
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Konvensi & Pattern Wajib
109
+
110
+ ### 1. Model
111
+
112
+ Semua model **WAJIB** menggunakan:
113
+ - `HasUuids` trait (UUID sebagai primary key, BUKAN auto-increment)
114
+ - `Queryable` trait (integrasi Spatie QueryBuilder)
115
+
116
+ ```php
117
+ use App\Traits\Queryable;
118
+ use Illuminate\Database\Eloquent\Concerns\HasUuids;
119
+
120
+ class NamaModel extends Model
121
+ {
122
+ use HasFactory, HasUuids, Queryable;
123
+
124
+ protected $fillable = ['field1', 'field2'];
125
+
126
+ // Opsional: kolom yang bisa di-search via ?search=keyword
127
+ protected $searchable = ['field1', 'field2'];
128
+
129
+ // Opsional: relasi yang bisa di-include via ?include=relation
130
+ protected $relationIncludes = ['relation1', 'relation2'];
131
+ }
132
+ ```
133
+
134
+ ### 2. Migration
135
+
136
+ Semua migration menggunakan **UUID primary key**:
137
+
138
+ ```php
139
+ Schema::create('table_name', function (Blueprint $table) {
140
+ $table->uuid('id')->primary();
141
+ // ... kolom lain
142
+ $table->foreignUuid('parent_id')->constrained('parents')->cascadeOnDelete(); // foreign key
143
+ $table->timestamps();
144
+ });
145
+ ```
146
+
147
+ ### 3. Query Class
148
+
149
+ Setiap model punya Query class di `app/Queries/`:
150
+
151
+ ```php
152
+ namespace App\Queries;
153
+
154
+ use App\Models\NamaModel;
155
+ use Spatie\QueryBuilder\AllowedFilter;
156
+ use Spatie\QueryBuilder\AllowedInclude;
157
+ use Spatie\QueryBuilder\QueryBuilder;
158
+
159
+ class NamaModelQuery extends QueryBuilder
160
+ {
161
+ public function __construct()
162
+ {
163
+ parent::__construct(NamaModel::query());
164
+
165
+ $this
166
+ ->allowedIncludes([
167
+ AllowedInclude::relationship('relation1'),
168
+ ])
169
+ ->allowedFilters([
170
+ AllowedFilter::exact('id'),
171
+ AllowedFilter::partial('name'),
172
+ AllowedFilter::exact('foreign_id'),
173
+ ]);
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### 4. Controller
179
+
180
+ Extends `Controller` (sudah include `ApiResponse` trait + `baseQuery()` method):
181
+
182
+ ```php
183
+ namespace App\Http\Controllers\Api\V1;
184
+
185
+ use App\Http\Controllers\Controller;
186
+ use App\Models\NamaModel;
187
+ use App\Queries\NamaModelQuery;
188
+ use App\Http\Requests\Api\V1\IndexRequest;
189
+ use App\Http\Requests\Api\V1\NamaModelStoreRequest;
190
+ use App\Http\Requests\Api\V1\NamaModelUpdateRequest;
191
+
192
+ class NamaModelController extends Controller
193
+ {
194
+ public function index(IndexRequest $request)
195
+ {
196
+ $query = new NamaModelQuery();
197
+ return $this->responseData($this->baseQuery($query, $request), 'NamaModel retrieved successfully');
198
+ }
199
+
200
+ public function show(string $id)
201
+ {
202
+ $query = new NamaModelQuery();
203
+ return $this->responseSuccess($query->findOrFail($id), 'NamaModel retrieved successfully');
204
+ }
205
+
206
+ public function store(NamaModelStoreRequest $request)
207
+ {
208
+ $data = $request->validated();
209
+ $model = NamaModel::create($data);
210
+ return $this->responseSuccess($model, 'NamaModel created successfully', 201);
211
+ }
212
+
213
+ public function update(NamaModelUpdateRequest $request, NamaModel $namaModel)
214
+ {
215
+ $data = array_filter($request->validated(), fn($v) => $v !== null);
216
+ $namaModel->update($data);
217
+ return $this->responseSuccess($namaModel, 'NamaModel updated successfully');
218
+ }
219
+
220
+ public function destroy(NamaModel $namaModel)
221
+ {
222
+ $namaModel->delete();
223
+ return $this->responseSuccess(null, 'NamaModel deleted successfully');
224
+ }
225
+ }
226
+ ```
227
+
228
+ ### 5. Form Request
229
+
230
+ ```php
231
+ namespace App\Http\Requests\Api\V1;
232
+
233
+ use Illuminate\Foundation\Http\FormRequest;
234
+
235
+ class NamaModelStoreRequest extends FormRequest
236
+ {
237
+ public function authorize(): bool
238
+ {
239
+ return true;
240
+ }
241
+
242
+ public function rules(): array
243
+ {
244
+ return [
245
+ /** @example John Doe */
246
+ 'name' => 'required|string|max:255',
247
+ /** @example john@example.com */
248
+ 'email' => 'required|email|unique:App\Models\NamaModel,email',
249
+ ];
250
+ }
251
+ }
252
+ ```
253
+
254
+ > Gunakan PHPDoc `@example` pada setiap rule agar Scramble auto-generate contoh di API docs.
255
+
256
+ ### 6. Route
257
+
258
+ Tambahkan di `routes/api_v1.php` di dalam group `auth:sanctum`:
259
+
260
+ ```php
261
+ Route::apiResource('nama-model', Controllers\NamaModelController::class);
262
+ ```
263
+
264
+ ### 7. API Response Format
265
+
266
+ Semua response menggunakan format konsisten via `ApiResponse` trait:
267
+
268
+ **Success:**
269
+ ```json
270
+ { "success": true, "message": "...", "code": 200, "data": { } }
271
+ ```
272
+
273
+ **Paginated:**
274
+ ```json
275
+ { "success": true, "message": "...", "code": 200, "data": [], "pagination": { "current_page": 1, "total": 50, "per_page": 10, "last_page": 5, "..." : "..." } }
276
+ ```
277
+
278
+ **Error:**
279
+ ```json
280
+ { "success": false, "message": "...", "code": 400 }
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Query Parameters (Built-in)
286
+
287
+ Semua endpoint `index` otomatis support:
288
+
289
+ | Parameter | Contoh | Keterangan |
290
+ |---|---|---|
291
+ | `search` | `?search=keyword` | Full-text search di kolom `$searchable` |
292
+ | `filter` | `?filter[name]=john&filter[status]=active` | Filter per kolom |
293
+ | `sort_by` | `?sort_by=name&sort_order=asc` | Sorting (default: `created_at` desc) |
294
+ | `include` | `?include=roles,permissions` | Eager load relasi |
295
+ | `paginate` | `?paginate=20&page=2` | Pagination (default: 10) |
296
+ | `paginate=false` | `?paginate=false` | Ambil semua tanpa pagination |
297
+ | `first` | `?first=true` | Ambil hanya 1 data pertama |
298
+
299
+ ---
300
+
301
+ ## CRUD Generator (Artisan GC)
302
+
303
+ Generate module lengkap (Migration + Model + Query + Controller + Requests + Route) dalam 1 command:
304
+
305
+ ```bash
306
+ # Basic
307
+ php artisan gc Product --fields="name:string,price:decimal,description:text"
308
+
309
+ # Dengan relasi
310
+ php artisan gc Product --fields="name:string,price:decimal,image:file" --belongsTo="Category,User" --hasMany="Review"
311
+
312
+ # Preview dulu sebelum generate
313
+ php artisan gc Product --fields="name:string,price:decimal" --preview
314
+
315
+ # Lihat migration text saja
316
+ php artisan gc Product --fields="name:string,price:decimal" --migration
317
+ ```
318
+
319
+ **Field types:** `string`, `text`, `integer`/`int`, `decimal`/`float`, `boolean`/`bool`, `date`, `datetime`, `file`/`image`
320
+
321
+ **Setelah generate:**
322
+ ```bash
323
+ php artisan migrate
324
+ ```
325
+
326
+ ### Generate dari Migration Existing
327
+
328
+ ```bash
329
+ php artisan gc:from-migration
330
+ ```
331
+
332
+ ---
333
+
334
+ ## Fitur Bawaan yang Sudah Tersedia
335
+
336
+ ### Authentication (Sanctum)
337
+ - `POST /api/v1/login` - Login, dapat token
338
+ - `POST /api/v1/logout` - Logout (auth required)
339
+ - `GET /api/v1/me` - Profile user login
340
+ - `PUT /api/v1/me` - Update profile
341
+ - `PUT /api/v1/change-password` - Ganti password
342
+
343
+ ### Role & Permission (Spatie)
344
+ - CRUD Role: `/api/v1/role`
345
+ - CRUD Permission: `/api/v1/permission`
346
+ - Assign: `/api/v1/user-role/attach`, `detach`, `sync-roles`, `sync-users`
347
+ - Assign: `/api/v1/role-permission/attach`, `detach`, `sync-permissions`, `sync-roles`
348
+
349
+ ### File Management
350
+ - CRUD File & Folder dengan soft-delete, restore, force-delete
351
+ - Upload dengan auto-compression (Imagick)
352
+ - Support S3 dan local disk
353
+
354
+ ### Excel Export
355
+ - Flexible, Multi-Sheet, Multi-Table template
356
+ - Data Provider pattern (interface-based)
357
+ - Custom styling via `config/export_info.php`
358
+
359
+ ### Activity Log
360
+ - Auto-log perubahan via Observers (User, Role, Permission)
361
+ - `GET /api/v1/log-activity` - Lihat semua log
362
+
363
+ ### Payment Gateways
364
+ - Midtrans, Xendit, PayPal, Doku (service classes tersedia di `app/Services/`)
365
+
366
+ ---
367
+
368
+ ## Langkah Memulai Project Baru
369
+
370
+ ### Checklist Setup
371
+
372
+ 1. **Clone & install** (lihat Quick Start di atas)
373
+ 2. **Update `.env`:**
374
+ - `APP_NAME` - Nama project
375
+ - `APP_URL` - URL production
376
+ - `DB_DATABASE` - Nama database
377
+ 3. **Hapus module contoh** (opsional):
378
+ - Hapus migration, model, controller, query, request untuk: `Post`, `Label`, `Folder`, `File` jika tidak dibutuhkan
379
+ 4. **Buat module baru** via `php artisan gc NamaModule --fields="..."`
380
+ 5. **Jalankan** `php artisan migrate`
381
+ 6. **Test** via Scramble docs di `/docs/api`
382
+
383
+ ### Instruksi untuk AI
384
+
385
+ Saat meminta AI membuat fitur baru, gunakan prompt seperti ini:
386
+
387
+ ```
388
+ Buatkan module [NamaModule] dengan fields: [daftar fields].
389
+ Ikuti pattern yang ada di project ini:
390
+ - Model: UUID + Queryable trait
391
+ - Query class di app/Queries/
392
+ - Controller extends Controller (gunakan baseQuery + ApiResponse)
393
+ - FormRequest dengan @example untuk Scramble docs
394
+ - Route di routes/api_v1.php dalam group auth:sanctum
395
+ - Migration dengan uuid('id')->primary()
396
+ ```
397
+
398
+ Atau lebih simpel, gunakan artisan gc dulu lalu minta AI untuk menyesuaikan:
399
+
400
+ ```
401
+ Jalankan: php artisan gc Product --fields="name:string,price:decimal" --belongsTo="Category"
402
+ Lalu sesuaikan validasi dan business logic-nya.
403
+ ```
404
+
405
+ ---
406
+
407
+ ## Referensi File Penting
408
+
409
+ | Kebutuhan | File |
410
+ |---|---|
411
+ | Response format | `app/Helpers/ApiResponse.php` |
412
+ | Base controller | `app/Http/Controllers/Controller.php` |
413
+ | Queryable trait | `app/Traits/Queryable.php` |
414
+ | Contoh controller | `app/Http/Controllers/Api/V1/UserController.php` |
415
+ | Contoh query | `app/Queries/UserQuery.php` |
416
+ | Contoh model | `app/Models/User.php` |
417
+ | Contoh request | `app/Http/Requests/Api/V1/UserStoreRequest.php` |
418
+ | Route API v1 | `routes/api_v1.php` |
419
+ | CRUD generator | `app/Console/Commands/GC.php` |
420
+ | File upload service | `app/Services/FileService.php` |
421
+ | Excel export service | `app/Services/ExcelExportService.php` |
422
+ | Export config | `config/export_info.php` |
423
+ | Payment services | `app/Services/{Midtrans,Xendit,PayPal,Doku}/` |