JSPM

@atomfe/oss-uploader

1.1.3
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 10
  • Score
    100M100P100Q65446F
  • License MIT

A powerful OSS uploader for uploading files to Aliyun OSS

Package Exports

  • @atomfe/oss-uploader
  • @atomfe/oss-uploader/package.json

Readme

oss-uploader Logo

oss-uploader

npm downloads license CI Coverage TypeScript Node.js Dual Module

🚀 A powerful OSS uploader for uploading files to Aliyun OSS 🚀

Simple, Fast, and Reliable - Perfect for your deployment workflow

English | įŽ€äŊ“中文


✨ Features

  • 🚀 Simple - One command to upload files
  • đŸ“Ļ Batch Upload - Support directory recursive upload
  • 🔐 Secure - Multiple config file formats, safe credential storage
  • đŸŽ¯ Flexible - Glob pattern file filtering
  • 📊 Progress - Real-time upload progress and statistics
  • đŸ—ēī¸ Mapping File - Auto-generate local-to-OSS URL mapping
  • 🔑 Content Hash - Automatic cache with 8-char content hash
  • đŸ› ī¸ Complete - Upload, list, delete, and more operations
  • đŸ’Ē TypeScript - Written in TypeScript with full type safety
  • ⚡ Modern - Dual format (ESM/CJS) with latest toolchain
  • 🔄 Compatible - Works in both CommonJS and ES Module projects

đŸ“Ļ Installation

npm install -g @atomfe/oss-uploader
# or
pnpm add -g @atomfe/oss-uploader
# or
yarn global add @atomfe/oss-uploader

🚀 Quick Start

Option 1: JSON Configuration

# 1. Initialize configuration (JSON)
oss-uploader init

# 2. Edit .ossrc.json with your credentials
{
  "region": "YOUR_REGION",
  "accessKeyId": "YOUR_ACCESS_KEY_ID",
  "accessKeySecret": "YOUR_ACCESS_KEY_SECRET",
  "bucket": "YOUR_BUCKET_NAME"
}

# 3. Upload files
oss-uploader upload ./file.txt
oss-uploader upload ./dist -t static/
# 1. Initialize JavaScript configuration
oss-uploader init -o oss.config.js

# 2. Set environment variables or edit oss.config.js
export OSS_REGION="oss-cn-hangzhou"
export OSS_ACCESS_KEY_ID="your-access-key-id"
export OSS_ACCESS_KEY_SECRET="your-access-key-secret"
export OSS_BUCKET="your-bucket-name"

# 3. Upload files
oss-uploader upload ./file.txt
oss-uploader upload ./dist -t static/

📖 Usage

Commands

# Upload file(s) or directory
oss-uploader upload <sources...> [options]

# List files in OSS bucket
oss-uploader list [prefix]

# Delete file from OSS
oss-uploader delete <path>

# Show bucket information
oss-uploader info

# Create sample configuration
oss-uploader init [options]

# Options for init command:
#   -o, --output <path>  Output path for configuration file (default: .ossrc.json)
#   -t, --type <type>    Configuration file type: json or js

Upload Options

Option Description
-t, --target <path> Target path in OSS bucket
-c, --config <path> Configuration file path
-r, --recursive Upload directory recursively (default: true)
-o, --overwrite Overwrite existing files (default: true)
-i, --include <patterns...> Include file patterns (glob)
-e, --exclude <patterns...> Exclude file patterns (glob)
-v, --verbose Show verbose output
-m, --mapping [path] Generate upload mapping file (default: .oss-uploader-mapping.json)
--no-mapping Do not generate upload mapping file
-h, --content-hash Add content hash to filename (default: true)
--no-content-hash Do not add content hash to filename

Examples

# Upload single file
oss-uploader upload ./image.png

# Upload multiple files (batch upload)
oss-uploader upload ./file1.js ./file2.css ./image.png

# Upload multiple files to specific directory
oss-uploader upload ./image1.png ./image2.jpg ./logo.svg -t images/2024/

