npm package: @howells/stow-server
Description: Server-side SDK for Stow file storage
Latest version: 2.5.0

# @howells/stow-server

Server-side SDK for [Stow](https://stow.sh) file storage. Use this to upload files, generate presigned URLs, and manage files from your Node.js server.

## Installation

```bash
npm install @howells/stow-server
# or
pnpm add @howells/stow-server
# or
yarn add @howells/stow-server
```

## Quick Start

```typescript
import { StowServer } from "@howells/stow-server";

const stow = new StowServer(process.env.STOW_API_KEY!);

// Upload a file
const buffer = await fs.readFile("./photo.jpg");
const result = await stow.uploadFile(buffer, { filename: "photo.jpg" });
console.log(result.url);
```

## API Reference

### `new StowServer(config)`

Create a new Stow server instance.

```typescript
// Simple: just pass the API key
const stow = new StowServer(process.env.STOW_API_KEY!);

// Advanced: pass a config object
const stow = new StowServer({
  apiKey: process.env.STOW_API_KEY!,
  baseUrl: "https://stow.sh", // optional, defaults to https://stow.sh
});
```

### `uploadFile(file, options?)`

Upload a file directly from your server.

```typescript
const result = await stow.uploadFile(buffer, {
  filename: "photo.jpg",
  contentType: "image/jpeg",
  route: "avatars", // optional folder/route
});

// Result:
// {
//   key: "bucket-id/avatars/abc123.jpg",
//   url: "https://stow.sh/files/bucket-id/avatars/abc123.jpg",
//   size: 12345,
//   contentType: "image/jpeg"
// }
```

### `uploadFromUrl(url, filename)`

Upload a file from a URL (server-side fetch + upload).

```typescript
const result = await stow.uploadFromUrl("https://example.com/image.jpg", "downloaded-image.jpg");
```

### `getPresignedUrl(filename, contentType, route?)`

Get a presigned URL for client-side upload.

```typescript
const { uploadUrl, fileKey, fileUrl } = await stow.getPresignedUrl(
  "photo.jpg",
  "image/jpeg",
  "avatars",
);

// Client can now PUT directly to uploadUrl
```

### `listFiles(options?)`

List files in your bucket.

```typescript
const { files, nextCursor } = await stow.listFiles({
  prefix: "avatars/",
  limit: 100,
  cursor: previousCursor,
});
```

### `deleteFile(key)`

Delete a file by its key.

```typescript
await stow.deleteFile("bucket-id/avatars/abc123.jpg");
```

### `getTransformUrl(url, options?)`

Get a URL with image transform query params. Transforms are applied at the edge by the Cloudflare Worker — no server round-trip needed.

```typescript
const transformedUrl = stow.getTransformUrl("https://photos.stow.sh/image.jpg", {
  width: 800,
  height: 600,
  quality: 80,
  format: "webp",
});
// → "https://photos.stow.sh/image.jpg?w=800&h=600&q=80&f=webp"
```

Transform options:

- `width` — Max width in pixels (clamped to 4096)
- `height` — Max height in pixels (clamped to 4096)
- `quality` — 1–100, quantized to nearest 5 (default: 80)
- `format` — `"webp"`, `"avif"`, `"jpeg"`, or `"png"` (default: `"webp"`)

## Error Handling

All methods throw `StowError` on failure:

```typescript
import { StowError } from "@howells/stow-server";

try {
  await stow.uploadFile(buffer);
} catch (error) {
  if (error instanceof StowError) {
    console.error(`Upload failed: ${error.message} (status: ${error.status})`);
  }
}
```

## TypeScript

Full TypeScript support with exported types:

```typescript
import type {
  StowServerConfig,
  UploadResult,
  TransformOptions,
  ListFilesResult,
} from "@howells/stow-server";
```

## License

MIT