UNPKG

@accounter/server

Version:
99 lines (81 loc) 3.27 kB
import { Inject, Injectable, Scope } from 'graphql-modules'; import { ENVIRONMENT } from '../../../shared/tokens.js'; import type { Environment } from '../../../shared/types/index.js'; import { folderContentSchema, type DriveFileContent, type DriveFolderContent, } from './types/folder-content.js'; @Injectable({ scope: Scope.Singleton, global: true, }) export class GoogleDriveProvider { private apiKey: string; constructor(@Inject(ENVIRONMENT) private env: Environment) { this.apiKey = this.env.googleDrive?.driveApiKey ?? ''; } private async fetchFolderContent(folderUrl: string): Promise<DriveFolderContent> { const mainUrl = folderUrl.split('?')[0]; const folderId = mainUrl.split('folders/')[1]; if (!folderId) { throw new Error('Invalid Google Drive URL'); } const url = new URL( `https://www.googleapis.com/drive/v3/files?q='${folderId}'+in+parents&key=${this.apiKey}`, ); const res = await fetch(url).catch(err => { const message = `Failed fetching data from Google Drive for URL="${folderUrl}"`; console.error(`${message}: ${err}`); throw new Error(message); }); const jsonResponse = await res.json().catch(err => { const message = `Failed parsing response from Google Drive`; console.error(`${message}: ${err}`); throw new Error(message); }); const parsedResponse = folderContentSchema.safeParse(jsonResponse); if (!parsedResponse.success) { const message = `Failed to parse response from Google Drive`; console.error(message, parsedResponse.error); throw new Error(message); } return parsedResponse.data; } private async fetchFile(fileInfo: DriveFileContent): Promise<File> { const fileId = fileInfo.id; const url = new URL(`https://drive.google.com/uc?export=download&id=${fileId}`); // fetch file const response = await fetch(url).catch(err => { const message = `Failed fetching file from Google Drive for file="${fileInfo.name}"`; console.error(`${message}: ${err}`); throw new Error(message); }); const buffer = await response.arrayBuffer().catch(err => { const message = `Failed parsing file from Google Drive for file="${fileInfo.name}"`; console.error(`${message}: ${err}`); throw new Error(message); }); const file = new File([buffer], fileInfo.name, { type: fileInfo.mimeType }); return file; } private isRelevantFileType(originalMimeType: string): boolean { const mimeType = originalMimeType.toLowerCase(); return mimeType === 'application/pdf' || mimeType.startsWith('image/'); } public async fetchFilesFromSharedFolder(folderUrl: string): Promise<File[]> { try { const folderData = await this.fetchFolderContent(folderUrl); const relevantFiles = folderData.files.filter(file => this.isRelevantFileType(file.mimeType)); if (!relevantFiles.length) { return []; } const files = await Promise.all(relevantFiles.map(fileInfo => this.fetchFile(fileInfo))); return files; } catch (e) { const message = `Failed fetching files from Google Drive`; console.error(`${message}: ${e}`); throw new Error(message, { cause: e }); } } }