npm.io
0.1.17 • Published 9 months ago

thru-mft-webcomponents

Licence
Version
0.1.17
Deps
8
Size
183 kB
Vulns
1
Weekly
0

Thru MFT Web Components

A collection of web components for file upload functionality, built with Preact and TypeScript. These components provide a robust, resumable file upload experience with progress tracking, error handling, and more.

Features

  • Resumable File Uploads: Automatically resume interrupted uploads
  • Chunked File Transfers: Files are split into chunks for efficient uploading
  • Progress Tracking: Real-time upload progress with speed and time estimations
  • Drag-and-Drop Support: User-friendly file selection interface
  • Conflict Resolution: Handles file conflicts with options to resume or overwrite
  • Auto-Upload: Configure whether uploads start automatically
  • Error Handling: Comprehensive error reporting and recovery options
  • Upload Cancellation: Ability to cancel uploads in progress
  • Upload Interceptor: Modify upload context before an upload begins
  • Multiple File Uploads: Support for uploading multiple files simultaneously
  • Server Path Selection: Choose from available server paths or automatically use the first one
  • Customizable Retry Logic: Configure retry attempts and delays for failed uploads

Installation

CDN Usage

Add the following to your HTML:

<script type="module" src="https://cdn.jsdelivr.net/npm/thru-mft-webcomponents/dist/assets/main.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/thru-mft-webcomponents/dist/assets/main.css" />
NPM Installation
npm install thru-mft-webcomponents
# or
yarn add thru-mft-webcomponents
# or
pnpm add thru-mft-webcomponents

Usage

Thru Upload Web Component

The thru-upload web component provides resumable file upload functionality with progress tracking and error handling.

<thru-upload
  api-key="your-api-key"
  flow-endpoint-id="123"
  api-url="https://your-api-url.com/api"
  auto-upload="true"
  assume-first-server-path="false"
  min-retry-delay="1000"
  retry-attempts="3"
></thru-upload>
Attributes
Attribute Type Required Default Description
api-key string Yes - Your API key for authentication
flow-endpoint-id number Yes - ID of the flow endpoint to upload to
api-url string Yes - Base URL of your API
auto-upload boolean No true Whether to start upload automatically when files are selected
assume-first-server-path boolean No false Whether to automatically use the first available server path
min-retry-delay number No - Minimum delay between retry attempts in milliseconds
retry-attempts number No - Maximum number of retry attempts for failed uploads
Events

The component dispatches the following custom events:

  • thru-upload-completed: Fired when an upload is completed successfully

    window.addEventListener("thru-upload-completed", (e) => {
      console.log(e.detail) // Contains upload details including id and uploadContext
    })
  • upload-files-added: Fired when files are added to the upload queue

    window.addEventListener("upload-files-added", (e) => {
      console.log(e.detail.files) // Contains file details
    })
Methods

The component exposes the following methods:

  • triggerUploads(): Manually trigger the upload of selected files
    const uploadedFiles = await document.querySelector("thru-upload").triggerUploads()
Upload Interceptor

You can add an upload interceptor to modify the upload context before the upload begins:

const thruUploadElement = document.querySelector("thru-upload")
thruUploadElement.uploadInterceptor = async (context) => {
  // Modify context as needed
  context.filePath = "custom/path"
  return context
}
Resume Upload Logic

The component automatically handles resuming uploads in case of interruptions:

  1. Upload sessions are saved in localStorage with key upload-session-{flowEndpointId}-{fileName}-{fileSize}
  2. When the component is initialized, it checks for existing upload sessions
  3. For incomplete uploads, it presents options to resume or restart the upload
  4. When resuming, it retrieves the last uploaded chunk from the server and continues from there
Upload Lifecycle

The upload process follows these states:

  1. Initial: Upload is being prepared
  2. Waiting: Ready to start upload
  3. In-progress: Upload is ongoing, showing progress, speed, and time remaining
  4. Assembling: All chunks uploaded, server is assembling the file
  5. Completed: Upload successfully completed
  6. Error: Error occurred during upload (with retry option)
FileUpload Component (React/Preact)

The FileUpload component provides a resumable file upload functionality with progress tracking and error handling.

import { FileUpload } from "thru-mft-webcomponents"

// In your component:
<FileUpload
  id="unique-upload-id"
  fileToUpload={file}
  abortController={new AbortController()}
  initialUploadContext={{
    flowEndpointId: number,
    serverPath: string,
    fileName: string,
    fileSize: number,
    filePath: string
  }}
  updateState={(updatedFile) => {
    // Handle state updates
  }}
  autoUpload={true}
  retryDelayMs={1000} // Optional
  retryAttempts={3} // Optional
/>
Props
Prop Type Required Description
id string Yes Unique identifier for the upload
fileToUpload File Yes The file to be uploaded
abortController AbortController Yes Controller for handling upload cancellation
initialUploadContext ResumableUploadContext Yes Initial context for the upload
updateState (file: any) => void Yes Callback for state updates
autoUpload boolean Yes Whether to start upload automatically
retryDelayMs number No Delay between retry attempts in milliseconds
retryAttempts number No Maximum number of retry attempts
UploadModal Component (React/Preact)

The UploadModal component provides a modal interface for file uploads with drag-and-drop support.

