Universal Storage
@alneas/universal-storage
Section titled “@alneas/universal-storage”Universal Web-standard zero-dependency storage layer for Browser, Edge, Cloudflare Workers, Deno, Bun, and Node.js
@alneas/universal-storage provides a unified, cross-platform abstraction for cloud object storage (Amazon S3, Cloudflare R2, Oracle Cloud Infrastructure Object Storage, and local storage).
It contains ZERO native bindings, ZERO node:crypto dependencies, and does NOT require @aws-sdk/client-s3 to function. It executes natively in browsers, service workers, and edge computing environments using standard fetch, ReadableStream, Uint8Array, and Web-standard crypto algorithms.
Features
Section titled “Features”- Zero Runtime Dependencies: No
@aws-sdkbloat, no Node-specific C++ addons. Pure TypeScript. - Universal Runtime: Runs seamlessly on Cloudflare Workers, Vercel Edge, Deno, Bun, Node.js (>=24), and modern Browsers.
- Amazon S3 & Cloudflare R2: First-class support with automatic SigV4 signing and presigned URL generation.
- Oracle Cloud (OCI): Full support for OCI Object Storage with namespace and compartment resolution.
- Data Integrity: SHA-256 checksums and S3 Object Lock transport support.
- Path Traversal Protection: Secure local storage adapter with strictly sandboxed directory containment.
- Symmetric Non-ASCII Metadata: UTF-8 and Japanese metadata preservation without header corruption or percent-encoding ambiguities.
Installation
Section titled “Installation”# npmnpm install @alneas/universal-storage
# bunbun add @alneas/universal-storage
# pnpmpnpm add @alneas/universal-storageQuick Start
Section titled “Quick Start”1. Amazon S3 / Cloudflare R2 in Browser or Edge
Section titled “1. Amazon S3 / Cloudflare R2 in Browser or Edge”import { S3StorageAdapter, R2StorageAdapter } from '@alneas/universal-storage';
// Amazon S3const s3 = new S3StorageAdapter({ region: 'ap-northeast-1', bucket: 'my-app-storage', accessKeyId: process.env.AWS_ACCESS_KEY_ID!, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,});
// Cloudflare R2const r2 = new R2StorageAdapter({ accountId: process.env.R2_ACCOUNT_ID!, bucket: 'my-r2-bucket', accessKeyId: process.env.R2_ACCESS_KEY_ID!, secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,});
// Upload string, Uint8Array, Blob, or ReadableStreamawait s3.upload('documents/hello.txt', 'こんにちは世界!', { contentType: 'text/plain; charset=utf-8', metadata: { author: '山田' },});
// Download as Uint8Arrayconst bytes = await s3.download('documents/hello.txt');console.log(new TextDecoder().decode(bytes!));
// Generate Presigned Download URL synchronously in Edge/Browserconst downloadUrl = await s3.getUrl('documents/hello.txt', { expiresIn: 3600, downloadFilename: 'exported-hello.txt',});License
Section titled “License”MIT © ALNEAS / DataArtHub
Repository and releases
Section titled “Repository and releases”This package in the ALNEAS public monorepo is the canonical source. See CONTRIBUTING.md for verification and RELEASING.md for npm release setup and initial dependency bootstrap. There is no source sync from the private application repository.
Runtime entry points and storage semantics
Section titled “Runtime entry points and storage semantics”Use @alneas/universal-storage/portable for browsers, Workers and service workers. It has no Node builtin imports or polyfills. The browser/default root resolves to the same portable module. Use /server for LocalStorageAdapter; Node’s conditional root keeps that historical export. The Node root is not a browser script URL. SHA-256/HMAC and ZIP helpers are portable.
S3/R2/OCI always use the explicit fetch/SigV4 implementation. Installing an AWS SDK does not change behavior. Unicode, control characters and literal b64: metadata values are encoded on write and decoded once on read. Previously stored unescaped b64: literals are inherently ambiguous; migrate them from a known original value. Copy preserves stored metadata. CopyObject reads its full XML response, rejects embedded errors/invalid success and confirms destination HEAD before move deletes the source. A failed source delete rejects move; a confirmed destination can remain for recovery. Same-key move is a no-op on an existing object.
Object Lock PUT adds and signs x-amz-sdk-checksum-algorithm: SHA256 and x-amz-checksum-sha256. The bucket must have versioning/Object Lock configured and the caller must have the applicable permissions. Deleting a versioned key can create a delete marker while locked versions remain; this API does not purge retained versions. Do not infer successful deletion of a retained version from key deletion.
Package tests cover failure responses, checksum known values, metadata round trips and ZIP records. Packed consumers execute the portable module in native Chromium without Buffer or Node polyfills. Real cloud credentials, bucket retention and IAM remain deployment-specific checks.
Direct transfer and package boundary
Section titled “Direct transfer and package boundary”Remote adapters provide getUploadUrl(key, { expiresIn }) for HTTP PUT and
getDownloadUrl(key) for HTTP GET. Signed URL expiry must be 1–604800 seconds.
For S3-compatible R2 test endpoints, set endpoint and an explicit region;
real Cloudflare R2 defaults to auto. copy and move preserve metadata.
Use /crypto and /zip for narrow helpers. ComplianceStorageManager, its document/
audit types and RFC 3161 TSA live in the private premium suite.
Run bun run test:containers for real MinIO requests; daily tests do not start Docker.
Consumer AI guidance ships in dist/ai/SKILL.md and package-context.json. Preview the package-scoped additions to your project instructions with the following command. Add --write after reviewing the preview; existing instructions are preserved.
node node_modules/@alneas/universal-storage/dist/ai/setup.mjs --project .