#Folder Organization

Learn how to organize your assets using folders, create hierarchies, and manage files efficiently.

#Creating a Folder Structure

Build a complete folder hierarchy for a project:

import { Walbucket } from '@walbucket/sdk';

const walbucket = new Walbucket({
  apiKey: process.env.WALBUCKET_API_KEY!,
  network: 'testnet',
  sponsorPrivateKey: process.env.SPONSOR_PRIVATE_KEY!,
});

async function setupProjectFolders() {
  // Create root project folder
  const projectId = await walbucket.createFolder('My Project');
  console.log('Created project folder:', projectId);
  
  // Create subfolders
  const docsId = await walbucket.createFolder('Documents', projectId);
  const imagesId = await walbucket.createFolder('Images', projectId);
  const videosId = await walbucket.createFolder('Videos', projectId);
  
  // Create nested folders
  const logosId = await walbucket.createFolder('Logos', imagesId);
  const photosId = await walbucket.createFolder('Photos', imagesId);
  
  return {
    project: projectId,
    documents: docsId,
    images: imagesId,
    videos: videosId,
    logos: logosId,
    photos: photosId,
  };
}

// Usage
const folders = await setupProjectFolders();
typescript

#Upload Files to Folders

Upload files directly into specific folders:

async function uploadToFolders(folders: any) {
  // Upload a document
  const doc = await walbucket.upload(documentFile, {
    name: 'Project Requirements.pdf',
    folder: folders.documents,
    category: 'documentation',
    tags: ['requirements', 'specs'],
  });
  
  // Upload a logo
  const logo = await walbucket.upload(logoFile, {
    name: 'company-logo.png',
    folder: folders.logos,
    category: 'branding',
    tags: ['logo', 'branding'],
  });
  
  // Upload a photo
  const photo = await walbucket.upload(photoFile, {
    name: 'team-photo.jpg',
    folder: folders.photos,
    category: 'photography',
    tags: ['team', 'office'],
  });
  
  console.log('Uploaded files to folders');
  
  return { doc, logo, photo };
}
typescript

#Move Files Between Folders

Reorganize files by moving them between folders:

async function reorganizeFiles(assetId: string, newFolderId: string) {
  try {
    // Move file to new folder
    await walbucket.moveToFolder(assetId, newFolderId);
    console.log('File moved successfully');
  } catch (error) {
    console.error('Failed to move file:', error);
  }
}

// Move file to root (no folder)
async function moveToRoot(assetId: string) {
  await walbucket.moveToFolder(assetId); // undefined = root
  console.log('Moved to root directory');
}
typescript

#List Folder Contents

Retrieve all folders and their contents:

async function listFolderContents(ownerAddress: string) {
  // Get all folders
  const folders = await walbucket.listFolders(ownerAddress);
  console.log(`Total folders: ${folders.length}`);
  
  // Get all assets
  const assets = await walbucket.list(ownerAddress);
  
  // Group assets by folder
  const assetsByFolder = assets.reduce((acc, asset) => {
    const folderId = asset.folderId || 'root';
    if (!acc[folderId]) {
      acc[folderId] = [];
    }
    acc[folderId].push(asset);
    return acc;
  }, {} as Record<string, typeof assets>);
  
  // Display folder structure
  folders.forEach(folder => {
    const count = assetsByFolder[folder.id]?.length || 0;
    console.log(`📁 ${folder.name}: ${count} files`);
  });
  
  // Root files
  const rootCount = assetsByFolder['root']?.length || 0;
  console.log(`📄 Root: ${rootCount} files`);
  
  return { folders, assetsByFolder };
}
typescript

#Complete File Manager Example

Build a complete file manager with folder navigation:

interface FileManagerState {
  currentFolder: string | null;
  folders: any[];
  assets: any[];
}

class FileManager {
  private walbucket: Walbucket;
  private state: FileManagerState;
  
  constructor(walbucket: Walbucket) {
    this.walbucket = walbucket;
    this.state = {
      currentFolder: null,
      folders: [],
      assets: [],
    };
  }
  
  async initialize(ownerAddress: string) {
    // Load all folders and assets
    this.state.folders = await this.walbucket.listFolders(ownerAddress);
    this.state.assets = await this.walbucket.list(ownerAddress);
    console.log('File manager initialized');
  }
  
  getCurrentFolderContents() {
    // Get assets in current folder
    return this.state.assets.filter(asset => 
      asset.folderId === this.state.currentFolder
    );
  }
  
  getSubfolders() {
    // Get folders inside current folder
    return this.state.folders.filter(folder =>
      folder.parentId === this.state.currentFolder
    );
  }
  
  async navigateToFolder(folderId: string | null) {
    this.state.currentFolder = folderId;
    console.log(`Navigated to: ${folderId || 'Root'}`);
  }
  
  async createFolder(name: string) {
    const folderId = await this.walbucket.createFolder(
      name,
      this.state.currentFolder || undefined
    );
    
    // Refresh folders list
    await this.initialize(/* ownerAddress */);
    
    return folderId;
  }
  
