BREAKING CHANGE(core): rebrand from smarts3 to smartstorage
Some checks failed
Default (tags) / security (push) Successful in 43s
Default (tags) / test (push) Failing after 26s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped

- Package renamed from @push.rocks/smarts3 to @push.rocks/smartstorage
- Class: Smarts3 → SmartStorage, Interface: ISmarts3Config → ISmartStorageConfig
- Method: getS3Descriptor → getStorageDescriptor
- Rust binary: rusts3 → ruststorage
- Rust types: S3Error→StorageError, S3Action→StorageAction, S3Config→SmartStorageConfig, S3Server→StorageServer
- On-disk file extension: ._S3_object → ._storage_object
- Default credentials: S3RVER → STORAGE
- All internal S3 branding removed; AWS S3 protocol compatibility fully maintained
This commit is contained in:
2026-03-14 15:20:30 +00:00
parent d437ffc226
commit bba0855218
26 changed files with 347 additions and 332 deletions

146
readme.md
View File

@@ -1,76 +1,76 @@
# @push.rocks/smarts3 🚀
# @push.rocks/smartstorage
A high-performance, S3-compatible local server powered by a **Rust core** with a clean TypeScript API. Drop-in replacement for AWS S3 during development and testing — no cloud, no Docker, no MinIO. Just `npm install` and go.
A high-performance, S3-compatible local storage server powered by a **Rust core** with a clean TypeScript API. Drop-in replacement for AWS S3 during development and testing — no cloud, no Docker, no MinIO. Just `npm install` and go.
## Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
## 🌟 Why smarts3?
## Why smartstorage?
| Feature | smarts3 | MinIO | s3rver |
|---------|---------|-------|--------|
| Feature | smartstorage | MinIO | s3rver |
|---------|-------------|-------|--------|
| Install | `pnpm add` | Docker / binary | `npm install` |
| Startup time | ~20ms | seconds | ~200ms |
| Large file uploads | Streaming, zero-copy | ✅ | ❌ OOM risk |
| Range requests | Seek-based | ✅ | ❌ Full read |
| Large file uploads | Streaming, zero-copy | Yes | OOM risk |
| Range requests | Seek-based | Yes | Full read |
| Language | Rust + TypeScript | Go | JavaScript |
| Multipart uploads | Full support | | |
| Auth | AWS SigV4 (full verification) | Full IAM | Basic |
| Bucket policies | IAM-style evaluation | | |
| Multipart uploads | Full support | Yes | No |
| Auth | AWS SigV4 (full verification) | Full IAM | Basic |
| Bucket policies | IAM-style evaluation | Yes | No |
### Core Features
- **Rust-powered HTTP server** — hyper 1.x with streaming I/O, zero-copy, backpressure
- 🔄 **Full S3 API compatibility** — works with AWS SDK v3, SmartBucket, any S3 client
- 📂 **Filesystem-backed storage** — buckets map to directories, objects to files
- 📤 **Streaming multipart uploads** — large files without memory pressure
- 🎯 **Byte-range requests**`seek()` directly to the requested byte offset
- 🔐 **AWS SigV4 authentication** — full signature verification with constant-time comparison and 15-min clock skew enforcement
- 📜 **Bucket policies** — IAM-style JSON policies with Allow/Deny evaluation, wildcard matching, and anonymous access support
- 🌐 **CORS middleware** — configurable cross-origin support
- 📊 **Structured logging** — tracing-based, error through debug levels
- 🧹 **Clean slate mode** — wipe storage on startup for test isolation
- 🧪 **Test-first design** — start/stop in milliseconds, no port conflicts
- **Rust-powered HTTP server** — hyper 1.x with streaming I/O, zero-copy, backpressure
- **Full S3-compatible API** — works with AWS SDK v3, SmartBucket, any S3 client
- **Filesystem-backed storage** — buckets map to directories, objects to files
- **Streaming multipart uploads** — large files without memory pressure
- **Byte-range requests** — `seek()` directly to the requested byte offset
- **AWS SigV4 authentication** — full signature verification with constant-time comparison and 15-min clock skew enforcement
- **Bucket policies** — IAM-style JSON policies with Allow/Deny evaluation, wildcard matching, and anonymous access support
- **CORS middleware** — configurable cross-origin support
- **Structured logging** — tracing-based, error through debug levels
- **Clean slate mode** — wipe storage on startup for test isolation
- **Test-first design** — start/stop in milliseconds, no port conflicts
## 📦 Installation
## Installation
```bash
pnpm add @push.rocks/smarts3 -D
pnpm add @push.rocks/smartstorage -D
```
> **Note:** The package ships with precompiled Rust binaries for `linux_amd64` and `linux_arm64`. No Rust toolchain needed on your machine.
## 🚀 Quick Start
## Quick Start
```typescript
import { Smarts3 } from '@push.rocks/smarts3';
import { SmartStorage } from '@push.rocks/smartstorage';
// Start a local S3 server
const s3 = await Smarts3.createAndStart({
// Start a local S3-compatible storage server
const storage = await SmartStorage.createAndStart({
server: { port: 3000 },
storage: { cleanSlate: true },
});
// Create a bucket
await s3.createBucket('my-bucket');
await storage.createBucket('my-bucket');
// Get connection details for any S3 client
const descriptor = await s3.getS3Descriptor();
// → { endpoint: 'localhost', port: 3000, accessKey: 'S3RVER', accessSecret: 'S3RVER', useSsl: false }
const descriptor = await storage.getStorageDescriptor();
// → { endpoint: 'localhost', port: 3000, accessKey: 'STORAGE', accessSecret: 'STORAGE', useSsl: false }
// When done
await s3.stop();
await storage.stop();
```
## 📖 Configuration
## Configuration
All config fields are optional — sensible defaults are applied automatically.
```typescript
import { Smarts3, ISmarts3Config } from '@push.rocks/smarts3';
import { SmartStorage, ISmartStorageConfig } from '@push.rocks/smartstorage';
const config: ISmarts3Config = {
const config: ISmartStorageConfig = {
server: {
port: 3000, // Default: 3000
address: '0.0.0.0', // Default: '0.0.0.0'
@@ -113,14 +113,14 @@ const config: ISmarts3Config = {
},
};
const s3 = await Smarts3.createAndStart(config);
const storage = await SmartStorage.createAndStart(config);
```
### Common Configurations
**CI/CD testing** — silent, clean, fast:
```typescript
const s3 = await Smarts3.createAndStart({
const storage = await SmartStorage.createAndStart({
server: { port: 9999, silent: true },
storage: { cleanSlate: true },
});
@@ -128,7 +128,7 @@ const s3 = await Smarts3.createAndStart({
**Auth enabled:**
```typescript
const s3 = await Smarts3.createAndStart({
const storage = await SmartStorage.createAndStart({
auth: {
enabled: true,
credentials: [{ accessKeyId: 'test', secretAccessKey: 'test123' }],
@@ -138,7 +138,7 @@ const s3 = await Smarts3.createAndStart({
**CORS for local web dev:**
```typescript
const s3 = await Smarts3.createAndStart({
const storage = await SmartStorage.createAndStart({
cors: {
enabled: true,
allowedOrigins: ['http://localhost:5173'],
@@ -147,12 +147,12 @@ const s3 = await Smarts3.createAndStart({
});
```
## 📤 Usage with AWS SDK v3
## Usage with AWS SDK v3
```typescript
import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
const descriptor = await s3.getS3Descriptor();
const descriptor = await storage.getStorageDescriptor();
const client = new S3Client({
endpoint: `http://${descriptor.endpoint}:${descriptor.port}`,
@@ -161,14 +161,14 @@ const client = new S3Client({
accessKeyId: descriptor.accessKey,
secretAccessKey: descriptor.accessSecret,
},
forcePathStyle: true, // Required for path-style S3
forcePathStyle: true, // Required for path-style access
});
// Upload
await client.send(new PutObjectCommand({
Bucket: 'my-bucket',
Key: 'hello.txt',
Body: 'Hello, S3!',
Body: 'Hello, Storage!',
ContentType: 'text/plain',
}));
@@ -177,7 +177,7 @@ const { Body } = await client.send(new GetObjectCommand({
Bucket: 'my-bucket',
Key: 'hello.txt',
}));
const content = await Body.transformToString(); // "Hello, S3!"
const content = await Body.transformToString(); // "Hello, Storage!"
// Delete
await client.send(new DeleteObjectCommand({
@@ -186,12 +186,12 @@ await client.send(new DeleteObjectCommand({
}));
```
## 🪣 Usage with SmartBucket
## Usage with SmartBucket
```typescript
import { SmartBucket } from '@push.rocks/smartbucket';
const smartbucket = new SmartBucket(await s3.getS3Descriptor());
const smartbucket = new SmartBucket(await storage.getStorageDescriptor());
const bucket = await smartbucket.createBucket('my-bucket');
const dir = await bucket.getBaseDirectory();
@@ -205,9 +205,9 @@ const content = await dir.fastGet('docs/readme.txt');
const files = await dir.listFiles();
```
## 📤 Multipart Uploads
## Multipart Uploads
For files larger than 5 MB, use multipart uploads. smarts3 handles them with **streaming I/O** — parts are written directly to disk, never buffered in memory.
For files larger than 5 MB, use multipart uploads. smartstorage handles them with **streaming I/O** — parts are written directly to disk, never buffered in memory.
```typescript
import {
@@ -244,9 +244,9 @@ await client.send(new CompleteMultipartUploadCommand({
}));
```
## 📜 Bucket Policies
## Bucket Policies
smarts3 supports AWS-style bucket policies for fine-grained access control. Policies use the same IAM JSON format as real S3 — so you can develop and test your policy logic locally before deploying.
smartstorage supports AWS-style bucket policies for fine-grained access control. Policies use the same IAM JSON format as real S3 — so you can develop and test your policy logic locally before deploying.
When `auth.enabled` is `true`, the auth pipeline works as follows:
1. **Authenticate** — verify the AWS SigV4 signature (anonymous requests skip this step)
@@ -294,38 +294,38 @@ await client.send(new PutBucketPolicyCommand({
Deleting a bucket automatically removes its associated policy.
## 🧪 Testing Integration
## Testing Integration
```typescript
import { Smarts3 } from '@push.rocks/smarts3';
import { SmartStorage } from '@push.rocks/smartstorage';
import { tap, expect } from '@git.zone/tstest/tapbundle';
let s3: Smarts3;
let storage: SmartStorage;
tap.test('setup', async () => {
s3 = await Smarts3.createAndStart({
storage = await SmartStorage.createAndStart({
server: { port: 4567, silent: true },
storage: { cleanSlate: true },
});
});
tap.test('should store and retrieve objects', async () => {
await s3.createBucket('test');
await storage.createBucket('test');
// ... your test logic using AWS SDK or SmartBucket
});
tap.test('teardown', async () => {
await s3.stop();
await storage.stop();
});
export default tap.start();
```
## 🔧 API Reference
## API Reference
### `Smarts3` Class
### `SmartStorage` Class
#### `static createAndStart(config?: ISmarts3Config): Promise<Smarts3>`
#### `static createAndStart(config?: ISmartStorageConfig): Promise<SmartStorage>`
Create and start a server in one call.
@@ -339,11 +339,11 @@ Gracefully stop the server and kill the Rust process.
#### `createBucket(name: string): Promise<{ name: string }>`
Create an S3 bucket.
Create a storage bucket.
#### `getS3Descriptor(options?): Promise<IS3Descriptor>`
#### `getStorageDescriptor(options?): Promise<IS3Descriptor>`
Get connection details for S3 clients. Returns:
Get connection details for S3-compatible clients. Returns:
| Field | Type | Description |
|-------|------|-------------|
@@ -353,16 +353,16 @@ Get connection details for S3 clients. Returns:
| `accessSecret` | `string` | Secret key from first configured credential |
| `useSsl` | `boolean` | Always `false` (plain HTTP) |
## 🏗️ Architecture
## Architecture
smarts3 uses a **hybrid Rust + TypeScript** architecture:
smartstorage uses a **hybrid Rust + TypeScript** architecture:
```
┌─────────────────────────────────┐
│ Your Code (AWS SDK, etc.) │
│ ↕ HTTP (localhost:3000) │
├─────────────────────────────────┤
│ rusts3 binary (Rust)
│ ruststorage binary (Rust) │
│ ├─ hyper 1.x HTTP server │
│ ├─ S3 path-style routing │
│ ├─ Streaming storage layer │
@@ -372,7 +372,7 @@ smarts3 uses a **hybrid Rust + TypeScript** architecture:
│ └─ S3 XML response builder │
├─────────────────────────────────┤
│ TypeScript (thin IPC wrapper) │
│ ├─ Smarts3 class
│ ├─ SmartStorage class │
│ ├─ RustBridge (stdin/stdout) │
│ └─ Config & S3 descriptor │
└─────────────────────────────────┘
@@ -380,9 +380,9 @@ smarts3 uses a **hybrid Rust + TypeScript** architecture:
**Why Rust?** The TypeScript implementation had critical perf issues: OOM on multipart uploads (parts buffered in memory), double stream copying, file descriptor leaks on HEAD requests, full-file reads for range requests, and no backpressure. The Rust binary solves all of these with streaming I/O, zero-copy, and direct `seek()` for range requests.
**IPC Protocol:** TypeScript spawns the `rusts3` binary with `--management` and communicates via newline-delimited JSON over stdin/stdout. Commands: `start`, `stop`, `createBucket`.
**IPC Protocol:** TypeScript spawns the `ruststorage` binary with `--management` and communicates via newline-delimited JSON over stdin/stdout. Commands: `start`, `stop`, `createBucket`.
### S3 Operations Supported
### S3-Compatible Operations Supported
| Operation | Method | Path |
|-----------|--------|------|
@@ -410,9 +410,9 @@ smarts3 uses a **hybrid Rust + TypeScript** architecture:
```
{storage.directory}/
{bucket}/
{key}._S3_object # Object data
{key}._S3_object.metadata.json # Metadata (content-type, x-amz-meta-*, etc.)
{key}._S3_object.md5 # Cached MD5 hash
{key}._storage_object # Object data
{key}._storage_object.metadata.json # Metadata (content-type, x-amz-meta-*, etc.)
{key}._storage_object.md5 # Cached MD5 hash
.multipart/
{upload-id}/
metadata.json # Upload metadata (bucket, key, parts)
@@ -423,10 +423,10 @@ smarts3 uses a **hybrid Rust + TypeScript** architecture:
{bucket}.policy.json # Bucket policy (IAM JSON format)
```
## 🔗 Related Packages
## Related Packages
- [`@push.rocks/smartbucket`](https://code.foss.global/push.rocks/smartbucket) — High-level S3 abstraction layer
- [`@push.rocks/smartrust`](https://code.foss.global/push.rocks/smartrust) — TypeScript Rust IPC bridge
- [`@push.rocks/smartbucket`](https://code.foss.global/push.rocks/smartbucket) — High-level S3-compatible abstraction layer
- [`@push.rocks/smartrust`](https://code.foss.global/push.rocks/smartrust) — TypeScript <-> Rust IPC bridge
- [`@git.zone/tsrust`](https://code.foss.global/git.zone/tsrust) — Rust cross-compilation for npm packages
## License and Legal Information