npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@oneminutecloud/storage-bucket

v1.0.0

Published

Backend SDK for OneMinute Cloud Storage Bucket

Readme

@oneminutecloud/storage-bucket

Official backend SDK for OneMinute Cloud Storage Buckets.
Upload, confirm, and inspect files from any Node.js / JavaScript server-side environment — NestJS, Express, Fastify, Next.js API routes, and more.

npm version License: ISC Node.js >= 18


Table of Contents


Features

  • 🚀 Multipart-aware — handles chunked uploads transparently via a two-step initiate → confirm flow
  • 🔒 Secure by default — your API key is only used server-side; never exposed to the browser
  • 🌐 Framework-agnostic — works with any Node.js ≥ 18 server framework
  • 📦 Zero runtime dependencies — uses the native fetch API (Node 18+)
  • 🏷️ Fully typed — complete TypeScript definitions included (ESM + CJS dual build)

Requirements

| Requirement | Version | |---|---| | Node.js | ≥ 18.0.0 | | TypeScript (optional) | ≥ 5.0 |

Note: This is a server-side SDK. Never import or use it in client-side/browser bundles — your API key would be exposed.


Installation

# npm
npm install @oneminutecloud/storage-bucket

# yarn
yarn add @oneminutecloud/storage-bucket

# pnpm
pnpm add @oneminutecloud/storage-bucket

Quick Start

import { createStorageBucket } from "@oneminutecloud/storage-bucket";
import { readFileSync } from "fs";

// 1. Create a client instance
const bucket = createStorageBucket({
  apiKey: "OMC_your_api_key_here",
});

// 2. Read the file into a Buffer
const fileBuffer = readFileSync("./my-video.mp4");

// 3. Initiate the upload
const upload = await bucket.initiateUpload(fileBuffer, {
  bucketId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  duration: 120, // optional: video duration in seconds
});

// 4. Confirm (complete) the upload
const result = await bucket.confirmUpload({
  bucketId: upload.bucketId,
  objectId: upload.objectId,
  uploadId: upload.uploadId,
  key:      upload.key,
  parts:    upload.parts,
});

console.log("File stored at key:", result.key);

// 5. Retrieve file metadata any time
const meta = await bucket.getMeta(result.key);
console.log(meta);

API Reference

createStorageBucket

Factory function that returns a StorageBucket client instance.

const bucket = createStorageBucket(options: StorageBucketOptions): StorageBucket

| Option | Type | Required | Description | |---|---|---|---| | apiKey | string | ✅ | Your OneMinute Cloud API key. Must start with OMC_. |

Throws if apiKey is missing or has an invalid format.


initiateUpload

Registers a new object in the bucket and returns the multipart upload credentials.

const result = await bucket.initiateUpload(
  file: Buffer | Uint8Array,
  options: UploadFileOptions
): Promise<UploadFileResult>

Parameters

| Parameter | Type | Required | Description | |---|---|---|---| | file | Buffer \| Uint8Array | ✅ | Raw file data. | | options.bucketId | string (UUID) | ✅ | Target bucket ID from your OneMinute Cloud dashboard. | | options.duration | number | ❌ | Media duration in seconds (e.g. for video/audio). Defaults to 0. |

Returns — UploadFileResult

| Field | Type | Description | |---|---|---| | objectId | string | Unique ID of the newly created object. | | key | string | Storage key for the file. | | uploadId | string | Multipart upload session ID. | | bucketId | string | The bucket the object belongs to. | | parts | UploadFilePart[] | Array of parts needed to confirm the upload. |


confirmUpload

Finalises the multipart upload session. Must be called after initiateUpload to make the file permanently accessible.

const result = await bucket.confirmUpload(
  options: ConfirmFileOptions
): Promise<ConfirmFileResult>

Parameters — ConfirmFileOptions

| Field | Type | Required | Description | |---|---|---|---| | bucketId | string | ✅ | Same bucket ID used in initiateUpload. | | objectId | string | ✅ | Returned by initiateUpload. | | uploadId | string | ✅ | Returned by initiateUpload. | | key | string | ✅ | Returned by initiateUpload. | | parts | UploadFilePart[] | ✅ | Array of { PartNumber, ETag } returned by initiateUpload. |

Returns — ConfirmFileResult

| Field | Type | Description | |---|---|---| | key | string | The final storage key of the confirmed file. |


getMeta

Fetches the stored metadata for an existing object by its key.

const meta = await bucket.getMeta(key: string): Promise<FileMeta>

Parameters

| Parameter | Type | Required | Description | |---|---|---|---| | key | string | ✅ | The file's storage key (returned from confirmUpload). |

Returns — FileMeta

| Field | Type | Description | |---|---|---| | key | string | Storage key. | | filename | string | Original filename. | | contentType | string | MIME type (e.g. video/mp4). | | size | number | File size in bytes. | | duration | number? | Media duration in seconds (if applicable). | | createdAt | string | ISO 8601 creation timestamp. | | updatedAt | string | ISO 8601 last-updated timestamp. |


TypeScript Types

All types are exported from the package root:

