Folder Management

Organize your files with folders and hierarchical structures using the Dropper API.

Create Folder

Create a new folder to organize your files:

import { DropperClient } from '@dropper/core'

const client = new DropperClient({
  publishableKey: 'pk_dropper_test_xxx',
})

const folder = await client.createFolder({
  name: 'My Documents',
})

console.log('Folder created:', folder.id)

CreateFolderDto

interface CreateFolderDto {
  name: string        // Folder name (required)
  parentId?: string   // Parent folder ID (optional)
}

Create Nested Folder

Create a folder inside another folder:

const parentFolder = await client.createFolder({
  name: 'Projects',
})

const childFolder = await client.createFolder({
  name: '2024',
  parentId: parentFolder.id,
})

List Folders

Retrieve a list of folders with optional filtering:

const response = await client.listFolders()

console.log(`Total folders: ${response.total}`)
response.folders.forEach((folder) => {
  console.log(`- ${folder.name} (${folder.path})`)
})

ListFoldersParams

interface ListFoldersParams {
  parentId?: string   // Filter by parent folder
  path?: string       // Filter by path
  page?: number       // Page number (default: 1)
  limit?: number      // Items per page (default: 20)
}

ListFoldersResponse

interface ListFoldersResponse {
  folders: FolderResponseDto[]  // Array of folders
  total: number                 // Total number of folders
  page: number                  // Current page
  limit: number                 // Items per page
}

Get Root Folders

Get all top-level folders (folders without a parent):

const rootFolders = await client.getRootFolders()

rootFolders.forEach((folder) => {
  console.log(`Root folder: ${folder.name}`)
})

Get Single Folder

Retrieve details for a specific folder:

const folder = await client.getFolder('folder_abc123')

console.log('Folder details:')
console.log(`- Name: ${folder.name}`)
console.log(`- Path: ${folder.path}`)
console.log(`- Parent: ${folder.parentId || 'None (root)'}`)
console.log(`- Created: ${folder.createdAt}`)

Get Folder Children

Get all child folders of a specific folder:

const children = await client.getFolderChildren('folder_abc123')

console.log(`Found ${children.length} child folders`)
children.forEach((child) => {
  console.log(`- ${child.name}`)
})

Update Folder

Rename a folder or move it to a different parent:

Rename Folder

const updated = await client.updateFolder('folder_abc123', {
  name: 'New Folder Name',
})

console.log('Folder renamed:', updated.name)

Move Folder

const updated = await client.updateFolder('folder_abc123', {
  parentId: 'folder_xyz789',
})

console.log('Folder moved to:', updated.path)

Move to Root

const updated = await client.updateFolder('folder_abc123', {
  parentId: null,
})

console.log('Folder moved to root')

Delete Folder

Remove a folder and all its contents:

await client.deleteFolder('folder_abc123')
console.log('Folder deleted successfully')

Warning: Deleting a folder will also delete all files and subfolders within it. This action cannot be undone.

With Error Handling

try {
  await client.deleteFolder('folder_abc123')
  console.log('Folder deleted successfully')
} catch (error) {
  if (error.statusCode === 404) {
    console.error('Folder not found')
  } else if (error.statusCode === 403) {
    console.error('Permission denied')
  } else {
    console.error('Delete failed:', error.message)
  }
}

FolderResponseDto

The folder object returned by the API:

interface FolderResponseDto {
  id: string          // Unique folder ID
  name: string        // Folder name
  path: string        // Full folder path (e.g., "/Projects/2024")
  parentId?: string   // Parent folder ID (undefined for root folders)
  appId: string       // App ID
  createdAt: string   // ISO timestamp
  updatedAt: string   // ISO timestamp
}

Complete Examples

Folder Tree

Build a folder tree structure:

async function buildFolderTree() {
  const rootFolders = await client.getRootFolders()
  
  async function getFolderWithChildren(folder: FolderResponseDto) {
    const children = await client.getFolderChildren(folder.id)
    return {
      ...folder,
      children: await Promise.all(
        children.map((child) => getFolderWithChildren(child))
      ),
    }
  }
  
  const tree = await Promise.all(
    rootFolders.map((folder) => getFolderWithChildren(folder))
  )
  
  return tree
}

Folder Browser