# Upload to specific directory
oss-uploader upload ./image.png -t images/2024/

# Upload directory with patterns
oss-uploader upload ./dist -i "**/*.js" "**/*.css"

# Exclude files
oss-uploader upload ./dist -e "**/*.map" "**/test/**"

# Verbose mode
oss-uploader upload ./dist -v

# Generate custom mapping file
oss-uploader upload ./dist -m ./upload-map.json

# Don't generate mapping file
oss-uploader upload ./dist --no-mapping

# Upload with content hash (default behavior)
oss-uploader upload ./dist
# Result: file.js → file.a1b2c3d4.js

# Upload without content hash
oss-uploader upload ./dist --no-content-hash
# Result: file.js → file.js

# Mix files and directories (batch upload)
oss-uploader upload ./src/file1.js ./src/file2.css ./assets

📊 Progress Display

The tool displays real-time progress during uploads with two modes:

Default Mode (Progress Bar)

For batch uploads, a beautiful progress bar is displayed showing:

  • ✅ Upload progress percentage
  • 📈 Completed/Total file count
  • 📄 Current file being uploaded
Upload Progress |████████████████████░░░░░░| 75% | 15/20 Files | src/components/Button.tsx

Verbose Mode (-v)

Use -v or --verbose option to see detailed upload information for each file:

oss-uploader upload ./dist -v

Sample output:

✓ Uploaded: src/index.js → static/index.js (24.5 KB)
✓ Uploaded: src/styles.css → static/styles.css (12.3 KB)
...

🔐 Content Hash Feature

