
Research
/Security News
Mini Shai-Hulud Campaign Hits Red Hat Cloud Services npm Packages
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.
@yofix/storage
Advanced tools
Universal storage manager for handling file operations across S3, GCS, R2, DigitalOcean Spaces, Firebase, and GitHub Actions
Universal storage manager for handling file operations across multiple cloud providers. Upload files to GitHub Actions Artifacts, Firebase Storage, AWS S3, or local filesystem with a unified API.
npm install @yofix/storage
or
yarn add @yofix/storage
import { uploadFiles } from '@yofix/storage'
const result = await uploadFiles({
storage: {
provider: 'local',
config: {
directory: './uploads',
createIfNotExists: true
}
},
files: [
'package.json',
'dist/**/*',
{
path: 'README.md',
destination: 'docs/README.md'
}
],
verbose: true
})
console.log(`Uploaded ${result.metadata.totalFiles} files`)
const result = await uploadFiles({
storage: {
provider: 'github',
config: {
artifactName: 'build-artifacts',
retentionDays: 30
}
},
files: ['dist/**/*', 'coverage/**/*'],
verbose: true
})
const result = await uploadFiles({
storage: {
provider: 'firebase',
config: {
bucket: 'your-project.appspot.com',
credentials: JSON.parse(process.env.FIREBASE_CREDENTIALS),
basePath: 'uploads'
}
},
files: ['images/**/*.{jpg,png}'],
verbose: true
})
const result = await uploadFiles({
storage: {
provider: 's3',
config: {
region: 'us-east-1',
bucket: 'your-bucket',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
basePath: 'uploads',
acl: 'public-read'
}
},
files: [
{
path: 'build/app.js',
destination: 'static/app.js',
metadata: {
version: '1.0.0'
}
}
],
onProgress: (progress) => {
console.log(`${progress.filesUploaded}/${progress.totalFiles}`)
}
})
name: Upload Artifacts
on:
push:
branches: [main]
jobs:
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
- name: Upload to GitHub Artifacts
uses: yofix/storage@main
with:
provider: github
files: 'dist/**/*,coverage/**/*'
artifact-name: 'build-artifacts'
retention-days: 30
verbose: true
- name: Upload to S3
uses: yofix/storage@main
with:
provider: s3
files: 'dist/**/*'
s3-region: us-east-1
s3-bucket: my-bucket
s3-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
s3-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
s3-base-path: builds/${{ github.sha }}
s3-acl: public-read
verbose: true
uploadFiles(options: StorageOptions): Promise<StorageResult>Main function to upload files to storage.
interface StorageOptions {
storage: ProviderConfig
files?: (string | FileToUpload)[]
overwrite?: boolean
verbose?: boolean
onProgress?: (progress: UploadProgress) => void
}
type ProviderConfig =
| { provider: 'github'; config?: GitHubConfig }
| { provider: 'firebase'; config: FirebaseConfig }
| { provider: 's3'; config: S3Config }
| { provider: 'local'; config: LocalConfig }
interface StorageResult {
success: boolean
files: UploadedFile[]
metadata: {
provider: StorageProvider
totalFiles: number
totalSize: number
duration: number
startedAt: string
completedAt: string
artifactInfo?: {
artifactName: string
artifactId?: string
size: number
}
bucketInfo?: {
bucket: string
basePath?: string
region?: string
}
}
errors?: StorageError[]
}
interface GitHubConfig {
artifactName?: string // Default: 'storage-artifacts'
retentionDays?: number // 1-90, Default: 90
}
interface FirebaseConfig {
projectId?: string
credentials?: string | object // Service account JSON
bucket: string // Required
basePath?: string
}
interface S3Config {
region: string // Required
bucket: string // Required
accessKeyId?: string
secretAccessKey?: string
basePath?: string
acl?: string // e.g., 'public-read', 'private'
endpoint?: string // For S3-compatible services
}
interface LocalConfig {
directory: string // Required
createIfNotExists?: boolean // Default: true
}
See the demo.js file for complete examples:
# Install dependencies
npm install
# Build the project
npm run build
# Run demos
npm run demo # Local storage (default)
node demo.js s3 # S3 storage
node demo.js firebase # Firebase storage
node demo.js github # GitHub Actions (requires GITHUB_ACTIONS env)
node demo.js all # Run all demos
const result = await uploadFiles({
storage: { provider: 'local', config: { directory: './uploads' } },
files: [
{
path: 'src/app.js',
destination: 'build/app.min.js',
contentType: 'application/javascript',
metadata: {
version: '1.0.0',
environment: 'production'
}
}
]
})
const result = await uploadFiles({
storage: { provider: 's3', config: {...} },
files: ['large-files/**/*'],
onProgress: (progress) => {
const percent = (progress.filesUploaded / progress.totalFiles) * 100
console.log(`Progress: ${percent.toFixed(1)}%`)
console.log(`Current: ${progress.currentFile}`)
}
})
import { StorageManager } from '@yofix/storage'
const manager = new StorageManager({
storage: { provider: 'local', config: { directory: './uploads' } },
files: ['*.json'],
verbose: true
})
// Upload files
const result = await manager.upload()
// Check if file exists
const exists = await manager.fileExists('package.json')
// List files
const files = await manager.listFiles()
// Delete file
await manager.deleteFile('old-file.txt')
For convenience, you can use environment variables:
# AWS S3
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
# Firebase
export FIREBASE_CREDENTIALS='{"type":"service_account",...}'
# Or use in code
const result = await uploadFiles({
storage: {
provider: 's3',
config: {
region: 'us-east-1',
bucket: 'my-bucket',
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
}
},
files: ['dist/**/*']
})
Full TypeScript support with comprehensive type definitions:
import type {
StorageOptions,
StorageResult,
ProviderConfig,
UploadedFile,
StorageError
} from '@yofix/storage'
try {
const result = await uploadFiles({...})
if (!result.success) {
result.errors?.forEach(error => {
console.error(`[${error.code}] ${error.message}`)
if (error.file) {
console.error(`File: ${error.file}`)
}
})
}
} catch (error) {
console.error('Upload failed:', error)
}
MIT
Contributions are welcome! Please open an issue or submit a pull request on GitHub.
FAQs
Universal storage manager for handling file operations across S3, GCS, R2, DigitalOcean Spaces, Firebase, and GitHub Actions
The npm package @yofix/storage receives a total of 2 weekly downloads. As such, @yofix/storage popularity was classified as not popular.
We found that @yofix/storage demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.

Security News
The Rust project is moving toward formal rules on LLM use in contributions after months of internal debate over maintainer burden, code quality, and contributor experience.