Member Junction
    Preparing search index...

    FileStorageBase implementation for Microsoft SharePoint using the Microsoft Graph API

    This provider allows working with files stored in SharePoint document libraries. It uses the Microsoft Graph API and client credentials authentication flow to securely access and manipulate SharePoint files and folders.

    This implementation requires the following environment variables:

    • STORAGE_SHAREPOINT_CLIENT_ID - Azure AD application (client) ID
    • STORAGE_SHAREPOINT_CLIENT_SECRET - Azure AD application client secret
    • STORAGE_SHAREPOINT_TENANT_ID - Azure AD tenant ID
    • STORAGE_SHAREPOINT_SITE_ID - The SharePoint site ID
    • STORAGE_SHAREPOINT_DRIVE_ID - The ID of the document library (drive)
    • STORAGE_SHAREPOINT_ROOT_FOLDER_ID (optional) - ID of a subfolder to use as the root

    To use this provider, you need to:

    1. Register an Azure AD application with appropriate Microsoft Graph API permissions (typically Files.ReadWrite.All and Sites.ReadWrite.All)
    2. Create a client secret for the application
    3. Grant admin consent for the permissions
    4. Find your SharePoint site ID and document library (drive) ID using the Microsoft Graph Explorer
    // Set required environment variables before creating the provider
    process.env.STORAGE_SHAREPOINT_CLIENT_ID = 'your-client-id';
    process.env.STORAGE_SHAREPOINT_CLIENT_SECRET = 'your-client-secret';
    process.env.STORAGE_SHAREPOINT_TENANT_ID = 'your-tenant-id';
    process.env.STORAGE_SHAREPOINT_SITE_ID = 'your-site-id';
    process.env.STORAGE_SHAREPOINT_DRIVE_ID = 'your-drive-id';

    // Create the provider
    const storage = new SharePointFileStorage();

    // Upload a file
    const fileContent = Buffer.from('Hello, SharePoint!');
    await storage.PutObject('documents/hello.txt', fileContent, 'text/plain');

    // Download a file
    const downloadedContent = await storage.GetObject('documents/hello.txt');

    // Get a temporary download URL
    const downloadUrl = await storage.CreatePreAuthDownloadUrl('documents/hello.txt');

    Hierarchy (View Summary)

    Index

    Constructors

    Properties

    _accountId: string

    The ID of the FileStorageAccount this driver instance is operating for. Set during initialization via the config parameter.

    _accountName: string

    The name of the FileStorageAccount (for logging/display purposes).

    providerName: "SharePoint" = 'SharePoint'

    The name of this storage provider

    Accessors

    • get AccountId(): string

      Gets the account ID this driver instance is operating for. Returns undefined if the driver was not initialized with an account.

      Returns string

    • get AccountName(): string

      Gets the account name this driver instance is operating for. Returns undefined if the driver was not initialized with an account.

      Returns string

    • get IsConfigured(): boolean

      Checks if SharePoint provider is properly configured. Returns true if the Graph client is initialized and has required IDs. Logs detailed error messages if configuration is incomplete.

      Returns boolean

    • get SupportsStreaming(): boolean

      SharePoint supports ranged streaming: the Microsoft Graph driveItem @microsoft.graph.downloadUrl is a short-lived pre-authenticated URL that honors the HTTP Range header.

      Returns boolean

    Methods

    • Copies a file from one location to another

      This method creates a copy of a file at a new location. The original file remains unchanged.

      Parameters

      • sourceObjectName: string

        Path to the source file (e.g., 'templates/report-template.docx')

      • destinationObjectName: string

        Path where the copy should be created (e.g., 'documents/new-report.docx')

      Returns Promise<boolean>

      A Promise that resolves to true if successful, false if an error occurs

      • The parent folder of the destination must exist
      • Both files and folders can be copied
      • The operation is asynchronous in SharePoint and may not complete immediately
      // Copy a file to a new location with a different name
      const copyResult = await storage.CopyObject(
      'templates/financial-report.xlsx',
      'reports/2024/q1-financial-report.xlsx'
      );

      if (copyResult) {
      console.log('File copied successfully');
      } else {
      console.error('Failed to copy file');
      }
    • Creates a directory (folder) in SharePoint

      This method creates a new folder at the specified path. The parent directory must already exist.

      Parameters

      • directoryPath: string

        Path where the directory should be created (e.g., 'documents/new-folder')

      Returns Promise<boolean>

      A Promise that resolves to true if successful, false if an error occurs

      • If a folder with the same name already exists, the operation will fail
      • The parent directory must exist for the operation to succeed
      • Trailing slashes in the path are automatically removed
      // Create a new folder
      const createResult = await storage.CreateDirectory('documents/2024-reports');

      if (createResult) {
      console.log('Folder created successfully');

      // Now we can put files in this folder
      await storage.PutObject(
      'documents/2024-reports/q1-results.xlsx',
      fileContent,
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      );
      } else {
      console.error('Failed to create folder');
      }
    • Creates a pre-authenticated download URL for an object

      This method generates a time-limited, publicly accessible URL that can be used to download a file without authentication. The URL expires after 10 minutes.

      Parameters

      • objectName: string

        Path to the object to create a download URL for (e.g., 'documents/report.pdf')

      Returns Promise<string>

      A Promise that resolves to the pre-authenticated download URL

      Error if the object doesn't exist or the URL creation fails

      // Generate a pre-authenticated download URL that will work for 10 minutes
      const downloadUrl = await storage.CreatePreAuthDownloadUrl('presentations/quarterly-update.pptx');
      console.log(`Download the file using this URL: ${downloadUrl}`);

      // You can share this URL with users who don't have SharePoint access
      // The URL will expire after 10 minutes
    • Creates a pre-authenticated upload URL (not supported in SharePoint)

      This method is not supported for SharePoint storage as SharePoint doesn't provide a way to generate pre-authenticated upload URLs like object storage services. Instead, use the PutObject method for file uploads.

      Parameters

      • objectName: string

        The object name (path) to create a pre-auth URL for

      Returns Promise<CreatePreAuthUploadUrlPayload>

      UnsupportedOperationError always, as this operation is not supported

      // This will throw an UnsupportedOperationError
      try {
      await storage.CreatePreAuthUploadUrl('documents/report.docx');
      } catch (error) {
      if (error instanceof UnsupportedOperationError) {
      console.log('Pre-authenticated upload URLs are not supported in SharePoint.');
      // Use PutObject instead
      await storage.PutObject('documents/report.docx', fileContent, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
      }
      }
    • Deletes a directory (folder) and optionally its contents

      This method deletes a folder from SharePoint. By default, it will only delete empty folders unless the recursive parameter is set to true.

      Parameters

      • directoryPath: string

        Path to the directory to delete (e.g., 'archive/old-reports')

      • recursive: boolean = false

        If true, delete the directory and all its contents; if false, only delete if empty

      Returns Promise<boolean>

      A Promise that resolves to true if successful, false if an error occurs

      • If recursive=false and the directory contains files, the operation will fail
      • SharePoint deleted items may be recoverable from the recycle bin depending on site settings
      • Trailing slashes in the path are automatically removed
      // Attempt to delete an empty folder
      const deleteResult = await storage.DeleteDirectory('temp/empty-folder');

      // Delete a folder and all its contents
      const recursiveDeleteResult = await storage.DeleteDirectory('archive/old-data', true);

      if (recursiveDeleteResult) {
      console.log('Folder and all its contents deleted successfully');
      } else {
      console.error('Failed to delete folder');
      }
    • Deletes an object (file) from SharePoint

      This method permanently deletes a file from SharePoint storage. Note that deleted files may be recoverable from the SharePoint recycle bin depending on your SharePoint configuration.

      Parameters

      • objectName: string

        Path to the object to delete (e.g., 'documents/old-report.docx')

      Returns Promise<boolean>

      A Promise that resolves to true if successful, false if an error occurs

      • Returns true if the object doesn't exist (for idempotency)
      • Handles 404 errors by returning true since the end result is the same
      // Delete a file
      const deleteResult = await storage.DeleteObject('temp/draft-document.docx');

      if (deleteResult) {
      console.log('File deleted successfully or already didn\'t exist');
      } else {
      console.error('Failed to delete file');
      }
    • Checks if a directory exists

      This method verifies whether a folder exists at the specified path. Unlike ObjectExists, this method also checks that the item is a folder.

      Parameters

      • directoryPath: string

        Path to check (e.g., 'documents/reports')

      Returns Promise<boolean>

      A Promise that resolves to true if the directory exists, false otherwise

      • Returns false if the path exists but points to a file instead of a folder
      • Trailing slashes in the path are automatically removed
      // Check if a directory exists before creating a file in it
      const dirExists = await storage.DirectoryExists('documents/reports');

      if (!dirExists) {
      // Create the directory first
      await storage.CreateDirectory('documents/reports');
      }

      // Now we can safely put a file in this directory
      await storage.PutObject('documents/reports/annual-summary.pdf', fileContent, 'application/pdf');
    • Downloads a file's contents

      This method retrieves the raw content of a file as a Buffer.

      Parameters

      • params: GetObjectParams

        Object identifier (prefer objectId for performance, fallback to fullPath)

      Returns Promise<Buffer>

      A Promise that resolves to a Buffer containing the file's contents

      Error if the file doesn't exist or cannot be downloaded

      • This method uses the Graph API's download URL to retrieve the file contents
      • The method will throw an error if the object is a folder
      • For large files, consider using CreatePreAuthDownloadUrl instead
      try {
      // Fast path: Use objectId (SharePoint item ID)
      const fileContent = await storage.GetObject({ objectId: '01BYE5RZ6QN3VYRVNHHFDK2QJODWDDFR4E' });

      // Slow path: Use path
      const fileContent2 = await storage.GetObject({ fullPath: 'documents/notes.txt' });

      // Convert Buffer to string for text files
      const textContent = fileContent.toString('utf8');
      console.log('File content:', textContent);

      // For binary files, you can write the buffer to a local file
      // or process it as needed
      } catch (error) {
      console.error('Error downloading file:', error.message);
      }
    • Gets metadata for a file or folder

      This method retrieves metadata information about a file or folder, such as its name, size, content type, and last modified date.

      Parameters

      Returns Promise<StorageObjectMetadata>

      A Promise that resolves to a StorageObjectMetadata object

      Error if the object doesn't exist or cannot be accessed

      try {
      // Fast path: Use objectId (SharePoint item ID)
      const metadata = await storage.GetObjectMetadata({ objectId: '01BYE5RZ6QN3VYRVNHHFDK2QJODWDDFR4E' });

      // Slow path: Use path
      const metadata2 = await storage.GetObjectMetadata({ fullPath: 'presentations/quarterly-update.pptx' });

      console.log(`Name: ${metadata.name}`);
      console.log(`Size: ${metadata.size} bytes`);
      console.log(`Content Type: ${metadata.contentType}`);
      console.log(`Last Modified: ${metadata.lastModified}`);
      console.log(`Is Directory: ${metadata.isDirectory}`);
      } catch (error) {
      console.error('Error getting metadata:', error.message);
      }
    • Streams a file's content from SharePoint, optionally honoring a byte range.

      Resolves the driveItem (fast path via objectId, slow path via fullPath), reads its @microsoft.graph.downloadUrl (a short-lived pre-authenticated URL), and fetches that URL with the inclusive Range encoded via BuildHttpRangeHeader. The fetch response body is a web ReadableStream, converted to a Node Readable via Readable.fromWeb so it is never buffered fully in memory. Content-Type, Content-Length, and (for ranged reads) Content-Range are read straight off the HTTP response headers, falling back to the item's size for the total when the server doesn't return a Content-Range.

      Parameters

      Returns Promise<ObjectStreamResult>

      A Promise resolving to an ObjectStreamResult.

      Error if the file doesn't exist or cannot be streamed.

    • Initialize SharePoint storage provider with optional configuration.

      ALWAYS call this method after creating a provider instance.

      Constructor loads credentials from environment variables, then call initialize() with no config to complete setup:

      Parameters

      • Optionalconfig: SharePointOAuthConfig

        Configuration object containing OAuth2 credentials from database

      Returns Promise<void>

      const storage = new SharePointFileStorage(); // Constructor loads env vars
      await storage.initialize(); // No config - uses env vars
      await storage.ListObjects('/'); // Ready to use

      Use infrastructure utility which handles credential decryption automatically:

      const storage = await initializeDriverWithAccountCredentials({
      accountEntity: accountWithProvider.account,
      providerEntity: accountWithProvider.provider,
      contextUser
      });
      await storage.ListObjects('/'); // Credentials already decrypted and initialized
    • Lists objects in a given directory (folder)

      This method retrieves all files and subfolders in the specified directory. It returns both a list of object metadata and a list of directory prefixes.

      Parameters

      • prefix: string

        Path to the directory to list (e.g., 'documents/reports')

      • Optionaldelimiter: string

        Optional delimiter character (not used in this implementation)

      Returns Promise<StorageListResult>

      A Promise that resolves to a StorageListResult containing objects and prefixes

      • The objects array in the result includes both files and folders
      • The prefixes array includes only folder paths (with trailing slashes)
      • Returns empty arrays if the directory doesn't exist or an error occurs
      // List all files and folders in the 'documents' directory
      const result = await storage.ListObjects('documents');

      // Process files
      for (const obj of result.objects) {
      console.log(`Name: ${obj.name}, Size: ${obj.size}, Type: ${obj.isDirectory ? 'Folder' : 'File'}`);
      }

      // Process subfolders
      for (const prefix of result.prefixes) {
      console.log(`Subfolder: ${prefix}`);
      }
    • Moves an object from one location to another

      This method moves a file or folder from one location in SharePoint to another. It handles both renaming and changing the parent folder.

      Parameters

      • oldObjectName: string

        Current path of the object (e.g., 'old-folder/document.docx')

      • newObjectName: string

        New path for the object (e.g., 'new-folder/renamed-document.docx')

      Returns Promise<boolean>

      A Promise that resolves to true if successful, false otherwise

      // Move a file to a different folder
      const moveResult = await storage.MoveObject(
      'documents/old-report.pdf',
      'archive/2023/annual-report.pdf'
      );

      if (moveResult) {
      console.log('File moved successfully');
      } else {
      console.error('Failed to move file');
      }
    • Checks if a file or folder exists

      This method verifies whether an object (file or folder) exists at the specified path.

      Parameters

      • objectName: string

        Path to check (e.g., 'documents/report.pdf')

      Returns Promise<boolean>

      A Promise that resolves to true if the object exists, false otherwise

      // Check if a file exists before attempting to download it
      const exists = await storage.ObjectExists('presentations/quarterly-update.pptx');

      if (exists) {
      // File exists, proceed with download
      const fileContent = await storage.GetObject('presentations/quarterly-update.pptx');
      // Process the file...
      } else {
      console.log('File does not exist');
      }
    • Uploads a file to SharePoint

      This method uploads a file to SharePoint at the specified path. It automatically determines whether to use a simple upload or a chunked upload based on file size.

      Parameters

      • objectName: string

        Path where the file should be uploaded (e.g., 'documents/report.pdf')

      • data: Buffer

        Buffer containing the file content

      • OptionalcontentType: string

        Optional MIME type of the file (if not provided, it will be guessed from the filename)

      • Optionalmetadata: Record<string, string>

        Optional metadata to associate with the file (not used in SharePoint implementation)

      Returns Promise<boolean>

      A Promise that resolves to true if successful, false if an error occurs

      • Files smaller than 4MB use a simple upload
      • Files 4MB or larger use a chunked upload session for better reliability
      • Automatically creates the parent folder structure if it doesn't exist
      • If a file with the same name exists, it will be replaced
      // Create a text file
      const textContent = Buffer.from('This is a sample document', 'utf8');
      const uploadResult = await storage.PutObject(
      'documents/sample.txt',
      textContent,
      'text/plain'
      );

      // Upload a large file using chunked upload
      const largeFileBuffer = fs.readFileSync('/path/to/large-presentation.pptx');
      const largeUploadResult = await storage.PutObject(
      'presentations/quarterly-results.pptx',
      largeFileBuffer,
      'application/vnd.openxmlformats-officedocument.presentationml.presentation'
      );

      if (largeUploadResult) {
      console.log('Large file uploaded successfully');
      } else {
      console.error('Failed to upload large file');
      }
    • Search files in SharePoint using Microsoft Graph Search API.

      This method provides powerful search capabilities using KQL (Keyword Query Language), SharePoint's native query language. The search can target file names, metadata, and optionally file contents.

      Parameters

      • query: string

        The search query string. Can be plain text or use KQL syntax for advanced queries.

      • Optionaloptions: FileSearchOptions

        Optional search configuration including filters, limits, and content search

      Returns Promise<FileSearchResultSet>

      A Promise resolving to FileSearchResultSet with matched files and pagination info

      KQL Query Syntax Examples:

      • Simple text: "quarterly report" - searches for files containing these terms
      • Boolean operators: "budget AND 2024", "draft OR final", "report NOT internal"
      • Wildcards: "proj*" matches "project", "projection", etc.
      • Property filters: "FileType:pdf", "Author:John Smith", "Size>1000000"
      • Date filters: "Created>=2024-01-01", "LastModifiedTime<2024-12-31"
      • Proximity: "project NEAR report" - finds terms near each other
      • Exact phrases: "\"annual budget report\"" - exact phrase match

      Additional Filtering: The method automatically adds KQL filters based on the provided options:

      • fileTypes: Adds FileType filters (e.g., FileType:pdf OR FileType:docx)
      • modifiedAfter/modifiedBefore: Adds LastModifiedTime filters
      • pathPrefix: Adds Path filter to restrict search to a directory
      • searchContent: When false, restricts search to filename only
      // Simple text search in filenames
      const results = await storage.SearchFiles('quarterly report', {
      maxResults: 20
      });

      // Search for PDFs only
      const pdfResults = await storage.SearchFiles('budget', {
      fileTypes: ['pdf'],
      maxResults: 50
      });

      // Search with date range
      const recentResults = await storage.SearchFiles('meeting notes', {
      modifiedAfter: new Date('2024-01-01'),
      modifiedBefore: new Date('2024-12-31'),
      searchContent: true
      });

      // Search within specific directory
      const folderResults = await storage.SearchFiles('presentation', {
      pathPrefix: 'documents/reports',
      fileTypes: ['pptx', 'pdf']
      });

      // Advanced KQL query
      const advancedResults = await storage.SearchFiles(
      'FileType:xlsx AND Created>=2024-01-01 AND Author:"John Smith"',
      { maxResults: 100 }
      );
    • Helper method to throw an UnsupportedOperationError with appropriate context. This method simplifies implementation of methods not supported by specific providers.

      Parameters

      • methodName: string

        The name of the method that is not supported

      Returns never

      UnsupportedOperationError with information about the unsupported method and provider