Metadata-Version: 2.4
Name: forkbit-sdk
Version: 0.1.2
Summary: Plugin SDK for building ForkBit plugins
Project-URL: Homepage, https://forkbit.de
Project-URL: Documentation, https://docs.forkbit.de
Author-email: ForkBit <hello@forkbit.de>
License-Expression: MIT
License-File: LICENSE
Keywords: app-store,forkbit,plugin,pyside6,qt,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.9
Requires-Dist: pyside6>=6.11
Provides-Extra: docs
Requires-Dist: furo; extra == 'docs'
Requires-Dist: sphinx-autobuild; extra == 'docs'
Requires-Dist: sphinx-copybutton; extra == 'docs'
Requires-Dist: sphinx-multiversion; extra == 'docs'
Requires-Dist: sphinx>=7.0; extra == 'docs'
Description-Content-Type: text/markdown

# ForkBit SDK

Build plugins for [ForkBit](https://forkbit.de) — the desktop app for managing app store workflows.

## Installation

```bash
pip install forkbit-sdk
```

## Quick Start

Create a new plugin:

```bash
forkbit plugin init my_plugin
```

This generates a ready-to-run plugin scaffold:

```
my_plugin/
  plugin.json    — manifest (id, name, version, dependencies)
  main.py        — your plugin code (BasePlugin subclass)
  settings.json  — settings schema
```

## Writing a Plugin

Every plugin is a `BasePlugin` subclass that builds its UI in `on_ready()`:

```python
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QLabel, QVBoxLayout

from forkbit_sdk import BasePlugin


class MyPlugin(BasePlugin):

    def on_ready(self) -> None:
        layout = QVBoxLayout(self.container)
        layout.setAlignment(Qt.AlignmentFlag.AlignTop)

        label = QLabel("Hello from my plugin!")
        layout.addWidget(label)
```

Your plugin inherits the app's theme automatically — standard PySide6 widgets just work.

## Plugin API

| Property / Method | Description |
|---|---|
| `self.container` | QWidget — build your UI inside this |
| `self.settings` | dict — current plugin settings values |
| `self.project_id` | str — current project ID |
| `self.project_path` | str — path to the project directory |
| `self.data_dir` | Path — per-instance storage directory |
| `self.git` | GitClient — git operations (status, tags, push, pull, commit) |
| `self.read_json(filename)` | Read JSON from data_dir |
| `self.write_json(filename, data)` | Atomic-write JSON to data_dir |
| `self.notify(message, level)` | Show a toast notification |
| `self.translate(text, src, tgt, on_done, on_error)` | Async translation |
| `self.set_subtitle(text)` | Update the plugin header subtitle |
| `self.secret_file(field_id)` | Get raw bytes of a secret file setting |
| `self.set_busy(busy)` | Mark plugin as busy (shown in sidebar) |
| `on_ready()` | Override to build UI and initialize state |
| `on_settings_changed(settings)` | Override to react to settings changes |

## Background Workers

Use `PluginWorker` for long-running tasks. It handles busy state, error handling, and logging automatically:

```python
from forkbit_sdk import BasePlugin, PluginWorker


class BuildWorker(PluginWorker):
    def execute(self) -> str:
        self.log_message.emit("Building...")
        self.step_changed.emit(0)
        # do work
        self.step_changed.emit(1)
        return "Build complete"


class MyPlugin(BasePlugin):
    def _on_build(self):
        worker = BuildWorker(self)
        worker.log_message.connect(self._append_log)
        worker.done.connect(self._on_done)
        worker.start()  # automatically sets busy=True

    def _on_done(self, success, message):
        # busy=False is set automatically
        self.notify(message, "success" if success else "error")
```

## Settings Schema

Define user-configurable settings in `settings.json`:

```json
{
  "fields": [
    { "id": "api_key", "label": "API Key", "type": "password" },
    { "id": "auto_sync", "label": "Auto-sync on save", "type": "bool", "default": true }
  ]
}
```

Supported types: `text`, `password`, `textarea`, `bool`, `secret_file`.

## Plugin Manifest

`plugin.json` defines your plugin's metadata:

```json
{
  "id": "com.mycompany.myplugin",
  "name": "My Plugin",
  "version": "1.0.0",
  "description": "What it does",
  "entry": "main.py",
  "min_app_version": "0.2.0",
  "requirements": []
}
```

## Development Mode

During development you don't need to build a `.forkbit` file. Register your plugin directory in ForkBit:

1. Open **Settings → Plugins**
2. Under **Development**, click **"Add Path…"**
3. Select the directory containing your `plugin.json`

Your plugin appears in the Add Plugin dialog with a `(dev)` label and loads directly from source.

## CLI Commands

```bash
forkbit plugin init [dir]        # scaffold a new plugin
forkbit plugin validate [dir]    # check manifest and imports
forkbit plugin build [dir]       # build for current platform
forkbit plugin release [dir]     # build for all platforms
```

## Documentation

Build the docs locally:

```bash
pip install forkbit-sdk[docs]
cd docs
sphinx-build -b html . _build/html
open _build/html/index.html
```

For live-reload during editing:

```bash
sphinx-autobuild docs docs/_build/html
```

## License

MIT