import type {
  StorageBucketOptions,
  UploadFileOptions,
  UploadFileResult,
  UploadFilePart,
  ConfirmFileOptions,
  ConfirmFileResult,
  FileMeta,
} from "@oneminutecloud/storage-bucket";

Framework Guides

Express.js

A complete file-upload endpoint using multer for multipart/form-data parsing:

npm install express multer
npm install --save-dev @types/express @types/multer
// src/routes/upload.ts
import express from "express";
import multer from "multer";
import { createStorageBucket } from "@oneminutecloud/storage-bucket";

const router = express.Router();
const upload = multer({ storage: multer.memoryStorage() });

const bucket = createStorageBucket({
  apiKey: process.env.OMC_API_KEY!, // store in .env, never hard-code
});

router.post("/upload", upload.single("file"), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: "No file provided" });
    }

    // Step 1 — initiate
    const initiated = await bucket.initiateUpload(req.file.buffer, {
      bucketId: process.env.OMC_BUCKET_ID!,
      duration: Number(req.body.duration) || 0,
    });

    // Step 2 — confirm
    const confirmed = await bucket.confirmUpload({
      bucketId: initiated.bucketId,
      objectId: initiated.objectId,
      uploadId: initiated.uploadId,
      key:      initiated.key,
      parts:    initiated.parts,
    });

    return res.status(201).json({ key: confirmed.key });
  } catch (err: any) {
    return res.status(500).json({ error: err.message });
  }
});

export default router;
// src/app.ts
import express from "express";
import uploadRouter from "./routes/upload";

const app = express();
app.use(express.json());
app.use("/api", uploadRouter);

app.listen(3000, () => console.log("Server running on http://localhost:3000"));

.env

OMC_API_KEY=OMC_your_api_key_here
OMC_BUCKET_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

NestJS

1. Create a reusable StorageBucketModule

npm install @oneminutecloud/storage-bucket
// src/storage-bucket/storage-bucket.service.ts
import { Injectable, OnModuleInit } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import {
  createStorageBucket,
  UploadFileOptions,
  ConfirmFileOptions,
  FileMeta,
} from "@oneminutecloud/storage-bucket";

@Injectable()
export class StorageBucketService implements OnModuleInit {
  private bucket: ReturnType<typeof createStorageBucket>;

  constructor(private readonly config: ConfigService) {}

  onModuleInit() {
    this.bucket = createStorageBucket({
      apiKey: this.config.getOrThrow<string>("OMC_API_KEY"),
    });
  }

  async upload(file: Buffer, options: UploadFileOptions) {
    const initiated = await this.bucket.initiateUpload(file, options);
    return this.bucket.confirmUpload({
      bucketId: initiated.bucketId,
      objectId: initiated.objectId,
      uploadId: initiated.uploadId,
      key:      initiated.key,
      parts:    initiated.parts,
    });
  }

  async getMeta(key: string): Promise<FileMeta> {
    return this.bucket.getMeta(key);
  }
}
// src/storage-bucket/storage-bucket.module.ts
import { Module } from "@nestjs/common";
import { StorageBucketService } from "./storage-bucket.service";

@Module({
  providers: [StorageBucketService],
  exports:   [StorageBucketService],
})
export class StorageBucketModule {}

2. Use it in a feature module

// src/media/media.controller.ts
import {
  Controller, Post, UploadedFile,
  UseInterceptors, Body, Get, Param,
} from "@nestjs/common";
import { FileInterceptor } from "@nestjs/platform-express";
import { StorageBucketService } from "../storage-bucket/storage-bucket.service";

@Controller("media")
export class MediaController {
  constructor(private readonly storageBucket: StorageBucketService) {}

  @Post("upload")
  @UseInterceptors(FileInterceptor("file"))
  async upload(
    @UploadedFile() file: Express.Multer.File,
    @Body("bucketId") bucketId: string,
    @Body("duration") duration?: string,
  ) {
    const result = await this.storageBucket.upload(file.buffer, {
      bucketId,
      duration: duration ? Number(duration) : 0,
    });
    return { key: result.key };
  }

  @Get("meta/:key")
  async getMeta(@Param("key") key: string) {
    return this.storageBucket.getMeta(key);
  }
}
// src/media/media.module.ts
import { Module } from "@nestjs/common";
import { MediaController } from "./media.controller";
import { StorageBucketModule } from "../storage-bucket/storage-bucket.module";

@Module({
  imports:     [StorageBucketModule],
  controllers: [MediaController],
})
export class MediaModule {}

.env

OMC_API_KEY=OMC_your_api_key_here
OMC_BUCKET_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Tip: Register ConfigModule.forRoot() in your AppModule and @nestjs/config to handle environment variables cleanly.


Next.js (App Router)

Create a server-side Route Handler to keep your API key off the client:

// app/api/upload/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createStorageBucket } from "@oneminutecloud/storage-bucket";

const bucket = createStorageBucket({
  apiKey: process.env.OMC_API_KEY!,
});

