Skip to content

API reference

Core Functions

uplnk(options): Promise<void>

Executes a single HTTP upload. Resolves when the request completes successfully (2xx); rejects with an UploadError on failure.

Options

OptionTypeRequiredDefaultDescription
urlstringYesDestination URL (e.g. signed URL).
fileFile | BlobYesThe payload to upload.
method'PUT' | 'POST' | 'PATCH'No'PUT'HTTP method.
headersRecord<string, string>No{}Request headers.
withCredentialsbooleanNofalseSend cookies / credentials.
signalAbortSignalNoAbort the in-flight upload.
timeoutMsnumberNoAbort after this many milliseconds.
progressProgressOptionsNoThrottle and lifecycle of progress events.
onProgress(progress: UploadProgress) => voidNoProgress callback.
onStart(xhr: XMLHttpRequest) => voidNoCalled before send().
onResponse(xhr: XMLHttpRequest) => voidNoCalled on completion (before the promise resolves).
onError(err: UploadError, xhr?: XMLHttpRequest) => voidNoCalled before the promise rejects.
retryRetryOptionsNoRetry configuration (opt-in).

Batch Upload Functions

batchUpload(uploads, options): Promise<BatchUploadResult>

Upload multiple files concurrently with progress tracking and concurrency control.

ts
const uploads = files.map((file, i) => ({
  url: signedUrls[i],
  file,
}));

const result = await batchUpload(uploads, {
  concurrency: 5,
  onProgress: (p) => console.log(`${p.percent}% (${p.completed}/${p.total})`),
  onItemError: (item) => console.error(`Failed: ${item.id}`, item.error),
});

console.log(`${result.successful} succeeded, ${result.failed} failed`);

Batch Options

OptionTypeDefaultDescription
concurrencynumber3Maximum concurrent uploads.
onProgress(progress: BatchProgress) => voidCalled when batch progress changes.
onItemComplete(item: BatchUploadItem) => voidCalled when an upload completes.
onItemError(item: BatchUploadItem) => voidCalled when an upload fails.
stopOnErrorbooleanfalseStop all uploads on first error.
signalAbortSignalAbort all uploads.

sequentialUpload(uploads, options): Promise<BatchUploadResult>

Upload files one at a time (concurrency: 1).

ts
const result = await sequentialUpload(uploads, {
  onProgress: (p) => updateProgressBar(p.percent),
  stopOnError: true,
});

createUploadQueue(options): UploadQueue

Create a dynamic upload queue that can be controlled at runtime.

ts
const queue = createUploadQueue({
  concurrency: 3,
  onProgress: (p) => console.log(`${p.percent}%`),
});

queue.add({ url: url1, file: file1 });
queue.add({ url: url2, file: file2 });

await queue.start();

// Add more while running
queue.add({ url: url3, file: file3 });

await queue.waitForCompletion();

Retry Strategies

exponentialBackoff(options?): RetryOptions

Retry with exponential backoff and optional jitter.

ts
await uplnk({
  url,
  file,
  retry: exponentialBackoff({
    maxAttempts: 5,
    baseDelayMs: 1000,
    maxDelayMs: 30000,
    jitter: true,
  }),
});

fixedDelay(options?): RetryOptions

Retry with fixed delay between attempts.

ts
await uplnk({
  url,
  file,
  retry: fixedDelay({ delayMs: 2000, maxAttempts: 5 }),
});

networkErrorsOnly(options?): RetryOptions

Only retry network errors (not HTTP errors).

ts
await uplnk({
  url,
  file,
  retry: networkErrorsOnly({ maxAttempts: 3 }),
});

customRetry(options): RetryOptions

Create a fully custom retry strategy.

ts
await uplnk({
  url,
  file,
  retry: customRetry({
    attempts: 5,
    shouldRetry: (err, attempt) => {
      if (err.type === "http" && err.status === 503) {
        return attempt < 3;
      }
      return err.type === "network";
    },
    getDelay: (attempt) => 1000 * (attempt + 1),
  }),
});

Validation Functions

validateFile(file, options): ValidationError | null

Validate file before upload with size, type, and custom checks.

ts
const error = validateFile(file, {
  maxSize: 10 * 1024 * 1024, // 10MB
  allowedTypes: ["image/png", "image/jpeg"],
  customValidator: (file) => {
    if (file.name.includes("test")) {
      return { type: "custom", message: "Test files not allowed" };
    }
    return null;
  },
});

if (error) {
  alert(formatValidationError(error));
}

validateSize(file, options): ValidationError | null

