# OneDrive Path Resolver Utility

This utility provides reusable functions for resolving OneDrive folder IDs to paths across different rclone operations.

## Problem Solved

Previously, OneDrive folder ID resolution logic was duplicated across multiple files:

- `fly-rclone/server.js` (folder copy operations).
- `fly-rclone/src/routes/copyRoutes.js` (file copy operations - 3 occurrences).

This led to:

- Code duplication.
- Inconsistent error handling.
- Difficult maintenance.
- Risk of bugs when updating logic.

## Solution

The `oneDrivePathResolver.js` utility centralizes all OneDrive path resolution logic into reusable functions.

## Usage

### Basic Resolution

```javascript
const {
  resolveOneDriveDestinationPath,
} = require("./utils/oneDrivePathResolver");

// For folder operations
const result = await resolveOneDriveDestinationPath({
  destPath: "3EC4DC457B29B213!sd0d5f4f552b94e23bd77deb55fd7c165",
  destRemote: "onedrive-account",
  config: rcloneConfig,
  folderName: "new-folder", // Optional
  isFileOperation: false,
});

console.log(result.resolvedPath); // 'resolved/path/new-folder'
console.log(result.wasResolved); // true
console.log(result.originalPath); // '3EC4DC457B29B213!sd0d5f4f552b94e23bd77deb55fd7c165'
```

### File Operations

```javascript
// For file operations
const result = await resolveOneDriveDestinationPath({
  destPath: "3EC4DC457B29B213!sd0d5f4f552b94e23bd77deb55fd7c165",
  destRemote: "onedrive-account",
  config: rcloneConfig,
  fileName: "document.pdf", // Optional
  isFileOperation: true,
});
```

### Simple Resolution

```javascript
const { resolveOneDrivePathSimple } = require("./utils/oneDrivePathResolver");

const resolvedPath = await resolveOneDrivePathSimple(
  "3EC4DC457B29B213!sd0d5f4f552b94e23bd77deb55fd7c165",
  "onedrive-account",
  rcloneConfig,
);
```

### Check if Resolution is Needed

```javascript
const { needsOneDriveResolution } = require("./utils/oneDrivePathResolver");

if (needsOneDriveResolution(destPath, destRemote)) {
  // Perform resolution
}
```

## Dropbox Path Resolver

The Dropbox Path Resolver provides utilities for converting Dropbox folder IDs to paths for rclone operations.

### Basic Usage

```javascript
const {
  resolveDropboxDestinationPath,
} = require("./utils/dropboxPathResolver");

// For folder operations
const result = await resolveDropboxDestinationPath({
  destPath: "id:2V5kn5RRfnAAAAAAAADjCA",
  destRemote: "dropbox-account",
  config: rcloneConfig,
  folderName: "new-folder", // Optional
  isFileOperation: false,
});

console.log(result.resolvedPath); // '/google to dropbox/new-folder'
console.log(result.wasResolved); // true
console.log(result.originalPath); // 'id:2V5kn5RRfnAAAAAAAADjCA'
```

### File Operations

```javascript
// For file operations
const result = await resolveDropboxDestinationPath({
  destPath: "id:2V5kn5RRfnAAAAAAAADjCA",
  destRemote: "dropbox-account",
  config: rcloneConfig,
  fileName: "document.pdf", // Optional
  isFileOperation: true,
});
```

### Simple Resolution

```javascript
const { resolveDropboxPathSimple } = require("./utils/dropboxPathResolver");

const resolvedPath = await resolveDropboxPathSimple(
  "id:2V5kn5RRfnAAAAAAAADjCA",
  "dropbox-account",
  rcloneConfig,
);
```

### Check if Resolution is Needed

```javascript
const { needsDropboxResolution } = require("./utils/dropboxPathResolver");

if (needsDropboxResolution(destPath, destRemote)) {
  // Perform resolution
}
```

## API Reference

