JSPM

linode-s3-utils

1.0.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q23031F
  • License MIT

Clean, intuitive class-based S3-compatible object storage utilities with named parameters for Linode Object Storage and AWS S3

Package Exports

  • linode-s3-utils
  • linode-s3-utils/s3Utils.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (linode-s3-utils) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

linode-s3-utils v1.0

Intuitive class-based S3-compatible object storage utilities with named parameters for Linode Object Storage and AWS S3.

✨ Features

  • Class-based approach - Create once, use everywhere
  • Named parameters - Self-documenting object-based API
  • Environment variable support - Auto-configuration from env vars
  • Auto content-type detection - Infers MIME types from file extensions
  • Flexible configuration - Works with Linode Object Storage and AWS S3
  • Clean error handling - Consistent success/error response format

Installation

npm install linode-s3-utils

Quick Start

const S3Utils = require('linode-s3-utils')

// Create an S3 instance with your configuration
const s3 = new S3Utils({
  region: 'us-east-1',
  accessKeyId: 'your-access-key',
  secretAccessKey: 'your-secret-key'
})

// Upload a file - self-documenting and clear!
const result = await s3.uploadFile({
  filePath: './myfile.jpg',
  key: 'uploads/myfile.jpg',
  bucket: 'my-bucket',
  contentType: 'image/jpeg',
  acl: 'public-read'
})

console.log(result.publicUrl)

// Generate presigned URL for client uploads
const presignedUrl = await s3.getPresignedUploadUrl({
  key: 'uploads/photo.jpg',
  bucket: 'my-bucket',
  contentType: 'image/jpeg',
  expiresIn: 300
})

// Delete an object
await s3.deleteObject({
  key: 'old-file.jpg',
  bucket: 'my-bucket'
})

Environment Variables

Set environment variables and create instance without config:

export LINODE_BUCKET_REGION=us-east-1
export LINODE_S3_ACCESS_KEY=your-access-key
export LINODE_S3_SECRET_KEY=your-secret-key
const S3Utils = require('linode-s3-utils')
const s3 = new S3Utils() // Uses environment variables automatically

const result = await s3.uploadData({
  data: 'Hello World!',
  key: 'files/hello.txt',
  bucket: 'my-bucket',
  contentType: 'text/plain'
})

API Reference

Constructor

const s3 = new S3Utils(config)

Parameters:

  • config.region (string): AWS/Linode region
  • config.accessKeyId (string): Access key ID
  • config.secretAccessKey (string): Secret access key
  • config.endpoint (string, optional): Custom endpoint (auto-generated for Linode)
  • config.forcePathStyle (boolean, optional): Force path-style addressing (default: true)

Methods

s3.uploadFile(params)

Upload a file from the local filesystem.

const result = await s3.uploadFile({
  filePath: './photo.jpg',
  key: 'photos/photo.jpg',
  bucket: 'my-bucket',
  contentType: 'image/jpeg',     // optional, auto-detected
  acl: 'public-read',            // optional, default: 'public-read'
  metadata: {                    // optional
    'uploaded-by': 'user123',
    'category': 'profile-pics'
  }
})

if (result.success) {
  console.log('File uploaded:', result.publicUrl)
}

Parameters:

  • params.filePath (string): Local path to the file
  • params.key (string): Object key (path) in the bucket
  • params.bucket (string): Bucket name
  • params.contentType (string, optional): MIME type (auto-detected if not provided)
  • params.acl (string, optional): Access control list (default: 'public-read')
  • params.metadata (object, optional): Additional metadata to store with the object

s3.uploadData(params)

Upload data (Buffer or string) directly.

const result = await s3.uploadData({
  data: 'Hello World!',
  key: 'files/hello.txt',
  bucket: 'my-bucket',
  contentType: 'text/plain',
  acl: 'private',                // optional
  metadata: {                    // optional
    'source': 'api-generated'
  }
})

Parameters:

  • params.data (Buffer|string): Data to upload
  • params.key (string): Object key (path) in the bucket
  • params.bucket (string): Bucket name
  • params.contentType (string): MIME type
  • params.acl (string, optional): Access control list (default: 'public-read')
  • params.metadata (object, optional): Additional metadata to store with the object

s3.getPresignedUploadUrl(params)

Generate a presigned URL for client-side uploads.

