// Path resolution utilities for Google Drive
import type { drive_v3 } from 'googleapis';
import { FOLDER_MIME_TYPE } from './mime.js';
export interface DriveService {
files: drive_v3.Resource$Files;
}
/**
* Resolve a slash-delimited path (e.g. "/some/folder") within Google Drive
* into a folder ID. Creates folders if they don't exist.
*/
export async function resolvePath(
drive: DriveService,
pathStr: string,
createIfNotExists = true
): Promise<string> {
if (!pathStr || pathStr === '/') return 'root';
const parts = pathStr.replace(/^\/+|\/+$/g, '').split('/');
let currentFolderId = 'root';
for (const part of parts) {
if (!part) continue;
const response = await drive.files.list({
q: `'${currentFolderId}' in parents and name = '${part}' and mimeType = '${FOLDER_MIME_TYPE}' and trashed = false`,
fields: 'files(id)',
spaces: 'drive',
includeItemsFromAllDrives: true,
supportsAllDrives: true,
});
if (!response.data.files?.length) {
if (!createIfNotExists) {
throw new Error(`Folder not found: ${part} in path ${pathStr}`);
}
// Create the folder
const folderMetadata = {
name: part,
mimeType: FOLDER_MIME_TYPE,
parents: [currentFolderId],
};
const folder = await drive.files.create({
requestBody: folderMetadata,
fields: 'id',
supportsAllDrives: true,
});
if (!folder.data.id) {
throw new Error(`Failed to create folder: ${part}`);
}
currentFolderId = folder.data.id;
} else {
currentFolderId = response.data.files[0].id!;
}
}
return currentFolderId;
}
/**
* Resolve a folder ID or path.
* If it's a path (starts with '/'), resolve it.
* If no folder is provided, return 'root'.
*/
export async function resolveFolderId(
drive: DriveService,
input: string | undefined,
createIfNotExists = true
): Promise<string> {
if (!input) return 'root';
if (input.startsWith('/')) {
return resolvePath(drive, input, createIfNotExists);
}
// Input is already a folder ID
return input;
}
/**
* Get the full path of a file/folder by traversing parents
*/
export async function getFullPath(
drive: DriveService,
fileId: string
): Promise<string> {
const parts: string[] = [];
let currentId = fileId;
while (currentId && currentId !== 'root') {
const response = await drive.files.get({
fileId: currentId,
fields: 'name,parents',
supportsAllDrives: true,
});
if (response.data.name) {
parts.unshift(response.data.name);
}
currentId = response.data.parents?.[0] || '';
}
return '/' + parts.join('/');
}