### `resolveOneDriveDestinationPath(options)`

Main function for resolving OneDrive paths with full options.

**Parameters:**

- `options.destPath` (string) - The destination path or folder ID.
- `options.destRemote` (string) - The destination remote name.
- `options.config` (string) - The rclone configuration.
- `options.folderName` (string, optional) - Folder name to append.
- `options.fileName` (string, optional) - File name to append.
- `options.isFileOperation` (boolean, optional) - Whether this is a file operation.

**Returns:** `Promise<OneDrivePathResolverResult>`

- `resolvedPath` (string) - The resolved path.
- `wasResolved` (boolean) - Whether the path was actually resolved from an ID.
- `originalPath` (string) - The original path/ID provided.

### `resolveOneDrivePathSimple(destPath, destRemote, config)`

Simplified version for basic resolution without additional handling.

**Returns:** `Promise<string>` - The resolved path

### `needsOneDriveResolution(destPath, destRemote)`

Checks if a destination path needs OneDrive resolution.

**Returns:** `boolean` - Whether resolution is needed

### `resolveDropboxDestinationPath(options)`

Main function for resolving Dropbox paths with full options.

**Parameters:**

- `options.destPath` (string) - The destination path or folder ID.
- `options.destRemote` (string) - The destination remote name.
- `options.config` (string) - The rclone configuration.
- `options.folderName` (string, optional) - Folder name to append.
- `options.fileName` (string, optional) - File name to append.
- `options.isFileOperation` (boolean, optional) - Whether this is a file operation.

**Returns:** `Promise<DropboxPathResolverResult>`

- `resolvedPath` (string) - The resolved path.
- `wasResolved` (boolean) - Whether the path was actually resolved from an ID.
- `originalPath` (string) - The original path/ID provided.

### `resolveDropboxPathSimple(destPath, destRemote, config)`

Simplified version for basic Dropbox resolution without additional handling.

**Returns:** `Promise<string>` - The resolved path

### `needsDropboxResolution(destPath, destRemote)`

Checks if Dropbox path resolution is needed. Returns `true` for Dropbox file IDs and for "root" paths (which need to be converted to empty strings for Dropbox).

**Returns:** `boolean` - Whether resolution is needed

### `isDropboxFileId(path)`

Checks if a path is a Dropbox folder ID.

**Returns:** `boolean` - Whether the path is a Dropbox folder ID

### `convertDropboxIdToPath(dropboxId, accessToken)`

Converts a Dropbox folder ID to a path using the Dropbox API.

**Returns:** `Promise<string>` - The resolved folder path

## Error Handling

The utility throws descriptive errors when:

- Access token cannot be extracted from config.
- OneDrive API calls fail.
- Invalid folder IDs are provided.

## Testing

Run tests with:

```bash
npm test -- oneDrivePathResolver.test.js
```

## Migration Guide

### Before (Duplicated Logic)

```javascript
// In multiple files
if (
  destRemote.startsWith("onedrive") &&
  destPath &&
  destPath !== "root" &&
  isOneDriveFileId(destPath)
) {
  const decodedDestPath = decodeURIComponent(destPath);
  const accessToken = extractAccessTokenFromConfig(config, destRemote);
  // ... more logic
}
```

### After (Using Utility)

```javascript
// Single line replacement
if (destRemote.startsWith("onedrive")) {
  const oneDriveResult = await resolveOneDriveDestinationPath({
    destPath,
    destRemote,
    config,
    folderName, // if applicable
    isFileOperation: false,
  });
  resolvedDestPath = oneDriveResult.resolvedPath;
}
```

## Benefits

1. **DRY Principle**: Eliminates code duplication
2. **Consistent Behavior**: Same logic across all operations
3. **Better Error Handling**: Centralized error messages
4. **Easier Testing**: Single place to test resolution logic
5. **Maintainability**: Updates only need to be made in one place
6. **Type Safety**: Clear interfaces and return types