async function browseFolder(folderId?: string) {
  if (folderId) {
    // Get specific folder
    const folder = await client.getFolder(folderId)
    console.log(`Current folder: ${folder.path}`)
    
    // Get children
    const children = await client.getFolderChildren(folderId)
    console.log(`Subfolders: ${children.length}`)
    
    // Get files in folder
    const files = await client.listFiles({ folderId })
    console.log(`Files: ${files.total}`)
  } else {
    // Get root folders
    const folders = await client.getRootFolders()
    console.log(`Root folders: ${folders.length}`)
  }
}

Create Folder Hierarchy

async function createFolderHierarchy() {
  // Create root folder
  const projects = await client.createFolder({
    name: 'Projects',
  })
  
  // Create year folders
  const year2024 = await client.createFolder({
    name: '2024',
    parentId: projects.id,
  })
  
  // Create month folders
  const months = ['January', 'February', 'March']
  for (const month of months) {
    await client.createFolder({
      name: month,
      parentId: year2024.id,
    })
  }
  
  console.log('Folder hierarchy created')
}

Move Files to Folder

async function moveFilesToFolder(fileIds: string[], folderId: string) {
  // Note: The current API doesn't have a direct "move file" endpoint
  // This would require re-uploading files to the new folder
  // Or implementing a backend endpoint to move files
  
  console.log(`Moving ${fileIds.length} files to folder ${folderId}`)
  // Implementation depends on your backend API
}

Folder Statistics

async function getFolderStatistics(folderId: string) {
  // Get folder details
  const folder = await client.getFolder(folderId)
  
  // Get files in folder
  const files = await client.listFiles({ folderId })
  
  // Get subfolders
  const subfolders = await client.getFolderChildren(folderId)
  
  // Calculate total size
  const totalSize = files.data.reduce((sum, file) => sum + file.size, 0)
  
  console.log(`Folder: ${folder.name}`)
  console.log(`Path: ${folder.path}`)
  console.log(`Files: ${files.total}`)
  console.log(`Subfolders: ${subfolders.length}`)
  console.log(`Total size: ${formatFileSize(totalSize)}`)
  
  return {
    folder,
    fileCount: files.total,
    subfolderCount: subfolders.length,
    totalSize,
  }
}

Bulk Delete Folders

async function deleteFolders(folderIds: string[]) {
  const results = await Promise.allSettled(
    folderIds.map((id) => client.deleteFolder(id))
  )
  
  const successful = results.filter((r) => r.status === 'fulfilled').length
  const failed = results.filter((r) => r.status === 'rejected').length
  
  console.log(`Deleted ${successful} folders`)
  if (failed > 0) {
    console.error(`Failed to delete ${failed} folders`)
  }
}

Upload to Folder

Upload files directly to a folder:

const folder = await client.createFolder({
  name: 'Uploads',
})

const file = new File(['content'], 'document.pdf')
const result = await client.uploadFile(file, {
  folderId: folder.id,
})

console.log(`File uploaded to ${folder.name}`)

Best Practices

1. Use Descriptive Names

Choose clear, descriptive folder names:

// Good
await client.createFolder({ name: 'Customer Documents' })
await client.createFolder({ name: 'Invoice Templates' })

// Avoid
await client.createFolder({ name: 'Folder1' })
await client.createFolder({ name: 'Misc' })

2. Organize by Purpose

Create a logical folder structure:

// By date
await client.createFolder({ name: '2024' })
await client.createFolder({ name: 'January', parentId: year2024.id })

// By category
await client.createFolder({ name: 'Documents' })
await client.createFolder({ name: 'Images' })
await client.createFolder({ name: 'Videos' })

// By project
await client.createFolder({ name: 'Project Alpha' })
await client.createFolder({ name: 'Project Beta' })

3. Limit Nesting Depth

Avoid deeply nested folder structures:

// Good: 2-3 levels
/Projects/2024/January

// Avoid: Too many levels
/Projects/2024/Q1/January/Week1/Monday

4. Handle Errors

Always handle errors when managing folders:

try {
  await client.createFolder({ name: 'New Folder' })
  showSuccess('Folder created')
} catch (error) {
  if (error.statusCode === 409) {
    showError('Folder already exists')
  } else {
    showError(`Failed to create folder: ${error.message}`)
  }
}

5. Cache Folder Lists

Cache folder lists to reduce API calls:

let cachedFolders: FolderResponseDto[] | null = null

async function getFolders(forceRefresh = false) {
  if (!forceRefresh && cachedFolders) {
    return cachedFolders
  }
  
  const response = await client.listFolders()
  cachedFolders = response.folders
  
  return cachedFolders
}

Next Steps