  async uploadFile(file: File, options: any = {}) {
    const result = await this.walbucket.upload(file, {
      ...options,
      folder: this.state.currentFolder || undefined,
    });
    
    // Refresh assets list
    await this.initialize(/* ownerAddress */);
    
    return result;
  }
  
  async moveFile(assetId: string, targetFolderId: string | null) {
    await this.walbucket.moveToFolder(assetId, targetFolderId || undefined);
    
    // Refresh assets list
    await this.initialize(/* ownerAddress */);
  }
  
  async deleteFolder(folderId: string) {
    await this.walbucket.deleteFolder(folderId);
    
    // Navigate to parent if we're in the deleted folder
    if (this.state.currentFolder === folderId) {
      const folder = this.state.folders.find(f => f.id === folderId);
      this.state.currentFolder = folder?.parentId || null;
    }
    
    // Refresh folders list
    await this.initialize(/* ownerAddress */);
  }
  
  getBreadcrumbs(): Array<{ id: string | null; name: string }> {
    const breadcrumbs: Array<{ id: string | null; name: string }> = [
      { id: null, name: 'Root' }
    ];
    
    let current = this.state.currentFolder;
    while (current) {
      const folder = this.state.folders.find(f => f.id === current);
      if (!folder) break;
      
      breadcrumbs.unshift({ id: folder.id, name: folder.name });
      current = folder.parentId;
    }
    
    return breadcrumbs;
  }
}

// Usage
const manager = new FileManager(walbucket);
await manager.initialize(userAddress);

// Navigate folders
await manager.navigateToFolder('folder-id-123');

// Get current contents
const files = manager.getCurrentFolderContents();
const folders = manager.getSubfolders();

// Upload to current folder
await manager.uploadFile(file, { name: 'document.pdf' });

// Create subfolder
await manager.createFolder('New Subfolder');
typescript

#React Component Example

Build a folder browser component:

import { useState, useEffect } from 'react';
import { Walbucket } from '@walbucket/sdk';

function FolderBrowser({ walbucket, userAddress }) {
  const [currentFolder, setCurrentFolder] = useState(null);
  const [folders, setFolders] = useState([]);
  const [assets, setAssets] = useState([]);
  
  useEffect(() => {
    loadData();
  }, [userAddress]);
  
  async function loadData() {
    const [foldersList, assetsList] = await Promise.all([
      walbucket.listFolders(userAddress),
      walbucket.list(userAddress),
    ]);
    
    setFolders(foldersList);
    setAssets(assetsList);
  }
  
  const currentAssets = assets.filter(
    a => a.folderId === currentFolder
  );
  
  const subfolders = folders.filter(
    f => f.parentId === currentFolder
  );
  
  const breadcrumbs = getBreadcrumbs(currentFolder, folders);
  
  return (
    <div>
      {/* Breadcrumbs */}
      <div className="breadcrumbs">
        {breadcrumbs.map((crumb, i) => (
          <span key={i}>
            <button onClick={() => setCurrentFolder(crumb.id)}>
              {crumb.name}
            </button>
            {i < breadcrumbs.length - 1 && ' > '}
          </span>
        ))}
      </div>
      
      {/* Folders */}
      <div className="folders">
        <h3>Folders</h3>
        {subfolders.map(folder => (
          <div 
            key={folder.id}
            onClick={() => setCurrentFolder(folder.id)}
            className="folder-item"
          >
            📁 {folder.name}
          </div>
        ))}
      </div>
      
      {/* Files */}
      <div className="files">
        <h3>Files</h3>
        {currentAssets.map(asset => (
          <div key={asset.assetId} className="file-item">
            📄 {asset.name}
          </div>
        ))}
      </div>
    </div>
  );
}

function getBreadcrumbs(currentId, folders) {
  const breadcrumbs = [{ id: null, name: 'Root' }];
  let current = currentId;
  
  while (current) {
    const folder = folders.find(f => f.id === current);
    if (!folder) break;
    breadcrumbs.unshift({ id: folder.id, name: folder.name });
    current = folder.parentId;
  }
  
  return breadcrumbs;
}
typescript

#Best Practices

#Folder Naming

// Good: Clear, descriptive names
await walbucket.createFolder('Project Alpha - Documents');
await walbucket.createFolder('Q4 2024 Reports');
await walbucket.createFolder('Marketing Assets');

// Avoid: Generic or unclear names
// await walbucket.createFolder('Folder1');
// await walbucket.createFolder('Stuff');
typescript

#Folder Depth

// Good: Reasonable depth (2-3 levels)
// Root > Projects > Project Alpha > Documents

// Avoid: Too deep (hard to navigate)
// Root > Projects > 2024 > Q4 > November > Week 1 > Day 1
typescript

#Error Handling

async function safeCreateFolder(name: string, parentId?: string) {
  try {
    const folderId = await walbucket.createFolder(name, parentId);
    return { success: true, folderId };
  } catch (error) {
    if (error.message.includes('E_NOT_OWNER')) {
      return { success: false, error: 'Not folder owner' };
    }
    if (error.message.includes('already exists')) {
      return { success: false, error: 'Folder name exists' };
    }
    return { success: false, error: error.message };
  }
}
typescript