@musallam/storage-and-collaboration-client
    Preparing search index...

    @musallam/storage-and-collaboration-client

    @musallam/storage-and-collaboration-client

    TypeScript client library for the Adobe Cloud Storage and Collaboration API.

    • 🚀 Full TypeScript support with auto-generated types from OpenAPI spec
    • 📦 Complete API coverage for all Storage and Collaboration endpoints
    • 🔄 Job polling utilities for async operations
    • 🔐 Built-in authentication via IMS client
    • 📝 Comprehensive documentation and examples
    npm install @musallam/storage-and-collaboration-client
    
    import {
    StorageAndCollaborationClient,
    STORAGE_AXIOS_INSTANCE,
    TokenIMSClient,
    } from '@musallam/storage-and-collaboration-client';

    // 1. Setup authentication
    const imsClient = new TokenIMSClient({
    clientId: 'YOUR_CLIENT_ID',
    clientSecret: 'YOUR_CLIENT_SECRET',
    scopes: ['openid', 'creative_sdk', 'AdobeID'],
    });

    // 2. Configure axios instance
    STORAGE_AXIOS_INSTANCE.interceptors.request.use(async (config) => {
    const token = await imsClient.getAccessToken();
    config.headers.Authorization = `Bearer ${token}`;
    config.headers['x-api-key'] = 'YOUR_CLIENT_ID';
    return config;
    });

    // 3. Use the client
    const projects = await StorageAndCollaborationClient.getProjects({
    limit: 10,
    });
    console.log(projects);
    • getProjects() - List all projects
    • createProject() - Create a new project
    • getProject() - Get project details
    • discardProject() - Soft delete a project
    • getProjectChildren() - List project contents
    • getProjectEffectivePermission() - Get user's permission
    • getProjectPermissions() - List all permissions
    • patchProjectPermissions() - Modify permissions
    • createFolder() - Create a folder
    • getFolder() - Get folder details
    • getFolderChildren() - List folder contents
    • getFolderEffectivePermission() - Get user's permission
    • getFolderPermissions() - List all permissions
    • getFile() - Get file metadata
    • downloadFile() - Get download URL
    • getFileImageRendition() - Get image rendition
    • getFileEffectivePermission() - Get user's permission
    • initBlockBasedFileUpload() - Initialize file upload
    • finalizeBlockBasedFileUpload() - Complete file upload
    • getJobStatus() - Check async job status
    • pollStorageJob() - Poll until completion (utility)
    const project = await StorageAndCollaborationClient.createProject({
    name: 'My New Project',
    });
    console.log(`Created: ${project.assetId}`);
    // Single folder
    const folder = await StorageAndCollaborationClient.createFolder({
    parentId: 'urn:aaid:sc:US:project-id',
    name: 'Documents',
    });

    // Nested folders (creates entire hierarchy)
    const nestedFolder = await StorageAndCollaborationClient.createFolder({
    parentId: 'urn:aaid:sc:US:project-id',
    path: 'Marketing/2024/Q4',
    });
    import { pollStorageJob } from '@musallam/storage-and-collaboration-client';

    // 1. Initialize upload
    const uploadInit = await StorageAndCollaborationClient.initBlockBasedFileUpload({
    parentId: 'urn:aaid:sc:US:folder-id',
    name: 'document.pdf',
    mediaType: 'application/pdf',
    size: fileSize,
    blockSize: 10485760, // 10MB blocks (optional)
    });

    // 2. Upload blocks to transfer URLs
    for (let i = 0; i < uploadInit.transferLinks.length; i++) {
    const link = uploadInit.transferLinks[i];
    const blockData = getBlockData(i); // Your logic to get block data

    await axios.put(link.url, blockData, {
    headers: { 'Content-Type': 'application/octet-stream' },
    });
    }

    // 3. Finalize upload
    const finalizeResponse = await StorageAndCollaborationClient.finalizeBlockBasedFileUpload({
    uploadId: uploadInit.uploadId,
    usedTransferLinks: [1, 2, 3], // Part numbers you uploaded
    });

    // 4. Poll for completion
    const result = await pollStorageJob(finalizeResponse.jobId, {
    intervalMs: 2000,
    maxAttempts: 60,
    onProgress: (status) => {
    console.log(`Upload status: ${status.status}`);
    },
    });

    console.log('Upload complete!', result);
    // Get effective permission for current user
    const permission = await StorageAndCollaborationClient.getProjectEffectivePermission({
    assetId: 'urn:aaid:sc:US:project-id',
    });
    console.log(`Your role: ${permission.role}`); // 'edit' or 'comment'

    // List all permissions
    const permissions = await StorageAndCollaborationClient.getProjectPermissions({
    assetId: 'urn:aaid:sc:US:project-id',
    });
    console.log(`Direct: ${permissions.direct.length}`);
    console.log(`Pending: ${permissions.pending.length}`);

    // Add collaborators
    await StorageAndCollaborationClient.patchProjectPermissions(
    { assetId: 'urn:aaid:sc:US:project-id' },
    {
    direct: {
    additions: [
    {
    recipient: 'mailto:user@example.com',
    type: 'user',
    role: 'comment',
    },
    {
    recipient: 'name:Marketing Team',
    type: 'group',
    role: 'edit',
    },
    ],
    },
    }
    );

    // Update or remove permissions
    await StorageAndCollaborationClient.patchProjectPermissions(
    { assetId: 'urn:aaid:sc:US:project-id' },
    {
    direct: {
    updates: [
    {
    id: 'user-id@AdobeID',
    type: 'user',
    role: 'edit', // Changed from 'comment' to 'edit'
    },
    ],
    deletions: [
    {
    id: 'another-user-id@AdobeID',
    type: 'user',
    },
    ],
    },
    }
    );
    // Get download URL
    const downloadInfo = await StorageAndCollaborationClient.downloadFile({
    assetId: 'urn:aaid:sc:US:file-id',
    urlTTL: 3600, // URL valid for 1 hour
    });

    console.log(`Download from: ${downloadInfo.url}`);
    console.log(`Expires: ${downloadInfo.urlExpirationDate}`);
    console.log(`Size: ${downloadInfo.size} bytes`);

    // For large files, the API might return 202 with a job ID
    // Poll the job to get the download URL when ready
    let cursor: string | undefined;
    let allProjects: typeof projects.items = [];

    do {
    const projects = await StorageAndCollaborationClient.getProjects({
    limit: 100,
    cursor,
    });

    allProjects.push(...(projects.items || []));

    // Extract cursor from nextUrl if present
    if (projects.paging?.nextUrl) {
    const url = new URL(projects.paging.nextUrl);
    cursor = url.searchParams.get('cursor') || undefined;
    } else {
    cursor = undefined;
    }
    } while (cursor);

    console.log(`Total projects: ${allProjects.length}`);
    // Filter projects by view
    const myProjects = await StorageAndCollaborationClient.getProjects({
    filter: 'view==yours',
    sortBy: '-created', // Sort by creation date descending
    });

    // Filter children by asset type
    const onlyFolders = await StorageAndCollaborationClient.getProjectChildren({
    assetId: 'urn:aaid:sc:US:project-id',
    filter: 'assetType==folder',
    });

    // Filter children by media type
    const pdfFiles = await StorageAndCollaborationClient.getProjectChildren({
    assetId: 'urn:aaid:sc:US:project-id',
    filter: 'assetType==file;mediaType==application/pdf',
    });

    For async operations, use the polling utility:

    import { pollStorageJob, PollingTimeoutError } from '@musallam/storage-and-collaboration-client';

    try {
    const result = await pollStorageJob(jobId, {
    intervalMs: 2000, // Poll every 2 seconds
    maxAttempts: 60, // Try up to 60 times
    timeoutMs: 300000, // Or timeout after 5 minutes
    onProgress: (status) => {
    console.log(`Status: ${status.status}`);
    },
    });

    console.log('Job completed:', result);
    } catch (error) {
    if (error instanceof PollingTimeoutError) {
    console.error('Job timed out');
    } else {
    console.error('Job failed:', error);
    }
    }
    try {
    const project = await StorageAndCollaborationClient.getProject({
    assetId: 'invalid-id',
    });
    } catch (error) {
    if (axios.isAxiosError(error)) {
    console.error(`HTTP ${error.response?.status}: ${error.response?.data?.message}`);
    console.error(`Error code: ${error.response?.data?.error_code}`);
    }
    }
    import axios from 'axios';
    import { STORAGE_AXIOS_INSTANCE } from '@musallam/storage-and-collaboration-client';

    // Add custom headers
    STORAGE_AXIOS_INSTANCE.defaults.headers.common['X-Custom-Header'] = 'value';

    // Add request interceptor
    STORAGE_AXIOS_INSTANCE.interceptors.request.use((config) => {
    console.log(`Making request to ${config.url}`);
    return config;
    });

    // Add response interceptor
    STORAGE_AXIOS_INSTANCE.interceptors.response.use(
    (response) => response,
    (error) => {
    console.error('Request failed:', error.message);
    return Promise.reject(error);
    }
    );
    STORAGE_AXIOS_INSTANCE.defaults.timeout = 30000; // 30 seconds
    

    All types are automatically generated from the OpenAPI spec:

    import type {
    ProjectAsset,
    FolderAsset,
    FileAsset,
    JobStatus,
    PaginatedProjectsResponseResponse,
    } from '@musallam/storage-and-collaboration-client';

    const project: ProjectAsset = await StorageAndCollaborationClient.createProject({
    name: 'Typed Project',
    });

    const status: JobStatus = await StorageAndCollaborationClient.getJobStatus({
    jobId: 'job-id',
    });

    MIT