code icon Code

Find Files in Drive

Search Google Drive for files by name or content, with optional type filtering

Source Code

import fs from "fs";
import path from "path";

const [query, outputPath, mimeType = "", maxResultsArg = "10"] = process.argv.slice(2);

if (!query || !outputPath) {
  console.error("Usage: query outputPath [mimeType] [maxResults]");
  process.exit(1);
}

const maxResults = parseInt(maxResultsArg, 10) || 10;

// Token placeholder - replaced at runtime by Sauna
const TOKEN = "GOOGLE_DRIVE_TOKEN";
const BASE_URL = "https://www.googleapis.com/drive/v3";

async function fetchWithAuth(url) {
  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${TOKEN}` },
  });

  if (!response.ok) {
    const error = await response.text();
    throw new Error(`API error ${response.status}: ${error}`);
  }

  return response.json();
}

try {
  console.log(`Searching Drive for: "${query}"`);
  if (mimeType) {
    console.log(`  Filtering by type: ${mimeType}`);
  }

  // Build Drive API query
  // Escape single quotes in query
  const escapedQuery = query.replace(/'/g, "\\'");

  let driveQuery = `(name contains '${escapedQuery}' or fullText contains '${escapedQuery}') and trashed=false`;

  if (mimeType) {
    driveQuery = `mimeType='${mimeType}' and ${driveQuery}`;
  }

  const params = new URLSearchParams({
    q: driveQuery,
    pageSize: maxResults.toString(),
    fields: "files(id,name,mimeType,modifiedTime,owners,webViewLink)",
    orderBy: "modifiedTime desc",
  });

  const url = `${BASE_URL}/files?${params}`;
  const response = await fetchWithAuth(url);

  const results = (response.files || []).map((file) => ({
    id: file.id,
    name: file.name,
    mimeType: file.mimeType,
    modifiedTime: file.modifiedTime,
    owner: file.owners?.[0]?.emailAddress || null,
    url: file.webViewLink,
  }));

  console.log(`  Found ${results.length} files`);
  for (const file of results) {
    const typeShort = file.mimeType?.split(".").pop() || "file";
    console.log(`  - ${file.name} (${typeShort}, modified: ${file.modifiedTime?.split("T")[0]})`);
  }

  // Ensure output directory exists
  const dir = path.dirname(outputPath);
  if (dir && dir !== ".") {
    fs.mkdirSync(dir, { recursive: true });
  }

  fs.writeFileSync(
    outputPath,
    JSON.stringify(
      {
        query,
        mimeType: mimeType || null,
        count: results.length,
        files: results,
      },
      null,
      2
    )
  );

  console.log(`  Written to: ${outputPath}`);

  // Output summary for agent
  console.log(
    JSON.stringify({
      success: true,
      query,
      mimeType: mimeType || null,
      count: results.length,
      outputPath,
      files: results.map((f) => ({ id: f.id, name: f.name, mimeType: f.mimeType })),
    })
  );
} catch (error) {
  console.error(`Error: ${error.message}`);
  process.exit(1);
}