import { UploadModal } from "thru-mft-webcomponents"

// In your component:
<UploadModal
  selectedFlowEndpointId={123}
  flowEnabled={true}
  getUploadInterceptor={() => {
    // Return your interceptor function
  }}
  autoUpload={true}
  assumeFirstServerPath={true}
  retryDelayMs={1000} // Optional
  retryAttempts={3} // Optional
/>
Props
Prop Type Required Description
selectedFlowEndpointId number Yes ID of the selected flow endpoint
flowEnabled boolean Yes Whether the flow is enabled
getUploadInterceptor () => Function Yes Function to get the upload interceptor
autoUpload boolean Yes Whether to start upload automatically
assumeFirstServerPath boolean Yes Whether to assume the first server path
retryDelayMs number No Delay between retry attempts in milliseconds
retryAttempts number No Maximum number of retry attempts

Implementation Guide

Basic HTML Implementation
  1. Add the required scripts and styles to your HTML page:
<script type="module" src="https://cdn.jsdelivr.net/npm/thru-mft-webcomponents/dist/assets/main.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/thru-mft-webcomponents/dist/assets/main.css" />
  1. Add the web component to your HTML:
<thru-upload
  api-key="your-api-key"
  flow-endpoint-id="123"
  api-url="https://your-api-url.com/api"
></thru-upload>
  1. Optionally, add event listeners for upload events:
document.addEventListener("DOMContentLoaded", () => {
  window.addEventListener("thru-upload-completed", (e) => {
    console.log("Upload completed:", e.detail)
  })
})
Advanced Usage
Triggering Uploads Manually

If you set auto-upload="false", you'll need to trigger uploads manually:

// Get the upload component
const uploadComponent = document.querySelector("thru-upload")

// Trigger uploads when a button is clicked
document.querySelector("#upload-button").addEventListener("click", async () => {
  const results = await uploadComponent.triggerUploads()
  console.log("Upload results:", results)
})
Custom Upload Interception

Implement an upload interceptor to modify upload context:

const uploadComponent = document.querySelector("thru-upload")

uploadComponent.uploadInterceptor = async (context) => {
  // Add metadata or modify paths
  context.filePath = `user_${userId}/${context.filePath}`
  
  // You can make API calls here if needed
  const additionalData = await fetchUserUploadPreferences()
  
  // Return the modified context
  return {
    ...context,
    ...additionalData
  }
}
React/Next.js Integration

When using with React or Next.js:

import { useEffect, useRef } from "react"

// Load the web component scripts
useEffect(() => {
  const script = document.createElement("script")
  script.src = "https://cdn.jsdelivr.net/npm/thru-mft-webcomponents/dist/assets/main.js"
  script.type = "module"
  document.head.appendChild(script)
  
  const link = document.createElement("link")
  link.rel = "stylesheet"
  link.href = "https://cdn.jsdelivr.net/npm/thru-mft-webcomponents/dist/assets/main.css"
  document.head.appendChild(link)
  
  return () => {
    document.head.removeChild(script)
    document.head.removeChild(link)
  }
}, [])

// Component that uses the web component
const FileUploader = ({ apiKey, flowEndpointId, apiUrl }) => {
  const uploadRef = useRef(null)
  
  useEffect(() => {
    if (uploadRef.current) {
      // Set up interceptor
      uploadRef.current.uploadInterceptor = (context) => {
        // Modify context
        return context
      }
      
      // Listen for completion events
      const handleUploadComplete = (e) => {
        console.log("Upload completed:", e.detail)
      }
      
      window.addEventListener("thru-upload-completed", handleUploadComplete)
      
      return () => {
        window.removeEventListener("thru-upload-completed", handleUploadComplete)
      }
    }
  }, [uploadRef.current])
  
  return (
    <div>
      <thru-upload
        ref={uploadRef}
        api-key={apiKey}
        flow-endpoint-id={flowEndpointId}
        api-url={apiUrl}
        auto-upload="true"
      ></thru-upload>
      
      <button onClick={() => uploadRef.current?.triggerUploads()}>
        Upload Files
      </button>
    </div>
  )
}

Technical Details

ResumableUploadContext

The upload context contains all the information needed for the upload:

type ResumableUploadContext = {
  flowCode: string
  endpointCode: string
  flowEndpointId: number
  serverPath: string
  fileName: string
  filePath: string
  fileSize: number
  lastUploadedChunkIndex?: number
  sessionUID?: string
  reportId?: string
  chunkSize?: number
  outcome?: {
    success: boolean
    error?: any
  }
}
Chunked Upload Process

Files are uploaded in chunks of 100MB by default:

const CHUNK_SIZE = 100 * 1024 * 1024 // 100MB

The upload process:

  1. Create an upload session
  2. Upload chunks sequentially
  3. Track upload progress
  4. Commit the session when all chunks are uploaded
  5. Handle errors and allow retries
CSS Customization

The component uses CSS variables for styling that can be overridden:

:root {
  --primary-color: #4051a5;
  --primary-color-bg: rgba(64, 81, 165, 0.1);
  --primary-color-dark: #062491;
  --off-theme-color: #415362;
  --off-theme-color-accent: #5f778a;
  --error-color: #d93025;
  --theme-delete-color: #d93025;
  --loader-color-bg: #e6e6e6;
}