By default, the uploader adds an 8-character content hash to filenames (similar to webpack's chunkhash), providing cache-busting capabilities for your assets.

How It Works

The tool generates an MD5 hash from the file content and appends the first 8 characters before the file extension:

Original:  app.js
Uploaded:  app.a1b2c3d4.js

Original:  style.min.css
Uploaded:  style.min.e5f6g7h8.css

Benefits

  • ✅ Cache Busting - Automatically invalidate browser cache when file content changes
  • 🔄 Version Control - Same content always generates the same hash
  • 🚀 CDN Friendly - Perfect for CDN cache management
  • đŸ“Ļ Build Pipeline - Works seamlessly with modern build tools

Usage

# Default: Content hash enabled
oss-uploader upload ./dist
# app.js → app.a1b2c3d4.js

# Disable content hash
oss-uploader upload ./dist --no-content-hash
# app.js → app.js

# With programmatic API
import { OSSUploader } from '@atomfe/oss-uploader';

const uploader = new OSSUploader(config);

// With content hash (default)
await uploader.upload({
  source: './dist',
  target: 'static/',
  contentHash: true  // default
});

// Without content hash
await uploader.upload({
  source: './dist',
  target: 'static/',
  contentHash: false
});

Use Cases

  • 🌐 Static Site Deployment - Ensure visitors get the latest version
  • 📱 SPA Applications - Reliable asset updates for single-page apps
  • 🔧 Microservices - Consistent versioning across services
  • đŸ“Ļ Library Distribution - Track different versions of published assets

đŸ—ēī¸ Upload Mapping File

After each upload, the tool automatically generates a .oss-uploader-mapping.json file in the current directory with detailed information about all uploaded files:

{
  "uploadTime": "2025-10-18T10:30:00.000Z",
  "bucket": "my-bucket",
  "region": "YOUR_REGION",
  "totalFiles": 10,
  "totalSize": 1024000,
  "files": [
    {
      "localPath": "/path/to/local/file.js",
      "remotePath": "static/file.js",
      "url": "https://my-bucket.YOUR_REGION.aliyuncs.com/static/file.js",
      "size": 1024,
      "uploadTime": "2025-10-18T10:30:00.000Z"
    }
  ]
}

Use Cases

  • 📝 Record Keeping - Keep complete records of each upload
  • 🔗 Quick Access - Get URLs for all uploaded files
  • 📊 Analytics - Analyze upload statistics
  • 🔄 CI/CD Integration - Use mapping info in build pipelines
  • 📱 CDN Configuration - Configure CDN cache rules easily

âš™ī¸ Configuration

The tool supports multiple configuration sources:

Priority Order: Config file first, fallback to Environment variables

Note: If a config file exists, it will be used exclusively. Environment variables are only used when no config file is found.

Configuration Sources

  1. Config Files (searched in order):

    • .ossrc / .ossrc.json
    • .ossrc.yaml / .ossrc.yml
    • oss.config.js / oss.config.json
    • oss field in package.json
  2. Environment Variables:

    • OSS_REGION
    • OSS_ACCESS_KEY_ID
    • OSS_ACCESS_KEY_SECRET
    • OSS_BUCKET
    • OSS_ENDPOINT (optional)
    • OSS_INTERNAL (optional, true/false)
    • OSS_SECURE (optional, true/false)
    • OSS_TIMEOUT (optional, in milliseconds)

Configuration Fields

Field Required Description
region ✅ OSS region (e.g., oss-cn-hangzhou)
accessKeyId ✅ AccessKey ID
accessKeySecret ✅ AccessKey Secret
bucket ✅ Bucket name
endpoint ❌ Custom endpoint
internal ❌ Use internal network
secure ❌ Use HTTPS (default: true)
timeout ❌ Timeout in ms (default: 60000)

Example: .ossrc.json

{
  "region": "YOUR_REGION",
  "accessKeyId": "YOUR_ACCESS_KEY_ID",
  "accessKeySecret": "YOUR_ACCESS_KEY_SECRET",
  "bucket": "my-bucket"
}

Example: oss.config.js

Generate JavaScript config with oss-uploader init -o oss.config.js

ESM format (with fallback values):

export default {
  region: process.env.OSS_REGION || 'YOUR_REGION',
  accessKeyId: process.env.OSS_ACCESS_KEY_ID || 'YOUR_ACCESS_KEY_ID',
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET || 'YOUR_ACCESS_KEY_SECRET',
  bucket: process.env.OSS_BUCKET || 'YOUR_BUCKET_NAME',
  
  // Optional fields
  // endpoint: process.env.OSS_ENDPOINT,
  // internal: process.env.OSS_INTERNAL === 'true',
  secure: true,
  timeout: 60000,
};

CommonJS format:

module.exports = {
  region: process.env.OSS_REGION || 'YOUR_REGION',
  accessKeyId: process.env.OSS_ACCESS_KEY_ID || 'YOUR_ACCESS_KEY_ID',
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET || 'YOUR_ACCESS_KEY_SECRET',
  bucket: process.env.OSS_BUCKET || 'YOUR_BUCKET_NAME',
  secure: true,
  timeout: 60000,
};

Example: Using Environment Variables Only

# Set environment variables
export OSS_REGION="YOUR_REGION"
export OSS_ACCESS_KEY_ID="your-access-key-id"
export OSS_ACCESS_KEY_SECRET="your-access-key-secret"
export OSS_BUCKET="my-bucket"

# Optional environment variables
export OSS_SECURE="true"
export OSS_TIMEOUT="60000"

# Now you can use the CLI without a config file
oss-uploader upload ./dist -t static/

# Note: If a config file exists, it will be used instead of environment variables

🔧 Programmatic Usage

ESM (ES Modules)

import { OSSUploader, loadConfig } from 'oss-uploader';

const config = await loadConfig();
const uploader = new OSSUploader(config);

const results = await uploader.upload({
  source: './dist',
  target: 'static/',
  recursive: true,
  overwrite: true,
  verbose: true,
  generateMapping: true,
});

console.log('Upload results:', results);

CommonJS

const { OSSUploader, loadConfig } = require('oss-uploader');

(async () => {
  const config = await loadConfig();
  const uploader = new OSSUploader(config);

  const results = await uploader.upload({
    source: './dist',
    target: 'static/',
    recursive: true,
    overwrite: true,
    verbose: true,
    generateMapping: true,
  });

  console.log('Upload results:', results);
})();

đŸŽ¯ Use Cases

Frontend Deployment

npm run build
oss-uploader upload ./dist -t static/my-app/

CI/CD Integration

# GitHub Actions - Using environment variables (recommended)
- name: Upload to OSS
  env:
    OSS_REGION: ${{ secrets.OSS_REGION }}
    OSS_ACCESS_KEY_ID: ${{ secrets.OSS_ACCESS_KEY_ID }}
    OSS_ACCESS_KEY_SECRET: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
    OSS_BUCKET: ${{ secrets.OSS_BUCKET }}
  run: |
    npm install -g @atomfe/oss-uploader
    oss-uploader upload ./dist -t static/

# Alternative: Using config file
- name: Upload to OSS
  run: |
    npm install -g @atomfe/oss-uploader
    echo '{"region":"${{ secrets.OSS_REGION }}","accessKeyId":"${{ secrets.OSS_ACCESS_KEY_ID }}","accessKeySecret":"${{ secrets.OSS_ACCESS_KEY_SECRET }}","bucket":"${{ secrets.OSS_BUCKET }}"}' > .ossrc.json
    oss-uploader upload ./dist -t static/

Package.json Scripts

{
  "scripts": {
    "deploy": "npm run build && oss-uploader upload ./dist -t static/"
  }
}

Using Mapping File

// Read mapping file
import mapping from './.oss-uploader-mapping.json' assert { type: 'json' };

// Get all uploaded URLs
const urls = mapping.files.map(f => f.url);

// Update resource references in HTML
const updateHTML = html => {
  mapping.files.forEach(file => {
    html = html.replace(
      new RegExp(file.localPath, 'g'),
      file.url
    );
  });
  return html;
};

🔐 Security

  • ✅ Add .ossrc.json to .gitignore
  • ✅ Use RAM sub-account instead of root account
  • ✅ Use environment variables in CI/CD
  • ✅ Rotate AccessKey regularly
  • ❌ Never hardcode credentials in code

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

For bug reports or feature requests, please create an issue.

📝 Development

# Install dependencies
pnpm install

# Development mode
pnpm run dev

# Build
pnpm run build

# Test
pnpm run test
pnpm run test:coverage

# Lint & Format
pnpm run lint
pnpm run format

🆕 Changelog

See CHANGELOG.md for version history.

📄 License

MIT Š 2025

🌟 Core Features

Modern Technology Stack

  • ✅ Dual Module Format - Support both ESM and CommonJS
  • ✅ TypeScript 5.7 - Full type safety
  • ✅ tsup Build - Ultra-fast builds with esbuild
  • ✅ Vitest Testing - Modern test framework
  • ✅ npm Provenance - Supply chain security

Developer Experience

  • đŸ”Ĩ Fast Build - Lightning-fast 0.05s builds
  • 🎨 Code Quality - ESLint + Prettier
  • 📊 Test Coverage - Unit tests + coverage reports
  • 🔄 Auto Release - Automated version management with Changesets
  • 📚 Complete Docs - Bilingual documentation (EN/CN)

💡 Tips & Tricks

1. Using Environment Variables

export OSS_ACCESS_KEY_ID="your-key"
export OSS_ACCESS_KEY_SECRET="your-secret"
export OSS_BUCKET="your-bucket"
export OSS_REGION="YOUR_REGION"

2. Batch Process Mapping Files

# Merge multiple mapping files
cat .oss-uploader-mapping-*.json | jq -s 'map(.files) | add' > all-uploads.json

3. Automated Deployment Script

#!/bin/bash
# deploy.sh

# Build project
npm run build

# Upload to OSS
oss-uploader upload ./dist -t "static/v$(date +%Y%m%d)/" -v

# Read mapping file and send notification
node -e "
const mapping = require('./.oss-uploader-mapping.json');
console.log(\`✅ Upload complete! Total \${mapping.totalFiles} files\`);
console.log(\`đŸ“Ļ Total size: \${(mapping.totalSize / 1024 / 1024).toFixed(2)} MB\`);
"

Made with â¤ī¸ by lorainwings