Validate file size only.

ts
const error = validateSize(file, {
  maxSize: 5 * 1024 * 1024, // 5MB
  minSize: 1024, // 1KB
});

validateType(file, options): ValidationError | null

Validate file type by MIME type or extension.

ts
const error = validateType(file, {
  allowedTypes: ["image/png", "image/jpeg"],
  allowedExtensions: [".png", ".jpg", ".jpeg"],
});

formatValidationError(error): string

Convert validation error to human-readable message.

ts
const error = validateFile(file, { maxSize: 5000000 });
if (error) {
  alert(formatValidationError(error));
  // "File size (10 MB) exceeds maximum allowed size (5 MB)"
}

formatBytes(bytes, decimals?): string

Format bytes into human-readable size.

ts
formatBytes(1536); // "1.5 KB"
formatBytes(1048576); // "1 MB"

File Type Presets

Use FILE_TYPE_PRESETS for common file types:

ts
import { validateFile, FILE_TYPE_PRESETS } from "@uplnk/core";

validateFile(file, {
  allowedTypes: FILE_TYPE_PRESETS.images,
  // ["image/png", "image/jpeg", "image/jpg", "image/gif", "image/webp", "image/svg+xml"]
});

Available presets: images, videos, audio, documents, archives.

File Size Presets

Use FILE_SIZE_PRESETS for common size limits:

ts
import { validateFile, FILE_SIZE_PRESETS } from "@uplnk/core";

validateFile(file, {
  maxSize: FILE_SIZE_PRESETS["10MB"],
});

Available presets: 1MB, 5MB, 10MB, 50MB, 100MB, 500MB, 1GB.


Types

UploadProgress

FieldTypeDescription
loadednumberBytes uploaded so far.
totalnumber | undefinedTotal bytes when computable.
percentnumber | undefined0–100.
speednumber | undefinedBytes per second.
etanumber | undefinedEstimated seconds remaining.

ProgressOptions

FieldTypeDefaultDescription
throttleMsnumber100Minimum ms between progress callbacks.
emitOnStartbooleantrueEmit initial 0% progress.
emitOnEndbooleantrueEmit final 100% progress.

UploadError

ts
type UploadError =
  | { type: "abort" }
  | { type: "timeout" }
  | { type: "network" }
  | { type: "http"; status: number; response?: string };

Example:

ts
try {
  await uplnk({ url, file });
} catch (err) {
  if (err.type === "timeout") console.log("retry or notify user");
}

RetryOptions

FieldTypeDescription
attemptsnumberMax attempts (including the first).
delayMsnumber | ((attempt: number) => number)Delay before the next attempt. Can be fixed or dynamic.
shouldRetry(err: UploadError, attempt: number) => booleanReturn true to retry.

Example:

ts
retry: {
  attempts: 3,
  delayMs: 1000,
  shouldRetry: (err, attempt) => err.type === "network",
}

Signed URLs may expire

Use retries only when appropriate; signed URLs may expire.

BatchProgress

FieldTypeDescription
totalnumberTotal number of uploads.
completednumberNumber of completed uploads.
failednumberNumber of failed uploads.
pendingnumberNumber of pending uploads.
uploadingnumberNumber of currently uploading.
percentnumberOverall completion percentage (0-100).
totalBytesnumberTotal bytes across all uploads.
uploadedBytesnumberUploaded bytes across all uploads.

BatchUploadItem

FieldTypeDescription
idstringUnique identifier.
status'pending' | 'uploading' | 'completed' | 'failed'Current status.
optionsUplnkOptionsUpload options.
progressUploadProgress?Current progress.
errorUploadError?Error if failed.
completedAtnumber?Completion timestamp.

BatchUploadResult

FieldTypeDescription
itemsBatchUploadItem[]All upload items with final status.
successfulnumberNumber of successful uploads.
failednumberNumber of failed uploads.
abortedbooleanWhether the batch was aborted.

ValidationError

ts
type ValidationError =
  | { type: "size-too-large"; maxSize: number; actualSize: number }
  | { type: "size-too-small"; minSize: number; actualSize: number }
  | { type: "invalid-type"; allowedTypes: string[]; actualType: string }
  | { type: "custom"; message: string };

FileValidationOptions

FieldTypeDescription
maxSizenumber?Maximum file size in bytes.
minSizenumber?Minimum file size in bytes.
allowedTypesstring[]?Allowed MIME types.
allowedExtensionsstring[]?Allowed file extensions.
customValidator((file: File | Blob) => ValidationError | null)?Custom validation function.