init push

This commit is contained in:
2026-07-16 22:16:45 +07:00
commit 8b068bdb10
1021 changed files with 332816 additions and 0 deletions

288
docs/file-manager-upload.md Normal file
View File

@@ -0,0 +1,288 @@
# File Manager
# Uploading New File
Sebelum hit API, FE ambil data per file:
- `name` (contoh: `spidey.png`)
- `content_type` (contoh: `image/png`)
- `size_bytes` (contoh: `42170`)
## Step 1 - FE minta upload intent ke BE, lalu upload langsung ke storage
## A. Minta Upload Intent ke Backend
### Endpoint
- `POST /api/v1/file-manager/files/upload`
### FE kirim request ini
- Single File
```json
{
"data": [
{
"type": "file_manager_file_upload_intent",
"attributes": {
"name": "image.png",
"content_type": "image/png",
"size_bytes": 123
}
}
]
}
```
- Bulk File
```json
{
"data": [
{
"type": "file_manager_file_upload_intent",
"attributes": {
"name": "image1.png",
"content_type": "image/png",
"size_bytes": 123
}
},
{
"type": "file_manager_file_upload_intent",
"attributes": {
"name": "image2.png",
"content_type": "image/png",
"size_bytes": 456
}
}
]
}
```
### Backend akan balas per file
- `upload_intent_uuid`
- `upload_url`
- `method` (`PUT`)
- `required_headers`
- `object.bucket`
- `object.key`
- `expires_at`
- `expires_in_seconds`
Contoh response:
```json
{
"data": [
{
"index": 0,
"success": true,
"resource": {
"type": "file_manager_file_upload_intent",
"id": "019d8215-c622-7576-86bd-3ddeecaf4867",
"attributes": {
"upload_intent_uuid": "019d8215-c622-7576-86bd-3ddeecaf4867",
"upload_url": "http://localhost:4566/...",
"method": "PUT",
"required_headers": {
"content-type": "image/png"
},
"object": {
"bucket": "wucher-file-dev",
"key": "fm/objects/files/2026/04/12/019d8215c6227a1aa20fc21f99f36584.png"
},
"file": {
"name": "spidey.png",
"mime_type": "image/png",
"size_bytes": 42170
},
"expires_at": "2026-04-12T14:40:58Z",
"expires_in_seconds": 899
}
}
}
],
"meta": {
"total": 1,
"success": 1,
"failed": 0,
"partial_success": false
}
}
```
## B. FE Handle langsung Upload Binary Langsung ke S3
Untuk setiap item `success: true` dari step 1:
1. Ambil `upload_url`
2. Ambil `method`
3. Ambil `required_headers` (jika ada)
4. Lakukan request upload file ke S3
Contoh yang akan dilakukan FE:
```js
await fetch(upload_url, {
method: method, // "PUT"
headers: { "Content-Type": file.type },
body: file,
});
```
atau pseudo
```js
const intents = await api.requestUploadIntents(files) // bulk
const readyToUpload = intents.data.filter(i => i.success)
const uploadResults = await parallelLimit(readyToUpload, 4, putToS3) // paralel
const succeeded = uploadResults.filter(r => r.success)
if (succeeded.length > 0) {
await api.createFilesBulk(succeeded.map(toCreatePayload))
}
```
Catatan penting:
- **1 file = 1 PUT ke S3**
- boleh paralel (disarankan pakai concurrency limit)
- file yang gagal PUT **jangan** dikirim ke step create
## Step 2 - Upload Cancel (opsional)
### Endpoint
- `DELETE /api/v1/file-manager/files/cancel-upload`
### FE kirim request ini
```json
{
"data": [
{
"type": "file_manager_file_cancel_upload",
"attributes": {
"upload_intent_uuid": "019d8215-c622-7576-86bd-3ddeecaf4867"
}
}
]
}
```
### Kapan dipakai
- user sudah request upload intent
- tapi user batal sebelum create
- FE bisa cancel upload intent supaya flow lebih bersih
### Contoh response
```json
{
"data": [
{
"index": 0,
"success": true,
"resource": {
"type": "file_manager_file_cancel_upload_result",
"id": "019d8215-c622-7576-86bd-3ddeecaf4867",
"attributes": {
"status": "canceled"
}
}
}
],
"meta": {
"total": 1,
"success": 1,
"failed": 0,
"partial_success": false
}
}
```
## Step 3 - FE Panggil Create ke Backend (Finalisasi)
Setelah PUT S3 sukses, FE gunakan:
### Endpoint
- `POST /api/v1/file-manager/files/create`
### FE kirim request ini
```json
{
"data": [
{
"type": "file_manager_file_create",
"attributes": {
"upload_intent_uuid": "019d8215-c622-7576-86bd-3ddeecaf4867",
"name": "spidey.png",
"folder_id": null
}
}
]
}
```
Aturan:
- `upload_intent_uuid`: wajib
- `name`: wajib
- `folder_id`: opsional (kalau mau dimasukkan ke folder)
- `null` atau tidak dikirim = root
## Step 4 - Process Create (BE)
Untuk setiap item:
1. Ambil upload intent dari `upload_intent_uuid`
2. Verify object benar-benar ada di storage
3. Verify metadata object (size/content type) sesuai intent
4. Simpan metadata file ke DB
5. Simpan outbox durable
6. Set status awal file menjadi `uploaded`
## Step 5 - Proses Async Lanjutan (Backend)
Setelah status `uploaded`, worker akan lanjut:
- `uploaded -> processing -> validated -> ready`
- atau `uploaded -> processing -> failed`
## Step 6 - FE Handle Response Create
Response create adalah bulk per item.
- Kalau semua sukses: HTTP `201`
- Kalau campuran sukses + gagal: HTTP `207` dengan `partial_success: true`
Contoh sukses:
```json
{
"data": [
{
"index": 0,
"success": true,
"message": "created",
"resource": {
"type": "file_manager_file",
"id": "019d628a-8d92-7949-b355-95de506da3b7",
"attributes": {
"folder_id": "019d4309-4dc8-78be-bb0c-3ebb8f3056ba",
"name": "spidey01.png",
"extension": "png",
"size_bytes": 42170,
"mime_type": "image/png",
"status": "uploaded",
"created_at": "2026-04-06T11:25:40Z",
"updated_at": "2026-04-06T11:25:40Z"
}
}
}
],
"meta": {
"total": 1,
"success": 1,
"failed": 0,
"partial_success": false
}
}
```