# RomM Uploader CLI

A Linux-first TypeScript CLI for uploading ROMs to your [RomM](https://romm.app/) instance.

## Features

- 🔐 OAuth2 authentication with token caching
- 🔍 Checksum-based duplicate detection (CRC32, MD5, SHA1)
- 💾 Local checksum cache for faster re-runs
- 📁 Support for files, directories, and glob patterns
- 🎮 Platform discovery and resolution
- 🧪 Dry-run mode for testing
- 📊 JSON output for scripting

## Prerequisites

- Node.js 18+ 
- RomM instance (v4.5.0+)

## Installation

```bash
# Run without installing
npx romm-uploader --help

# Or install globally
npm install -g romm-uploader
```

## Usage

### Basic Upload

```bash
# Using environment variables
export ROMM_BASE_URL=https://romm.example.com
export ROMM_USERNAME=admin
export ROMM_PASSWORD=secret

romm-uploader --platform snes "Super Mario World.smc"
```

### With CLI Options

```bash
romm-uploader \
  --base-url https://romm.example.com \
  --username admin \
  --password secret \
  --platform gba \
  ~/roms/gameboy/*.gba
```

### List Platforms

```bash
romm-uploader --list-platforms
```

### Dry Run

```bash
romm-uploader --dry-run --platform psx ~/roms/playstation/
```

### Multiple Input Methods

```bash
romm-uploader \
  --platform snes \
  --upload-file "game1.smc" \
  --upload-file "game2.smc" \
  --upload-dir ~/roms/more/ \
  --glob "*.sfc"
```

## Configuration

Configuration precedence (highest to lowest):
1. CLI options
2. Environment variables
3. Defaults

### Environment Variables

| Variable | Description |
|----------|-------------|
| `ROMM_BASE_URL` | RomM instance URL |
| `ROMM_USERNAME` | Username for authentication |
| `ROMM_PASSWORD` | Password for authentication |

Copy `.env.example` to `.env` and fill in your values.

## CLI Options

### Connection Options

| Option | Description | Default |
|--------|-------------|---------|
| `--base-url <url>` | RomM base URL | `ROMM_BASE_URL` env |
| `--username <user>` | Username | `ROMM_USERNAME` env |
| `--password <pass>` | Password | `ROMM_PASSWORD` env |

### Platform Options

| Option | Description |
|--------|-------------|
| `--platform <value>` | Target platform (slug, name, or ID) |
| `--list-platforms` | List available platforms and exit |

### Input Options

| Option | Description |
|--------|-------------|
| `[paths...]` | Positional file/directory paths |
| `--upload-file <path>` | Specific file to upload (repeatable) |
| `--upload-dir <path>` | Directory to upload from (repeatable) |
| `--glob <pattern>` | Glob pattern for files (repeatable) |
| `--recursive` | Include nested directories |

### Checksum Options

| Option | Description | Default |
|--------|-------------|---------|
| `--checksum <algo>` | Additional hash algorithm | - |
| `--cache-enabled <bool>` | Enable checksum cache | `true` |
| `--cache-max-mb <n>` | Cache size limit | `4` |
| `--cache-path <path>` | Custom cache location | XDG default |

### Auth Options

| Option | Description | Default |
|--------|-------------|---------|
| `--auth-cache-enabled <bool>` | Enable token cache | `true` |
| `--auth-cache-path <path>` | Custom auth cache location | XDG default |
| `--auth-reauth-skew-seconds <n>` | Early refresh window | `60` |

### Request Options

| Option | Description | Default |
|--------|-------------|---------|
| `--request-timeout-seconds <n>` | HTTP timeout | `60` |
| `--retry-count <n>` | Retry attempts | `0` |

### Behavior Options

| Option | Description | Default |
|--------|-------------|---------|
| `--dry-run` | Check only, no upload | `false` |
| `--concurrency <n>` | Parallel processing | `3` |

### Output Options

| Option | Description | Default |
|--------|-------------|---------|
| `--json` | JSON output | `false` |
| `--verbose` | Debug logging | `false` |

## Exit Codes

| Code | Meaning |
|------|---------|
| `0` | Success (all files processed) |
| `1` | Partial/complete failure |
| `2` | Invalid usage/configuration |

## Development

```bash
# Install dependencies
npm install

# Run in development mode
npm run dev -- --help

# Build
npm run build

# Release gate (must pass before publish)
npm run release:check

# Run tests
npm test

# Lint
npm run lint

# Format
npm run format
```

## Project Structure

```
.
├── src/
│   ├── cli.ts                 # Entry point
│   ├── config.ts              # Configuration management
│   ├── types.ts               # Type definitions
│   ├── files/
│   │   └── discover-files.ts  # File discovery
│   ├── checksum/
│   │   └── compute-checksum.ts # Hash computation
│   ├── cache/
│   │   └── checksum-cache.ts  # Checksum caching
│   ├── romm/
│   │   └── client.ts          # RomM API client
│   ├── output/
│   │   └── reporter.ts        # Output formatting
│   └── workflow/
│       └── process-roms.ts    # Main workflow
├── test/
│   ├── unit/                  # Unit tests
│   └── integration/           # Integration tests
├── docs/
│   └── api-notes.md           # RomM API documentation
└── package.json
```

## Release Notes

- `npm publish` is guarded by `prepublishOnly`, which runs `npm run release:check`.
- `npm run release:check` runs typecheck, lint, tests, and package dry-run.
- Build output is cleaned before compile to prevent stale artifacts.

## License

MIT
