Dokumentasi Resmi & Panduan Rekayasa

Arsitektur & Referensi API OpenDrive

Panduan lengkap menyulap kapasitas 15 GB Google Drive menjadi storage bucket mandiri bebas batas payload 4.5 MB Vercel Serverless.

1. Pola Direct-to-Drive Resumable Upload

Vercel Serverless Function memiliki batas ukuran request body maksimum sebesar 4.5 MB dan batas waktu eksekusi 10 detik pada paket gratis (Hobby Plan). Jika klien mengirim berkas biner besar (misal: video 100 MB) melalui API route Vercel, serverless akan gagal dengan status HTTP 413 Payload Too Large.

Alur Orkestrasi OpenDrive:

  1. Browser mengirimkan metadata berkas (nama, ukuran, tipe MIME) ke endpoint Vercel.
  2. Vercel memvalidasi sesi Supabase JWT dan meminta Resumable Session URI ke Google Drive API via Service Account.
  3. Google Drive mengembalikan URL sesi sementara. Vercel meneruskan URL ini ke browser (waktu eksekusi ≤ 400 ms).
  4. Browser mengunggah berkas binary langsung ke Google Drive melalui HTTP PUT, menghitung progres via xhr.upload.onprogress.
  5. Setelah berhasil, browser mencatat relasi berkas ke basis data Supabase PostgreSQL yang terlindungi oleh RLS.

2. Contoh Kode Implementasi Unggah

Langkah 1: Inisiasi Tiket Resumable (/api/upload/init)
// Inisiasi sesi upload ke Vercel Serverless
const res = await fetch('/api/upload/init', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${supabaseAccessToken}`,
  },
  body: JSON.stringify({
    fileName: 'portofolio.pdf',
    mimeType: 'application/pdf',
    fileSize: 15728640, // 15 MB
    bucketId: '6c4b2679-b1d2-4328-86d1-4ad909ce9880',
  }),
});

const { uploadUrl } = await res.json();
// uploadUrl adalah Resumable Session URI Google Drive
Langkah 2: Direct Binary Stream ke Google Drive
// Unggah langsung file biner ke Google Drive via HTTP PUT
const xhr = new XMLHttpRequest();
xhr.open('PUT', uploadUrl);

xhr.upload.onprogress = (event) => {
  if (event.lengthComputable) {
    const percentage = Math.round((event.loaded / event.total) * 100);
    console.log(`Progres unggahan: ${percentage}%`);
  }
};

xhr.onload = () => {
  if (xhr.status === 200 || xhr.status === 201) {
    const response = JSON.parse(xhr.responseText);
    console.log('File ID Google Drive:', response.id);
  }
};

xhr.send(fileBlob);

3. Skema PostgreSQL & Kebijakan RLS

Jalankan skrip DDL berikut pada konsol SQL Editor Supabase untuk mengaktifkan partisi virtual bucket dan isolasi multi-tenant yang aman:

supabase_schema.sql
-- Skrip DDL Supabase PostgreSQL dengan Row Level Security
CREATE TABLE public.buckets (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    name VARCHAR(64) NOT NULL,
    is_public BOOLEAN DEFAULT false NOT NULL,
    created_at TIMESTAMPTZ DEFAULT TIMEZONE('utc'::text, NOW()) NOT NULL,
    CONSTRAINT unique_user_bucket_name UNIQUE (user_id, name)
);

ALTER TABLE public.buckets ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can manage own buckets"
    ON public.buckets FOR ALL
    USING (auth.uid() = user_id)
    WITH CHECK (auth.uid() = user_id);

4. Variabel Lingkungan (.env)

NEXT_PUBLIC_SUPABASE_URL: URL project Supabase Anda (dapat diakses dari browser).
NEXT_PUBLIC_SUPABASE_ANON_KEY: Kunci anonim publik Supabase (dibatasi oleh RLS).
GDRIVE_CLIENT_EMAIL: Email Service Account Google Cloud Console.
GDRIVE_PRIVATE_KEY: Private Key RSA Service Account (hanya di server Vercel, jangan pakai prefiks NEXT_PUBLIC_).

5. Panduan Konfigurasi Google Cloud & Service Account

Untuk mengizinkan OpenDrive mengunggah berkas ke Google Drive Anda secara terotentikasi:

1Buat Project di Google Cloud Console

Buka console.cloud.google.com, buat project baru (misal: opendrive-storage), lalu aktifkan Google Drive API v3 di menu APIs & Services > Library.

2Buat Service Account & Unduh Kunci JSON

Masuk ke menu IAM & Admin > Service Accounts. Buat Service Account baru, buat Private Key bertipe JSON, lalu salin client_email dan private_key ke variabel lingkungan Anda.

3Bagikan Folder Google Drive ke Email Service Account

Buka Google Drive pribadi Anda, buat folder khusus (misal: OpenDrive_Pool), lalu bagikan folder tersebut (Share) ke email Service Account dengan peran Editor.

6. Tabel Referensi Kode Error API & Penanganan

Daftar kode status HTTP yang mungkin dikembalikan oleh Route Handlers OpenDrive beserta panduan perbaikannya di sisi klien:

Status HTTPPenyebab ErrorTindakan Solusi di Klien
400 Bad RequestPayload tidak lengkap, nama berkas mengandung path traversal, atau ekstensi berbahaya ditolak.Pastikan file_name telah disanitasi, bucket_id valid, dan ekstensi bukan skrip terlarang (.html, .js, .exe).
401 UnauthorizedToken autentikasi Supabase JWT atau API Secret Key tidak disertakan atau telah kedaluwarsa.Sertakan header Authorization: Bearer <TOKEN> yang valid atau periksa status sesi pengguna.
403 ForbiddenKapasitas kuota akun habis atau pelanggaran Row Level Security (RLS) PostgreSQL.Periksa sisa kuota penyimpanan akun atau pastikan operasi dilakukan pada bucket milik sendiri.
413 Payload Too LargeUkuran berkas melebihi batas yang dikonfigurasikan pada pengaturan API Gateway (misal: > 50 MB di Free Tier).Sesuaikan slider batas ukuran file di menu API Gateway atau tingkatkan ke Developer Plan.
415 Unsupported Media TypeTipe MIME berkas tidak terdaftar di dalam Whitelist MIME API Settings.Centang tipe MIME yang bersangkutan di menu Pengaturan Gateway > Upload Rules.
500 Internal Server ErrorKoneksi ke Google Drive API gagal (kredensial Service Account tidak valid atau kuota Google Drive habis).Periksa variabel lingkungan GDRIVE_PRIVATE_KEY atau tautkan akun cadangan di Google Drive Pool.