const uploadUrl = await s3.getPresignedUploadUrl({
  key: 'uploads/user-photo.jpg',
  bucket: 'my-bucket',
  contentType: 'image/jpeg',
  expiresIn: 300,                // 5 minutes
  acl: 'public-read'
})

Parameters:

  • params.key (string): Object key (path) in the bucket
  • params.bucket (string): Bucket name
  • params.contentType (string, optional): MIME type (auto-detected if not provided)
  • params.expiresIn (number, optional): URL expiration time in seconds (default: 180)
  • params.acl (string, optional): Access control list (default: 'public-read')

s3.deleteObject(params)

Delete an object.

const result = await s3.deleteObject({
  key: 'old-file.jpg',
  bucket: 'my-bucket'
})

Parameters:

  • params.key (string): Object key to delete
  • params.bucket (string): Bucket name

s3.getPublicUrl(key, bucket)

Get public URL for an object.

const url = s3.getPublicUrl('photos/photo.jpg', 'my-bucket')

Usage Patterns

Pattern 1: Single Instance for Entire App

// utils/s3.js
const S3Utils = require('linode-s3-utils')

const s3 = new S3Utils({
  region: process.env.LINODE_BUCKET_REGION,
  accessKeyId: process.env.LINODE_S3_ACCESS_KEY,
  secretAccessKey: process.env.LINODE_S3_SECRET_KEY,
})

module.exports = s3
// anywhere in your app
const s3 = require('./utils/s3')
const result = await s3.uploadFile({
  filePath: './file.jpg',
  key: 'uploads/file.jpg',
  bucket: 'my-bucket'
})

Pattern 2: Application-Specific Manager

class AppS3Manager {
  constructor() {
    this.s3 = new S3Utils({ /* config */ })
    this.bucketName = 'my-app-bucket'
  }
  
  async uploadUserAvatar(userId, imageBuffer, mimeType) {
    return await this.s3.uploadData({
      data: imageBuffer,
      key: `users/${userId}/avatar.${mimeType.split('/')[1]}`,
      bucket: this.bucketName,
      contentType: mimeType,
      metadata: { 'user-id': userId, 'type': 'avatar' }
    })
  }
  
  async generateUserUploadUrl(userId, fileName, mimeType) {
    return await this.s3.getPresignedUploadUrl({
      key: `users/${userId}/uploads/${fileName}`,
      bucket: this.bucketName,
      contentType: mimeType,
      expiresIn: 600
    })
  }
}

const appS3 = new AppS3Manager()
module.exports = appS3

Pattern 3: Express Route Integration

const S3Utils = require('linode-s3-utils')
const s3 = new S3Utils({ /* config */ })

router.post('/upload', async (req, res) => {
  const result = await s3.uploadData({
    data: req.file.buffer,
    key: `uploads/${req.file.originalname}`,
    bucket: 'my-bucket',
    contentType: req.file.mimetype,
    metadata: {
      'uploaded-by': req.user.id,
      'upload-time': new Date().toISOString()
    }
  })
  
  if (result.success) {
    res.json({ url: result.publicUrl })
  } else {
    res.status(500).json({ error: result.error })
  }
})

Why Named Parameters?

Comparison: Positional vs Named Parameters

Traditional Approach (Confusing):

// Hard to remember order, unclear what each parameter does
await uploadFile('./file.jpg', 'uploads/file.jpg', 'my-bucket', 'image/jpeg', 'public-read')

Our Approach (Clear):

// Self-documenting, clear, order-independent
await s3.uploadFile({
  filePath: './file.jpg',
  key: 'uploads/file.jpg',
  bucket: 'my-bucket',
  contentType: 'image/jpeg',
  acl: 'public-read'
})

Benefits:

  • Self-documenting - parameter names make it clear what each value is
  • Order independent - can specify parameters in any order
  • Optional parameters - easy to omit optional parameters
  • IDE support - better autocomplete and IntelliSense
  • Less error-prone - harder to mix up parameter order
  • Future-proof - easy to add new parameters without breaking changes

Error Handling

All methods return objects with a success boolean:

const result = await s3.uploadFile({
  filePath: './file.jpg',
  key: 'file.jpg',
  bucket: 'bucket'
})

if (result.success) {
  console.log('Success:', result.publicUrl)
} else {
  console.error('Error:', result.error)
}

Supported File Types

Auto-detection for common extensions:

  • Images: jpg, jpeg, png, gif
  • Documents: pdf, txt, json, html, css, js
  • Media: mp3, mp4, mov, wav

License

MIT