export async function POST(req: NextRequest) {
  try {
    const formData = await req.formData();
    const file = formData.get("file") as File | null;
    const bucketId = formData.get("bucketId") as string;

    if (!file) {
      return NextResponse.json({ error: "No file provided" }, { status: 400 });
    }

    const arrayBuffer = await file.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);

    // Step 1 — initiate
    const initiated = await bucket.initiateUpload(buffer, {
      bucketId,
      duration: Number(formData.get("duration")) || 0,
    });

    // Step 2 — confirm
    const confirmed = await bucket.confirmUpload({
      bucketId: initiated.bucketId,
      objectId: initiated.objectId,
      uploadId: initiated.uploadId,
      key:      initiated.key,
      parts:    initiated.parts,
    });

    return NextResponse.json({ key: confirmed.key }, { status: 201 });
  } catch (err: any) {
    return NextResponse.json({ error: err.message }, { status: 500 });
  }
}
// app/api/meta/[key]/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createStorageBucket } from "@oneminutecloud/storage-bucket";

const bucket = createStorageBucket({ apiKey: process.env.OMC_API_KEY! });

export async function GET(
  _req: NextRequest,
  { params }: { params: { key: string } },
) {
  try {
    const meta = await bucket.getMeta(params.key);
    return NextResponse.json(meta);
  } catch (err: any) {
    return NextResponse.json({ error: err.message }, { status: 500 });
  }
}

.env.local

OMC_API_KEY=OMC_your_api_key_here

Important: Never use this SDK inside a "use client" component or any browser-side code. Use it only in Route Handlers (route.ts), Server Actions, or getServerSideProps.


Fastify

npm install fastify @fastify/multipart
// src/server.ts
import Fastify from "fastify";
import multipart from "@fastify/multipart";
import { createStorageBucket } from "@oneminutecloud/storage-bucket";

const app = Fastify({ logger: true });
app.register(multipart);

const bucket = createStorageBucket({
  apiKey: process.env.OMC_API_KEY!,
});

app.post("/upload", async (request, reply) => {
  const data = await request.file();
  if (!data) {
    return reply.status(400).send({ error: "No file provided" });
  }

  const chunks: Buffer[] = [];
  for await (const chunk of data.file) {
    chunks.push(chunk);
  }
  const fileBuffer = Buffer.concat(chunks);

  // Initiate
  const initiated = await bucket.initiateUpload(fileBuffer, {
    bucketId: process.env.OMC_BUCKET_ID!,
    duration: 0,
  });

  // Confirm
  const confirmed = await bucket.confirmUpload({
    bucketId: initiated.bucketId,
    objectId: initiated.objectId,
    uploadId: initiated.uploadId,
    key:      initiated.key,
    parts:    initiated.parts,
  });

  return reply.status(201).send({ key: confirmed.key });
});

app.get<{ Params: { key: string } }>("/meta/:key", async (request, reply) => {
  const meta = await bucket.getMeta(request.params.key);
  return reply.send(meta);
});

app.listen({ port: 3000 }, () => {
  console.log("Server running on http://localhost:3000");
});

Error Handling

All SDK methods throw a plain Error with a descriptive message prefixed with [OneMinute Cloud].

try {
  const initiated = await bucket.initiateUpload(fileBuffer, { bucketId });
  const confirmed = await bucket.confirmUpload({ ...initiated, parts: initiated.parts });
  console.log("Uploaded:", confirmed.key);
} catch (err) {
  if (err instanceof Error) {
    // e.g. "[OneMinute Cloud] Invalid bucket ID"
    // e.g. "[OneMinute Cloud] Upload initiation failed"
    console.error(err.message);
  }
}

Common Error Messages

| Error | Cause | |---|---| | apiKey is required | No API key was passed to createStorageBucket. | | Invalid API key format | API key does not start with OMC_. | | bucketId is required | bucketId is missing from the options. | | Invalid bucket ID | bucketId is not a valid UUID. | | File data is required | An empty Buffer was passed to initiateUpload. | | Upload initiation failed | The API returned a non-2xx response during initiation. | | Upload confirmation failed | The API returned a non-2xx response during confirmation. | | Failed to get file metadata | The API returned a non-2xx response for getMeta. |


FAQ

Q: Do I need to split the file into parts manually?
A: No. initiateUpload handles this automatically. Just pass the raw Buffer and call confirmUpload with the result.

Q: Can I use this in the browser or in a React component?
A: No. This is a server-side-only SDK. Your API key must never be exposed to the client. Use a backend route (Express, NestJS, Next.js Route Handler, etc.) to proxy uploads.

Q: What file types are supported?
A: Any file type. The SDK sends application/octet-stream as the content type for raw Buffers. If you pass a browser File object (e.g. in a Bun/Deno environment), the file's native MIME type is used automatically.

Q: Where do I find my Bucket ID and API Key?
A: Log in to your OneMinute Cloud Dashboard, navigate to Storage Buckets, and copy the bucket UUID. Your API key is available in Settings → Developer Access.

Q: Is there a file size limit?
A: Limits depend on your OneMinute Cloud plan. The SDK itself imposes no limit — it streams multipart metadata to the API. Check your plan's quota in the dashboard.


Contributing & Support


License

ISC © OneMinute Stack