SonusLab StorageSonusLab Storage

Server SDK

StorageClient runs on your backend and authenticates with your API key. Use it to mint upload URLs, manage files, and run multipart uploads.

Server-only

The API key must never be exposed to the browser. Always import from sonuslab-storage/server in a server-only file (Nitro server/api, Node script, edge function).

Constructor

import { StorageClient } from 'sonuslab-storage/server'

const storage = new StorageClient({
  apiKey: process.env.SONUSLAB_STORAGE_API_KEY!,
})
ParameterTypeDescription
apiKeyrequiredstringsl_... token from the app Keys tab.
baseUrlstringDefaults to https://storage-api.sonuslab.dev. Override only when self-hosting.
fetch(typeof fetch)?Override the fetch implementation (Cloudflare Workers, tests, etc).

Self-hosting

Running your own storage-api? Pass baseUrl: 'https://storage-api.yourdomain.com' to point the SDK at your deployment.

storage.upload(input)

Upload bytes directly from your server. Best for small files (< single PUT limit).

const file = await storage.upload({
  name: 'report.pdf',
  contentType: 'application/pdf',
  data: pdfBuffer,
  metadata: { userId: 'abc' },
})
ParameterTypeDescription
namerequiredstringOriginal file name (visible in the dashboard).
contentTyperequiredstringMIME type — must match the actual bytes.
datarequiredBuffer | Uint8Array | BlobThe file contents.
metadataRecord<string, string>Arbitrary key/value pairs stored alongside the file.
storage.presign(input)

Mint a short-lived upload URL for the browser.

const presign = await storage.presign({
  name: 'avatar.png',
  size: file.size,
  contentType: 'image/png',
})

// presign.uploadUrl  → short-lived upload URL (browser PUTs to it)
// presign.fileId     → opaque id used for completeUpload()
// presign.key        → final object key
ParameterTypeDescription
namerequiredstringOriginal file name.
sizerequirednumberByte size of the file. Validated against the app maxFileSize.
contentTyperequiredstringMIME type.
metadataRecord<string, string>Stored on the file once the upload finalizes.
storage.completeUpload({ fileId })

Finalize a presigned upload after the browser PUT succeeds.

const file = await storage.completeUpload({ fileId: presign.fileId })
ParameterTypeDescription
fileIdrequiredstringThe id returned by presign().
storage.initMultipart(input)

Start a multipart upload session (server-side, for large files).

const init = await storage.initMultipart({
  name: 'movie.mp4',
  size: file.size,
  contentType: 'video/mp4',
})

// init.uploadId, init.key, init.fileId
ParameterTypeDescription
namerequiredstringOriginal file name.
sizerequirednumberTotal file size in bytes.
contentTyperequiredstringMIME type.
metadataRecord<string, string>Stored on the file once completed.
storage.presignMultipartPart(uploadId, key, partNumber)

Mint an upload URL for one part of a multipart upload.

const { uploadUrl, partNumber } =
  await storage.presignMultipartPart(init.uploadId, init.key, 1)
storage.completeMultipart(input)

Finalize a multipart upload after all parts succeed.

const file = await storage.completeMultipart({
  uploadId: init.uploadId,
  key: init.key,
  fileId: init.fileId,
  parts: [{ partNumber: 1, etag: '...' }, ...],
})
ParameterTypeDescription
uploadIdrequiredstringFrom initMultipart.
keyrequiredstringFrom initMultipart.
fileIdrequiredstringFrom initMultipart.
partsrequired{ partNumber, etag }[]Ordered list of completed parts.
storage.abortMultipart(uploadId, key, fileId)

Abort a multipart upload (call this if the user cancels).

await storage.abortMultipart(init.uploadId, init.key, init.fileId)
storage.listFiles({ limit?, cursor?, search? })

Paginated list of files in the app.

const { items, nextCursor } = await storage.listFiles({
  limit: 50,
  search: 'avatar',
})

while (cursor) {
  const page = await storage.listFiles({ cursor })
  // ...
}
ParameterTypeDescription
limitnumberPage size. Default 50, max 200.
cursorstringOpaque pagination token from a previous call.
searchstringSubstring match against file name.
storage.getFile(id)

Fetch a single file by id.

const file = await storage.getFile('file_abc')
storage.deleteFile(id)

Soft-delete a file. Recoverable through the grace window, then permanently removed.

await storage.deleteFile('file_abc')