# spearmint

A CLI tool that syncs Roblox developer products and game passes from a local TOML config to the [Roblox Open Cloud API](https://create.roblox.com/docs/cloud).

Define your products in `spearmint.toml`, run `spearmint sync`, and spearmint handles creating/updating them on Roblox while generating Lua and TypeScript files for your game.

## Install

```bash
cargo install --path .
```

## Setup

1. Create a Roblox Open Cloud API key at [create.roblox.com/dashboard/credentials](https://create.roblox.com/dashboard/credentials) with **Developer Product** and **Game Pass** write permissions for your experience.

2. In your project directory, create a `.env` file:

```
ROBLOX_PRODUCTS_API_KEY=your_api_key_here
```

3. Initialize the config:

```bash
spearmint init
```

4. Edit the generated `spearmint.toml` with your universe ID and products.

## Config

```toml
universe_id = 123456789

[output]
path = "src/shared/modules/Products.luau"
typescript = true

[products.coins_100]
type = "dev_product"
name = "100 Coins"
price = 99
description = "Get 100 coins"
image = "assets/products/coins.png"

[products.vip]
type = "gamepass"
name = "VIP"
price = 499
description = "VIP access"
image = "assets/products/vip.png"
```

Each product entry supports:

| Field | Required | Description |
|---|---|---|
| `type` | Yes | `dev_product` or `gamepass` |
| `name` | Yes | Display name on Roblox |
| `price` | Yes | Price in Robux |
| `description` | No | Product description |
| `image` | No | Path to thumbnail image |
| `product_id` | No | Existing Roblox ID (skips creation, used for updates) |

## Commands

### `spearmint sync`

Syncs all products to Roblox. Creates new products and updates existing ones when the config has changed. Generates Lua/TypeScript output after syncing.

```bash
spearmint sync
spearmint sync --no-generate    # skip code generation
spearmint sync -c custom.toml   # custom config path
```

### `spearmint generate`

Generates Lua and TypeScript output files from the current mapping without making any API calls.

```bash
spearmint generate
```

### `spearmint list`

Lists all products and their sync status.

```bash
spearmint list
```

### `spearmint init`

Creates a default `spearmint.toml` template.

```bash
spearmint init
spearmint init --force   # overwrite existing config
```

## How It Works

spearmint uses a lock file (`spearmint.lock.toml`) to track the mapping between local product keys and Roblox IDs, along with cached metadata. On each sync, it compares the current config against the lock file to determine what's changed:

- **New products** (no lock file entry) are created via the API
- **Changed products** (name, price, description, or image contents differ) are updated
- **Unchanged products** are skipped

Image changes are detected by SHA-256 hashing the file contents, so replacing an image file without renaming it will trigger an update.

## Generated Output

After syncing, spearmint generates a Lua module and optionally a TypeScript declaration file:

**Products.luau**
```lua
-- This file is auto-generated by spearmint. Do not edit manually.

local Products = {
	DevProducts = {
		["coins_100"] = 123456,
	},
	Gamepasses = {
		["vip"] = 789012,
	},
}

return Products
```

**Products.d.ts**
```typescript
// This file is auto-generated by spearmint. Do not edit manually.

interface Products {
	DevProducts: {
		readonly "coins_100": 123456;
	};
	Gamepasses: {
		readonly "vip": 789012;
	};
}

declare const Products: Products;
export = Products;
```

## License

MIT
