feat: start working on google drive storage

This commit is contained in:
charlesgauthereau
2026-01-24 00:26:05 +01:00
parent 797b287899
commit 657586ddff
18 changed files with 1038 additions and 7 deletions
@@ -0,0 +1,73 @@
// import {drive_v3, google} from "googleapis";
// import Drive = drive_v3.Drive;
// import {GoogleDriveConfig} from "@/features/storages/providers/google-drive/types";
//
//
// export async function getGoogleDriveClient(config: GoogleDriveConfig): Promise<Drive> {
// const auth = new google.auth.JWT({
// email: config.clientEmail,
// key: config.privateKey?.replace(/\\n/g, "\n"),
// scopes: ["https://www.googleapis.com/auth/drive"],
// });
//
// return google.drive({
// version: "v3",
// auth,
// });
// }
//
//
// export async function findFileByName(
// drive: any,
// name: string,
// folderId: string
// ): Promise<string | null> {
// const res = await drive.files.list({
// q: `name='${name}' and '${folderId}' in parents and trashed=false`,
// fields: "files(id)",
// pageSize: 1,
// });
//
// return res.data.files?.[0]?.id ?? null;
// }
import {drive_v3, google} from "googleapis";
import {GoogleDriveConfig} from "@/features/storages/providers/google-drive/types";
import Drive = drive_v3.Drive;
import {getServerUrl} from "@/utils/get-server-url";
export async function getGoogleDriveClient(config: GoogleDriveConfig): Promise<Drive> {
const baseUrl = getServerUrl();
const oauth2Client = new google.auth.OAuth2(
config.clientId,
config.clientSecret,
// config.redirectUri
baseUrl
);
oauth2Client.setCredentials({
refresh_token: config.refreshToken
});
return google.drive({
version: "v3",
auth: oauth2Client
});
}
export async function findFileByName(
drive: drive_v3.Drive,
name: string,
folderId: string
): Promise<string | null> {
const res = await drive.files.list({
q: `name='${name}' and '${folderId}' in parents and trashed=false`,
fields: "files(id)",
pageSize: 1,
supportsAllDrives: true,
includeItemsFromAllDrives: true,
});
return res.data.files?.[0]?.id ?? null;
}
@@ -0,0 +1,201 @@
"use server"
import {StorageDeleteInput, StorageGetInput, StorageResult, StorageUploadInput} from '../../types';
import {GoogleDriveConfig} from "@/features/storages/providers/google-drive/types";
import {findFileByName, getGoogleDriveClient} from "@/features/storages/providers/google-drive/helpers";
import {Readable} from "node:stream";
// export async function uploadGoogleDrive(
// config: GoogleDriveConfig,
// input: { data: StorageUploadInput }
// ): Promise<StorageResult> {
// const client = await getGoogleDriveClient(config);
//
// const name = input.data.path;
//
// const existing = await findFileByName(client, name, config.folderId);
// if (existing) {
// return {
// success: false,
// provider: "google-drive",
// error: "File already exists"
// };
// }
//
// await client.files.create({
// requestBody: {
// name,
// parents: [config.folderId],
// },
// media: {
// body: input.data.file as Buffer,
// },
// });
//
//
// return {
// success: true,
// provider: 'google-drive',
// };
// }
//
// export async function getGoogleDrive(
// config: GoogleDriveConfig,
// input: { data: StorageGetInput }
// ): Promise<StorageResult> {
// const client = await getGoogleDriveClient(config);
// const name = input.data.path;
//
// const fileId = await findFileByName(client, name, config.folderId);
// if (!fileId) {
// return {success: false, provider: "google-drive", error: "File not found"};
// }
//
// const res = await client.files.get(
// {fileId, alt: "media"},
// {responseType: "arraybuffer"}
// );
//
// return {
// success: true,
// provider: "google-drive",
// file: Buffer.from(res.data as ArrayBuffer),
// };
// }
//
//
// export async function deleteGoogleDrive(
// config: GoogleDriveConfig,
// input: { data: StorageDeleteInput }
// ): Promise<StorageResult> {
// const client = await getGoogleDriveClient(config);
// const name = input.data.path;
//
// const fileId = await findFileByName(client, name, config.folderId);
// if (!fileId) {
// return {success: false, provider: "google-drive", error: "File not found"};
// }
//
// await client.files.delete({fileId});
//
// return {
// success: true,
// provider: "google-drive"
// };
// }
//
//
// export async function pingGoogleDrive(config: GoogleDriveConfig): Promise<StorageResult> {
// try {
// const drive = await getGoogleDriveClient(config);
// const name = `ping-${Date.now()}.txt`;
//
// const buffer = Buffer.from("ping");
//
// const file = await drive.files.create({
// requestBody: {
// name,
// parents: [config.folderId],
// },
// media: {
// mimeType: "text/plain",
// body: Readable.from(buffer),
// },
// fields: "id",
// });
// console.log(file)
//
// await drive.files.get({fileId: file.data.id!});
// await drive.files.delete({fileId: file.data.id!});
//
// return {
// success: true,
// provider: "google-drive",
// response: "Google Drive storage OK",
// };
// } catch (err: any) {
// return {
// success: false,
// provider: "google-drive",
// response: err.message,
// };
// }
// }
export async function uploadGoogleDrive(
config: GoogleDriveConfig,
input: { data: StorageUploadInput }
): Promise<StorageResult> {
const client = await getGoogleDriveClient(config);
const name = input.data.path;
const existing = await findFileByName(client, name, config.folderId);
if (existing) return {success: false, provider: "google-drive", error: "File already exists"};
await client.files.create({
requestBody: {name, parents: [config.folderId]},
media: {body: Readable.from(input.data.file as Buffer)},
fields: "id",
supportsAllDrives: true,
});
return {success: true, provider: 'google-drive'};
}
export async function getGoogleDrive(
config: GoogleDriveConfig,
input: { data: StorageGetInput }
): Promise<StorageResult> {
const client = await getGoogleDriveClient(config);
const name = input.data.path;
const fileId = await findFileByName(client, name, config.folderId);
if (!fileId) return {success: false, provider: "google-drive", error: "File not found"};
const res = await client.files.get(
{fileId, alt: "media", supportsAllDrives: true},
{responseType: "arraybuffer"}
);
return {
success: true,
provider: "google-drive",
file: Buffer.from(res.data as ArrayBuffer),
};
}
export async function deleteGoogleDrive(
config: GoogleDriveConfig,
input: { data: StorageDeleteInput }
): Promise<StorageResult> {
const client = await getGoogleDriveClient(config);
const name = input.data.path;
const fileId = await findFileByName(client, name, config.folderId);
if (!fileId) return {success: false, provider: "google-drive", error: "File not found"};
await client.files.delete({fileId, supportsAllDrives: true});
return {success: true, provider: "google-drive"};
}
export async function pingGoogleDrive(config: GoogleDriveConfig): Promise<StorageResult> {
try {
const drive = await getGoogleDriveClient(config);
const name = `ping-${Date.now()}.txt`;
const buffer = Buffer.from("ping");
const file = await drive.files.create({
requestBody: {name, parents: [config.folderId]},
media: {mimeType: "text/plain", body: Readable.from(buffer)},
fields: "id",
supportsAllDrives: true,
});
await drive.files.get({fileId: file.data.id!, supportsAllDrives: true});
// await drive.files.delete({fileId: file.data.id!, supportsAllDrives: true});
return {success: true, provider: "google-drive", response: "Google Drive storage OK"};
} catch (err: any) {
return {success: false, provider: "google-drive", response: err.message};
}
}
@@ -0,0 +1,15 @@
// export type GoogleDriveConfig = {
// clientEmail: string;
// privateKey: string;
// folderId: string;
// };
export type GoogleDriveConfig = {
clientId: string;
clientSecret: string;
refreshToken: string; // from OAuth flow
// redirectUri: string; // e.g., http://localhost:3000/oauth2callback
folderId: string; // target folder in your Drive
};
+12
View File
@@ -6,6 +6,12 @@ import type {
import {uploadLocal, getLocal, deleteLocal, pingLocal} from './local';
import {deleteS3, getS3, pingS3, uploadS3} from "@/features/storages/providers/s3";
import {
deleteGoogleDrive,
getGoogleDrive,
pingGoogleDrive,
uploadGoogleDrive
} from "@/features/storages/providers/google-drive";
type ProviderHandler = {
upload: (config: any, input: StorageInput & { action: 'upload' }) => Promise<StorageResult>;
@@ -27,6 +33,12 @@ const handlers: Record<StorageProviderKind, ProviderHandler> = {
delete: deleteS3,
ping: pingS3,
},
"google-drive": {
upload: uploadGoogleDrive,
get: getGoogleDrive,
delete: deleteGoogleDrive,
ping: pingGoogleDrive,
}
// gcs: null as any,
// azure: null as any,
};
+1
View File
@@ -1,6 +1,7 @@
export type StorageProviderKind =
| 'local'
| 's3'
| 'google-drive'
;
export type StorageAction =