This reference details all methods available on the StorageClient class, its fluent transformation builder, Cloudinary-compatible namespaces (.uploader and .api), and error classes.
Method Summary Table#
| Method | Description | Return Type |
|---|---|---|
new StorageClient(config) | Initialize a client instance with server endpoint and API credentials | StorageClient |
client.upload(file, options) | Ingest a file from disk path, Buffer, Blob, or stream using API key or token | Promise<AssetResult> / dict |
client.uploadWithToken(file, token, options) | Direct frontend/browser upload using signed upload token (zero API key) | Promise<AssetResult> / dict |
client.url(publicId, options?) | Construct transformed CDN URLs via fluent chaining or options dict | TransformationBuilder | string |
client.getPublicUrl(publicId) | Directly get the public CDN URL without transformation options | string |
client.getSignedUrl(publicId, options) | Generate time-limited expiring HMAC-SHA256 download URL for private files | Promise<string> / str |
client.createSignedUploadToken(options) | Generate signed authorization payload for direct browser-to-server uploads | Promise<SignedUploadResult> / dict |
client.listFiles(options) | Query assets with folder filtering, pagination, and sorting | Promise<FileListResult> / dict |
client.getResource(publicId) | Retrieve detailed metadata (dimensions, format, bytes, visibility) for an asset | Promise<AssetResult> / dict |
client.getFile(publicId) | Clean alias for getResource() to retrieve asset metadata | Promise<AssetResult> / dict |
client.updateAccess(publicId, access) | Toggle asset access between 'public' and 'private' | Promise<{ success: boolean }> |
client.delete(publicId) | Permanently delete an asset and invalidate all cached edge variations | Promise<{ success: boolean }> |
client.destroy(publicId) | Clean alias for delete() to remove asset and purge edge cache | Promise<{ success: boolean }> |
client.purgeCache() | Invalidate and purge all on-the-fly transformed image cache variants | Promise<{ success: boolean; purgedCount: number }> |
client.getStats() | Query cluster storage volume, total files, and bandwidth metrics | Promise<ServerStats> / dict |
client.healthCheck() | Check connectivity and response latency to your Storage Server cluster | Promise<HealthCheckResult> / dict |
client.uploader.* | Cloudinary drop-in write namespace (upload, destroy, delete) | Compatible methods |
client.api.* | Cloudinary drop-in admin namespace (resources, resource, update, usage) | Compatible methods |
1. Client Initialization: new StorageClient()#
Creates an instance of the DevCloudDesk Storage Client. Credentials can be passed explicitly or read automatically from environment variables.
Configuration Options#
| Option | Type | Default | Description |
|---|---|---|---|
endpoint | string | process.env.DCD_STORAGE_ENDPOINT | Base URL of your self-hosted Storage Server (e.g. https://cdn.mycompany.com) |
apiKey | string | process.env.DCD_STORAGE_API_KEY | Master API Key generated by your Storage Server |
timeoutMs | number | 30000 (30s) | Global request timeout in milliseconds (Node.js) |
timeout | int | 30 (30s) | Global request timeout in seconds (Python) |
deliveryPrefix | string | 'image/upload' | CDN delivery route prefix for transformed URLs |
import { StorageClient } from '@dcd-sdk/storage-client';
const storage = new StorageClient({
endpoint: 'https://cdn.mycompany.com',
apiKey: 'dcd_live_9a7bf3c0918e4726',
timeoutMs: 45000,
});2. client.upload(file, options)#
Uploads an image, video, PDF, or raw binary asset to your storage server with automatic magic-byte MIME validation.
Arguments#
| Argument | Type | Required | Description |
|---|---|---|---|
file | string | Buffer | Blob | File | Stream | bytes | Yes | Local file path, in-memory Buffer/bytes, Web Standard Blob/File, or ReadableStream |
options | UploadOptions | No | Additional upload metadata and access control settings |
UploadOptions Reference#
| Option | Type | Default | Description |
|---|---|---|---|
folder | string | Root "" | Target destination folder (e.g. 'products/shoes') |
filename | string | Original | Custom filename to assign on the server |
publicId / public_id | string | Auto | Explicit unique identifier path (without extension) |
access | 'public' | 'private' | 'public' | Access level. Private assets require HMAC signed URLs |
overwrite | boolean | true | Overwrite existing asset if public ID collides |
uniqueFilename / unique_filename | boolean | false | Append unique timestamp/random hash to avoid name collisions |
token | string | undefined | Short-lived signed upload token (allows upload without master API key) |
tags | string[] | [] | Searchable metadata tags to attach |
webhookUrl / webhook_url | string | undefined | Optional webhook URL notified on upload completion |
onProgress | (percent: number) => void | undefined | Progress callback for browser client uploads (0 to 100%) |
timeoutMs | number | 30000 | Custom timeout override for this upload in milliseconds |
Return Value (AssetResult)#
The storage server returns a dual-format JSON object compatible with both Cloudinary naming conventions and standard TypeScript camelCase:
{
"asset_id": "a1b2c3d4e5f6",
"public_id": "products/shoes/runner-10",
"version": 1761570000,
"version_id": "v_1761570000",
"width": 1200,
"height": 800,
"format": "jpg",
"resource_type": "image",
"bytes": 245678,
"url": "https://cdn.mycompany.com/image/upload/products/shoes/runner-10.jpg",
"secure_url": "https://cdn.mycompany.com/image/upload/products/shoes/runner-10.jpg",
"folder": "products/shoes",
"original_filename": "runner-10",
"display_name": "runner-10.jpg",
"created_at": "2026-10-27T08:30:00Z",
"tags": ["marketing", "q4-sale"],
"id": "a1b2c3d4e5f6",
"publicId": "products/shoes/runner-10",
"resourceType": "image",
"mimeType": "image/jpeg",
"access": "public",
"storageDriver": "local",
"secureUrl": "https://cdn.mycompany.com/image/upload/products/shoes/runner-10.jpg"
}3. client.uploadWithToken(file, token, options)#
Designed specifically for client-side environments (React, Next.js frontend, Vue, Mobile apps) or frontend microservices. Uploads directly to the storage server using a temporary signed upload token generated by your backend server—no master API key is ever exposed.
Arguments#
| Argument | Type | Required | Description |
|---|---|---|---|
file | File | Blob | Buffer | string | bytes | Yes | File input payload to upload |
token | string | Yes | Short-lived signed authorization token issued by createSignedUploadToken() |
options | Omit<UploadOptions, 'token'> | No | Additional options: folder, onProgress, timeoutMs, publicId, overwrite |
import { createStorageClient } from '@dcd-sdk/storage-client';
// Client initialization requires only the public endpoint (zero API key)
const storage = createStorageClient({
endpoint: 'https://cdn.mycompany.com',
});
// Upload using signed token obtained from your API backend:
const asset = await storage.uploadWithToken(fileFromInput, signedToken, {
folder: 'user-avatars',
onProgress: (percent) => {
console.log(`Upload progress: ${percent}%`);
},
});
console.log('Direct upload complete:', asset.publicId, asset.secure_url);4. client.url(publicId, options?)#
Generates on-the-fly CDN transformation URLs. When called with just publicId, returns a fluent TransformationBuilder. When called with an options dictionary, returns the finished URL string immediately.
Transformation Builder Methods#
| Builder Method | Arguments | Example | Description |
|---|---|---|---|
.resize(w, h, crop?) | width, height, crop | .resize(800, 600, 'fill') | Set dimensions and crop mode |
.width(w) | number | .width(400) | Target image width in pixels |
.height(h) | number | .height(300) | Target image height in pixels |
.crop(mode) | 'fill' | 'fit' | 'limit' | 'crop' | 'scale' | 'thumb' | .crop('fill') | Intelligent cropping / fitting algorithm |
.format(fmt) | 'webp' | 'avif' | 'jpg' | 'png' | 'auto' | .format('webp') | Output image encoding |
.quality(q) | number (1-100) | .quality(80) | Compression quality factor |
.blur(sigma) | number (1-100) | .blur(5) | Gaussian blur radius |
.sharpen(val) | boolean | number | .sharpen(2) | Unsharp mask filter |
.rotate(deg) | number | 'auto' | .rotate(90) | Rotation angle |
.build() / .to_string() | None | .build() | Compiles and returns final URL string |
// 1. Fluent Chaining Style:
const webpUrl = storage
.url('store/banners/hero')
.resize(800, 600, 'fill')
.format('webp')
.quality(85)
.build();
// 2. Direct Options Style:
const thumbUrl = storage.url('store/banners/hero', {
width: 200,
height: 200,
crop: 'thumb',
format: 'webp',
});5. client.getPublicUrl(publicId)#
Generates a clean CDN delivery URL for an asset without any transformation steps.
const rawUrl = storage.getPublicUrl('avatars/user-99.png');
// Output: https://cdn.mycompany.com/image/upload/avatars/user-99.png6. client.getSignedUrl(publicId, options)#
Generates an expiring HMAC-SHA256 authenticated URL for private assets (e.g. invoices, KYC IDs, contracts).
SignedDownloadOptions Reference#
| Option | Type | Default | Description |
|---|---|---|---|
expiresInSeconds | number | 900 (15 min) | Signature validity lifetime in seconds |
resourceType | 'image' | 'raw' | 'image' | Delivery pipeline (raw streams original bytes for PDF/ZIP) |
transform | string | object | undefined | Optional transformation string to sign along with the asset |
const downloadLink = await storage.getSignedUrl('billing/invoices/inv-2026.pdf', {
expiresInSeconds: 600, // 10 minutes TTL
resourceType: 'raw',
});
console.log('Secure Link:', downloadLink);7. client.createSignedUploadToken(options)#
Generates a cryptographically signed upload authorization token that allows client browsers or mobile applications to upload files directly to your storage server without proxying through your backend RAM. (Alias: client.createUploadToken(options)).
SignUploadOptions Reference#
| Option | Type | Default | Description |
|---|---|---|---|
folder | string | Root | Restricted destination folder where uploads are allowed |
maxBytes | number | 52428800 (50MB) | Maximum file size permitted for this token in bytes |
expiresInSeconds | number | 300 (5 min) | Token expiration lifetime |
access | 'public' | 'private' | 'public' | Access mode for the uploaded asset |
// In your backend route:
const token = await storage.createSignedUploadToken({
folder: `users/${userId}/documents`,
maxBytes: 15 * 1024 * 1024, // 15MB limit
expiresInSeconds: 300,
access: 'private',
});
return Response.json(token);8. client.listFiles(options)#
Queries assets stored on your server with pagination, folder filtering, and sort ordering. (Alias: client.list(options)).
FileListOptions Reference#
| Option | Type | Default | Description |
|---|---|---|---|
folder | string | "" | Filter results by folder prefix |
page | number | 1 | Page number (1-indexed) |
limit | number | 20 | Max items per page (up to 100) |
sortBy | 'created_at' | 'bytes' | 'public_id' | 'created_at' | Field to sort results by |
order | 'asc' | 'desc' | 'desc' | Sort direction |
const result = await storage.listFiles({
folder: 'marketing/campaigns',
page: 1,
limit: 25,
});
console.log(`Found ${result.pagination.total} files.`);
result.data.files.forEach((f) => console.log(f.publicId, f.bytes));9. client.getResource(publicId) & client.getFile(publicId)#
Fetches the comprehensive metadata document for a single stored asset. Both getResource and its clean alias getFile (get_file in Python) return the identical AssetResult object.
// Using getResource or clean alias getFile:
const meta = await storage.getFile('store/banners/hero');
console.log('Dimensions:', meta.width, 'x', meta.height);
console.log('Format:', meta.format);
console.log('Byte Size:', meta.bytes);
console.log('Storage Driver:', meta.storageDriver);10. client.updateAccess(publicId, access)#
Updates the access policy of an existing asset without re-uploading.
// Make a previously private asset public
await storage.updateAccess('documents/contract-101.pdf', 'public');11. client.delete(publicId) & client.destroy(publicId)#
Permanently deletes the original asset and all associated cached edge transformations from storage. Both delete and destroy accept the asset publicId.
const res = await storage.delete('store/banners/old-hero.png');
// Or using destroy alias:
// const res = await storage.destroy('store/banners/old-hero.png');
console.log('Deleted successfully:', res);12. client.purgeCache()#
Purges and invalidates all on-the-fly generated image transformation variations from server disk cache across your cluster. Does not affect original assets.
const result = await storage.purgeCache();
console.log('Purged cache variations:', result.purgedCount);13. client.getStats()#
Returns aggregated cluster storage usage, total assets indexed, and delivery statistics.
const stats = await storage.getStats();
console.log('Total Disk Used:', stats.totalBytes);
console.log('Total Asset Count:', stats.totalFiles);14. client.healthCheck()#
Pings the server's health monitoring endpoint to check reachability and response latency.
const health = await storage.healthCheck();
console.log('Server status:', health.status, 'Version:', health.version);15. Cloudinary .uploader Namespace#
Implements identical method signatures to Cloudinary's v2.uploader for zero-friction migration.
| Method | Cloudinary Equivalent | DevCloudDesk Implementation |
|---|---|---|
storage.uploader.upload(file, options) | cloudinary.v2.uploader.upload | Maps directly to client.upload() |
storage.uploader.destroy(publicId) | cloudinary.v2.uploader.destroy | Maps directly to client.delete() |
storage.uploader.delete(publicId) | cloudinary.v2.uploader.delete | Maps directly to client.delete() |
16. Cloudinary Admin .api Namespace#
Implements identical method signatures to Cloudinary's v2.api administration namespace.
| Method | Cloudinary Equivalent | DevCloudDesk Implementation |
|---|---|---|
storage.api.resources(options) | cloudinary.v2.api.resources | Maps directly to client.listFiles() |
storage.api.resource(publicId) | cloudinary.v2.api.resource | Maps directly to client.getResource() |
storage.api.update(publicId, opts) | cloudinary.v2.api.update | Maps directly to client.updateAccess() |
storage.api.delete_resources(ids) | cloudinary.v2.api.delete_resources | Batch deletes array of IDs |
storage.api.usage() | cloudinary.v2.api.usage | Maps directly to client.getStats() |
17. Error Classes Reference#
The SDK throws descriptive custom error subclasses that extend native Error:
| Error Class | HTTP Code | Cause |
|---|---|---|
AuthenticationError | 401 Unauthorized | Invalid or missing API key in configuration |
NotFoundError | 404 Not Found | The requested publicId does not exist on the server |
PayloadTooLargeError | 413 Payload Too Large | Upload file exceeds max upload limits or token limits |
NetworkTimeoutError | Client Timeout | Request exceeded specified timeoutMs |
StorageError | Generic | Base class for all DevCloudDesk SDK exceptions |
import {
StorageClient,
AuthenticationError,
NotFoundError,
PayloadTooLargeError,
} from '@dcd-sdk/storage-client';
try {
await storage.upload('./heavy-video.mp4');
} catch (err) {
if (err instanceof PayloadTooLargeError) {
console.error('File exceeds storage cluster limits.');
} else if (err instanceof AuthenticationError) {
console.error('Check your DCD_STORAGE_API_KEY credentials.');
} else {
console.error('Storage operation failed:', err.message);
}
}