{"version":3,"sources":["../../../src/storage/providers/google-drive.ts"],"sourcesContent":["/**\n * Google Drive Storage Provider for Vana SDK\n *\n * Implements storage interface for Google Drive using OAuth2 authentication.\n * Based on patterns from dlp-ui-template with NextAuth integration.\n */\n\nimport {\n  StorageError,\n  type StorageProvider,\n  type StorageUploadResult,\n  type StorageFile,\n  type StorageListOptions,\n  type StorageProviderConfig,\n} from \"../index\";\n\nexport interface GoogleDriveConfig {\n  /** OAuth2 access token */\n  accessToken: string;\n  /** Optional refresh token for token renewal */\n  refreshToken?: string;\n  /** OAuth2 client ID */\n  clientId?: string;\n  /** OAuth2 client secret */\n  clientSecret?: string;\n  /** Parent folder ID to upload files to */\n  folderId?: string;\n}\n\ninterface GoogleDriveFile {\n  id: string;\n  name: string;\n  webViewLink: string;\n  size: string;\n  mimeType: string;\n  createdTime: string;\n}\n\ninterface GoogleDriveUploadResponse {\n  id: string;\n  name: string;\n}\n\ninterface GoogleDriveListResponse {\n  files: GoogleDriveFile[];\n}\n\ninterface GoogleDriveTokenResponse {\n  access_token: string;\n}\n\n/**\n * Google Drive Storage Provider with folder management capabilities\n *\n * @remarks\n * Implements storage interface for Google Drive using OAuth2 authentication.\n * Provides file upload/download operations and advanced folder management\n * including search, creation, and nested folder structures. Requires the\n * `https://www.googleapis.com/auth/drive.file` OAuth scope for full functionality.\n *\n * @category Storage\n *\n * @example\n * ```typescript\n * const googleDriveStorage = new GoogleDriveStorage({\n *   accessToken: \"your-oauth-access-token\",\n *   refreshToken: \"your-oauth-refresh-token\",\n *   clientId: \"your-oauth-client-id\",\n *   clientSecret: \"your-oauth-client-secret\",\n * });\n *\n * // Create folder structure and upload file\n * const folderId = await googleDriveStorage.findOrCreateFolder(\"screenshots\");\n * const result = await googleDriveStorage.upload(fileBlob, \"image.png\");\n * ```\n */\nexport class GoogleDriveStorage implements StorageProvider {\n  private readonly baseUrl = \"https://www.googleapis.com/drive/v3\";\n  private readonly uploadUrl = \"https://www.googleapis.com/upload/drive/v3\";\n\n  constructor(private config: GoogleDriveConfig) {\n    if (!config.accessToken) {\n      throw new StorageError(\n        \"Google Drive access token is required\",\n        \"MISSING_ACCESS_TOKEN\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  async upload(file: Blob, filename?: string): Promise<StorageUploadResult> {\n    try {\n      const fileName = filename ?? `vana-file-${Date.now()}.dat`;\n\n      // Create file metadata\n      const metadata = {\n        name: fileName,\n        parents: this.config.folderId ? [this.config.folderId] : undefined,\n      };\n\n      // Create multipart upload request\n      const delimiter = \"-------314159265358979323846\";\n      const closeDelim = `\\r\\n--${delimiter}--`;\n\n      const metadataBlob = new Blob([JSON.stringify(metadata)], {\n        type: \"application/json\",\n      });\n\n      const multipartRequestBody = [\n        `--${delimiter}`,\n        \"Content-Type: application/json\",\n        \"\",\n        await metadataBlob.text(),\n        `--${delimiter}`,\n        `Content-Type: ${file.type || \"application/octet-stream\"}`,\n        \"\",\n        \"\",\n      ].join(\"\\r\\n\");\n\n      const requestBody = new Blob([multipartRequestBody, file, closeDelim]);\n\n      const response = await fetch(\n        `${this.uploadUrl}/files?uploadType=multipart`,\n        {\n          method: \"POST\",\n          headers: {\n            Authorization: `Bearer ${this.config.accessToken}`,\n            \"Content-Type\": `multipart/related; boundary=\"${delimiter}\"`,\n          },\n          body: requestBody,\n        },\n      );\n\n      if (!response.ok) {\n        const error = await response.text();\n        throw new StorageError(\n          `Failed to upload to Google Drive: ${error}`,\n          \"UPLOAD_FAILED\",\n          \"google-drive\",\n        );\n      }\n\n      const result = (await response.json()) as GoogleDriveUploadResponse;\n\n      // Make file publicly readable\n      await this.makeFilePublic(result.id);\n\n      return {\n        url: `https://drive.google.com/uc?id=${result.id}&export=download`,\n        size: file.size,\n        contentType: file.type || \"application/octet-stream\",\n        metadata: {\n          id: result.id,\n          name: result.name,\n          driveUrl: `https://drive.google.com/file/d/${result.id}/view`,\n        },\n      };\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive upload error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"UPLOAD_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  async download(url: string): Promise<Blob> {\n    try {\n      // Extract file ID from Google Drive URL\n      const fileId = this.extractFileId(url);\n      if (!fileId) {\n        throw new StorageError(\n          \"Invalid Google Drive URL format\",\n          \"INVALID_URL\",\n          \"google-drive\",\n        );\n      }\n\n      const response = await fetch(\n        `${this.baseUrl}/files/${fileId}?alt=media`,\n        {\n          headers: {\n            Authorization: `Bearer ${this.config.accessToken}`,\n          },\n        },\n      );\n\n      if (!response.ok) {\n        const error = await response.text();\n        throw new StorageError(\n          `Failed to download from Google Drive: ${error}`,\n          \"DOWNLOAD_FAILED\",\n          \"google-drive\",\n        );\n      }\n\n      const blob = await response.blob();\n\n      // Check if we got HTML content instead of the actual file (authentication issue)\n      if (blob.type === \"text/html\") {\n        throw new StorageError(\n          \"Received HTML content instead of file data. This suggests an authentication or URL formatting issue with Google Drive.\",\n          \"AUTHENTICATION_ERROR\",\n          \"google-drive\",\n        );\n      }\n\n      return blob;\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive download error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"DOWNLOAD_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  async list(options?: StorageListOptions): Promise<StorageFile[]> {\n    try {\n      let query = \"trashed = false\";\n\n      // Add parent folder filter if configured\n      if (this.config.folderId) {\n        query += ` and '${this.config.folderId}' in parents`;\n      }\n\n      // Add name pattern filter\n      if (options?.namePattern) {\n        query += ` and name contains '${options.namePattern}'`;\n      }\n\n      const params = new URLSearchParams({\n        q: query,\n        fields: \"files(id,name,size,mimeType,createdTime,webViewLink)\",\n        pageSize: (options?.limit ?? 100).toString(),\n      });\n\n      if (options?.offset && typeof options.offset === \"string\") {\n        params.set(\"pageToken\", options.offset);\n      }\n\n      const response = await fetch(`${this.baseUrl}/files?${params}`, {\n        headers: {\n          Authorization: `Bearer ${this.config.accessToken}`,\n        },\n      });\n\n      if (!response.ok) {\n        const error = await response.text();\n        throw new StorageError(\n          `Failed to list Google Drive files: ${error}`,\n          \"LIST_FAILED\",\n          \"google-drive\",\n        );\n      }\n\n      const result = (await response.json()) as GoogleDriveListResponse;\n\n      return result.files.map((file: GoogleDriveFile) => ({\n        id: file.id,\n        name: file.name,\n        url: `https://drive.google.com/uc?id=${file.id}&export=download`,\n        size: parseInt(file.size) || 0,\n        contentType: file.mimeType,\n        createdAt: new Date(file.createdTime),\n        metadata: {\n          id: file.id,\n          driveUrl: file.webViewLink,\n        },\n      }));\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive list error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"LIST_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  async delete(url: string): Promise<boolean> {\n    try {\n      // Extract file ID from Google Drive URL\n      const fileId = this.extractFileId(url);\n      if (!fileId) {\n        throw new StorageError(\n          \"Invalid Google Drive URL format\",\n          \"INVALID_URL\",\n          \"google-drive\",\n        );\n      }\n\n      const response = await fetch(`${this.baseUrl}/files/${fileId}`, {\n        method: \"DELETE\",\n        headers: {\n          Authorization: `Bearer ${this.config.accessToken}`,\n        },\n      });\n\n      if (!response.ok && response.status !== 404) {\n        const error = await response.text();\n        throw new StorageError(\n          `Failed to delete from Google Drive: ${error}`,\n          \"DELETE_FAILED\",\n          \"google-drive\",\n        );\n      }\n\n      return true;\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive delete error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"DELETE_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  getConfig(): StorageProviderConfig {\n    return {\n      name: \"Google Drive\",\n      type: \"google-drive\",\n      requiresAuth: true,\n      features: {\n        upload: true,\n        download: true,\n        list: true,\n        delete: true,\n      },\n    };\n  }\n\n  /**\n   * Make a Google Drive file publicly readable\n   *\n   * @param fileId - Google Drive file ID\n   */\n  private async makeFilePublic(fileId: string): Promise<void> {\n    try {\n      await fetch(`${this.baseUrl}/files/${fileId}/permissions`, {\n        method: \"POST\",\n        headers: {\n          Authorization: `Bearer ${this.config.accessToken}`,\n          \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify({\n          role: \"reader\",\n          type: \"anyone\",\n        }),\n      });\n    } catch (error) {\n      // Non-critical error - file upload succeeded but sharing failed\n      console.warn(\"Failed to make Google Drive file public:\", error);\n    }\n  }\n\n  /**\n   * Extract file ID from various Google Drive URL formats\n   *\n   * @param url - Google Drive URL\n   * @returns File ID or null if not found\n   */\n  private extractFileId(url: string): string | null {\n    // Handle various Google Drive URL formats\n    const patterns = [\n      /\\/file\\/d\\/([a-zA-Z0-9-_]+)/, // https://drive.google.com/file/d/FILE_ID/view\n      /id=([a-zA-Z0-9-_]+)/, // https://drive.google.com/uc?id=FILE_ID\n      /^([a-zA-Z0-9-_]+)$/, // Just the file ID\n    ];\n\n    for (const pattern of patterns) {\n      const match = url.match(pattern);\n      if (match) {\n        return match[1];\n      }\n    }\n\n    return null;\n  }\n\n  /**\n   * Searches for an existing folder by name within a specified parent folder\n   *\n   * @remarks\n   * This method queries the Google Drive API to find a folder with the exact name\n   * within the specified parent directory. Only searches for folders (not files)\n   * and excludes trashed items.\n   *\n   * @param name - The exact name of the folder to search for\n   * @param parentId - The ID of the parent folder to search within (defaults to 'root')\n   * @returns Promise that resolves to the folder ID if found, or `null` if not found\n   * @throws {StorageError} When the Google Drive API request fails\n   *\n   * @example\n   * ```typescript\n   * // Search for a folder in the root directory\n   * const folderId = await googleDriveStorage.findFolder(\"screenshots\");\n   * if (folderId) {\n   *   console.log(\"Found folder:\", folderId);\n   * } else {\n   *   console.log(\"Folder not found\");\n   * }\n   *\n   * // Search for a subfolder within another folder\n   * const subFolderId = await googleDriveStorage.findFolder(\"roasts\", parentFolderId);\n   * ```\n   */\n  async findFolder(\n    name: string,\n    parentId: string = \"root\",\n  ): Promise<string | null> {\n    try {\n      const query = `name='${name}' and '${parentId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed = false`;\n\n      const params = new URLSearchParams({\n        q: query,\n        fields: \"files(id,name,mimeType)\",\n      });\n\n      const response = await fetch(`${this.baseUrl}/files?${params}`, {\n        headers: {\n          Authorization: `Bearer ${this.config.accessToken}`,\n        },\n      });\n\n      if (!response.ok) {\n        const error = await response.text();\n        throw new StorageError(\n          `Failed to search Google Drive folders: ${error}`,\n          \"FIND_FOLDER_FAILED\",\n          \"google-drive\",\n        );\n      }\n\n      const result = (await response.json()) as GoogleDriveListResponse;\n\n      if (result.files && result.files.length > 0) {\n        return result.files[0].id;\n      }\n\n      return null;\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive findFolder error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"FIND_FOLDER_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  /**\n   * Creates a new folder within a specified parent folder\n   *\n   * @remarks\n   * This method creates a new folder using the Google Drive API. The folder will be\n   * created with the specified name as a child of the parent folder. Requires the\n   * `https://www.googleapis.com/auth/drive.file` OAuth scope.\n   *\n   * @param name - The name for the new folder\n   * @param parentId - The ID of the parent folder where the new folder will be created (defaults to 'root')\n   * @returns Promise that resolves to the ID of the newly created folder\n   * @throws {StorageError} When the Google Drive API request fails or folder creation is denied\n   *\n   * @example\n   * ```typescript\n   * // Create a folder in the root directory\n   * const folderId = await googleDriveStorage.createFolder(\"my-documents\");\n   * console.log(\"Created folder:\", folderId);\n   *\n   * // Create a subfolder within another folder\n   * const subFolderId = await googleDriveStorage.createFolder(\"reports\", parentFolderId);\n   * ```\n   */\n  async createFolder(name: string, parentId: string = \"root\"): Promise<string> {\n    try {\n      const metadata = {\n        name,\n        mimeType: \"application/vnd.google-apps.folder\",\n        parents: [parentId],\n      };\n\n      const response = await fetch(`${this.baseUrl}/files`, {\n        method: \"POST\",\n        headers: {\n          Authorization: `Bearer ${this.config.accessToken}`,\n          \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify(metadata),\n      });\n\n      if (!response.ok) {\n        const error = await response.text();\n        throw new StorageError(\n          `Failed to create Google Drive folder: ${error}`,\n          \"CREATE_FOLDER_FAILED\",\n          \"google-drive\",\n        );\n      }\n\n      const result = (await response.json()) as GoogleDriveUploadResponse;\n      return result.id;\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive createFolder error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"CREATE_FOLDER_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  /**\n   * Finds an existing folder by name, or creates it if it doesn't exist\n   *\n   * @remarks\n   * This is a convenience method that combines `findFolder` and `createFolder`.\n   * It first searches for an existing folder with the specified name. If found,\n   * it returns the existing folder's ID. If not found, it creates a new folder\n   * and returns the new folder's ID.\n   *\n   * @param name - The name of the folder to find or create\n   * @param parentId - The ID of the parent folder to search within or create the folder in (defaults to 'root')\n   * @returns Promise that resolves to the folder ID (either existing or newly created)\n   * @throws {StorageError} When the Google Drive API request fails\n   *\n   * @example\n   * ```typescript\n   * // Ensure a folder exists, creating it if necessary\n   * const folderId = await googleDriveStorage.findOrCreateFolder(\"screenshots\");\n   * console.log(\"Folder ID:\", folderId); // Will be same ID if folder already existed\n   *\n   * // Create nested folder structure\n   * const parentId = await googleDriveStorage.findOrCreateFolder(\"projects\");\n   * const childId = await googleDriveStorage.findOrCreateFolder(\"vana-app\", parentId);\n   * ```\n   */\n  async findOrCreateFolder(\n    name: string,\n    parentId: string = \"root\",\n  ): Promise<string> {\n    try {\n      const existingFolderId = await this.findFolder(name, parentId);\n\n      if (existingFolderId) {\n        return existingFolderId;\n      }\n\n      return await this.createFolder(name, parentId);\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive findOrCreateFolder error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"FIND_OR_CREATE_FOLDER_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n\n  /**\n   * Refresh the access token using refresh token\n   *\n   * @returns Promise with new access token\n   */\n  async refreshAccessToken(): Promise<string> {\n    if (\n      !this.config.refreshToken ||\n      !this.config.clientId ||\n      !this.config.clientSecret\n    ) {\n      throw new StorageError(\n        \"Refresh token, client ID, and client secret are required for token refresh\",\n        \"MISSING_REFRESH_CONFIG\",\n        \"google-drive\",\n      );\n    }\n\n    try {\n      const response = await fetch(\"https://oauth2.googleapis.com/token\", {\n        method: \"POST\",\n        headers: {\n          \"Content-Type\": \"application/x-www-form-urlencoded\",\n        },\n        body: new URLSearchParams({\n          client_id: this.config.clientId,\n          client_secret: this.config.clientSecret,\n          refresh_token: this.config.refreshToken,\n          grant_type: \"refresh_token\",\n        }),\n      });\n\n      if (!response.ok) {\n        const error = await response.text();\n        throw new StorageError(\n          `Failed to refresh Google Drive token: ${error}`,\n          \"TOKEN_REFRESH_FAILED\",\n          \"google-drive\",\n        );\n      }\n\n      const result = (await response.json()) as GoogleDriveTokenResponse;\n      this.config.accessToken = result.access_token;\n\n      return result.access_token;\n    } catch (error) {\n      if (error instanceof StorageError) {\n        throw error;\n      }\n      throw new StorageError(\n        `Google Drive token refresh error: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        \"TOKEN_REFRESH_ERROR\",\n        \"google-drive\",\n      );\n    }\n  }\n}\n"],"mappings":"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","names":[]}