Google Drive
Google Drive
Just need ad-hoc uploads? Wrap this adapter in the
Filesfacade for a one-liner API. The reference below shows direct adapter usage, OAuth wiring, and Drive-specific key resolution.
Overview
The Google Drive adapter routes virtual keys onto fileIds by stamping every upload with an appProperties.fsdkKey marker. An LRU cache amortizes the resolve cost. Drive isn't a key-value store, so a virtual key like "docs/report.pdf" can technically map to multiple Drive files — the adapter throws if files.list returns more than one match, and call sites can drop to storage.raw to disambiguate.
Installation
npm install @googleapis/drive google-auth-libraryyarn add @googleapis/drive google-auth-librarypnpm add @googleapis/drive google-auth-libraryUsage
import GoogleDriveStorage from "@visulima/storage/provider/google-drive";
const storage = new GoogleDriveStorage({
credentials: {
client_email: process.env.GOOGLE_DRIVE_CLIENT_EMAIL!,
private_key: process.env.GOOGLE_DRIVE_PRIVATE_KEY!,
},
driveId: process.env.GOOGLE_DRIVE_ID, // Shared Drive id
rootFolderId: process.env.GOOGLE_DRIVE_ROOT_FOLDER_ID,
});Configuration
Auth precedence
client— pre-builtdrive_v3.Driveinstance.credentials— inline service-account credentials (client_email+private_key).keyFilename— path to a service-account JSON file.oauth— 3-legged refresh token (clientId+clientSecret+refreshToken).- Env fallbacks:
GOOGLE_DRIVE_CLIENT_EMAIL+GOOGLE_DRIVE_PRIVATE_KEY, orGOOGLE_DRIVE_KEY_FILE.
GOOGLE_DRIVE_SUBJECT enables domain-wide delegation for service-account auth shapes.
Shared Drive
Service accounts have a 15 GB personal quota. Production workloads should target a Shared Drive with the service account added as a member:
const storage = new GoogleDriveStorage({
keyFilename: "/etc/secrets/sa.json",
driveId: "0AAbCdEfG...",
rootFolderId: "0AAbCdEfG...", // typically the same as driveId
});OAuth (end-user Drive)
const storage = new GoogleDriveStorage({
oauth: {
clientId: process.env.GOOGLE_OAUTH_CLIENT_ID!,
clientSecret: process.env.GOOGLE_OAUTH_CLIENT_SECRET!,
refreshToken: process.env.GOOGLE_DRIVE_REFRESH_TOKEN!,
},
});The google-auth-library OAuth2Client handles refresh natively — no per-request token plumbing in the adapter.
Public reads
const storage = new GoogleDriveStorage({
credentials: {
/* … */
},
publicByDefault: true,
});
const url = await storage.getReadUrl("file.mp4");
// → https://drive.google.com/uc?export=download&id=<fileId>When publicByDefault is set, every write() also creates an "anyone with link, reader" permission.
URL Generation
getReadUrl(key, options?)
Requires publicByDefault: true — Drive has no signed-URL primitive. Returns the canonical https://drive.google.com/uc?export=download&id=<fileId> URL. responseContentDisposition is not supported.
getUploadUrl(key, options?)
Returns a resumable-upload session URL (https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable). Requires credentials, keyFilename, or oauth — the pre-built client escape hatch throws because the adapter can't recover the underlying auth handle to mint tokens.
Features
- Virtual-key routing — uploads stamp
appProperties.fsdkKey; reads resolve viafiles.list, cached in an LRU. - Shared-Drive aware — sets
supportsAllDrives/includeItemsFromAllDriveson every request. - Domain-wide delegation — pass
subject(orGOOGLE_DRIVE_SUBJECT) to impersonate a workspace user. - Resumable uploads —
getUploadUrlinitiates a session that the caller can drive directly from a browser.
Limitations
getReadUrl()throwsMETHOD_NOT_ALLOWEDwithoutpublicByDefault: true. Useget()for private files.- Single-shot writes via
write(); for large files usegetUploadUrl()and stream against the session URL. - Duplicate virtual keys (same
fsdkKeyon multiple Drive files) causeresolveto throw — surface viastorage.rawand reconcile manually.