@muhammedaksam/easiarr 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +173 -0
- package/package.json +72 -0
- package/src/VersionInfo.ts +12 -0
- package/src/api/arr-api.ts +198 -0
- package/src/api/index.ts +1 -0
- package/src/apps/categories.ts +14 -0
- package/src/apps/index.ts +2 -0
- package/src/apps/registry.ts +868 -0
- package/src/compose/generator.ts +234 -0
- package/src/compose/index.ts +2 -0
- package/src/compose/templates.ts +68 -0
- package/src/config/defaults.ts +37 -0
- package/src/config/index.ts +3 -0
- package/src/config/manager.ts +109 -0
- package/src/config/schema.ts +191 -0
- package/src/docker/client.ts +129 -0
- package/src/docker/index.ts +1 -0
- package/src/index.ts +24 -0
- package/src/structure/manager.ts +86 -0
- package/src/ui/App.ts +95 -0
- package/src/ui/components/ApplicationSelector.ts +256 -0
- package/src/ui/components/FileEditor.ts +91 -0
- package/src/ui/components/PageLayout.ts +104 -0
- package/src/ui/index.ts +1 -0
- package/src/ui/screens/AdvancedSettings.ts +177 -0
- package/src/ui/screens/ApiKeyViewer.ts +223 -0
- package/src/ui/screens/AppConfigurator.ts +549 -0
- package/src/ui/screens/AppManager.ts +271 -0
- package/src/ui/screens/ContainerControl.ts +142 -0
- package/src/ui/screens/MainMenu.ts +161 -0
- package/src/ui/screens/QuickSetup.ts +1110 -0
- package/src/ui/screens/SecretsEditor.ts +256 -0
- package/src/ui/screens/index.ts +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Muhammed Mustafa AKŞAM
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# easiarr
|
|
2
|
+
|
|
3
|
+
> **It could be easiarr.**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@muhammedaksam/easiarr)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://bun.sh/)
|
|
9
|
+
[](https://github.com/muhammedaksam/easiarr/actions)
|
|
10
|
+
|
|
11
|
+
> ⚠️ **Work In Progress** - This project is in early experimental development. Features may be incomplete, unstable, or change without notice.
|
|
12
|
+
|
|
13
|
+
TUI tool for generating docker-compose files for the \*arr media ecosystem with 41 apps, TRaSH Guides best practices, VPN routing, and Traefik reverse proxy support.
|
|
14
|
+
|
|
15
|
+
A terminal-based wizard that helps you set up Radarr, Sonarr, Prowlarr, and other \*arr applications with Docker Compose, following best practices from [TRaSH Guides](https://trash-guides.info/).
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- 📦 **Quick Setup Wizard** - Get started in minutes with a guided setup flow
|
|
20
|
+
- 🐳 **Docker Compose Generation** - Automatically generates optimized `docker-compose.yml`
|
|
21
|
+
- ✅ **TRaSH Guides Compliant** - Follows best practices for folder structure and hardlinks
|
|
22
|
+
- 🎮 **Container Control** - Start, stop, and restart containers directly from the TUI
|
|
23
|
+
- ⚙️ **App Management** - Add or remove apps from your stack with ease
|
|
24
|
+
- 💾 **Persistent Configuration** - Settings saved to `~/.easiarr/config.json`
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### Run directly with bunx (no installation required)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bunx @muhammedaksam/easiarr
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Or install globally
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
bun add -g @muhammedaksam/easiarr
|
|
38
|
+
easiarr
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Or clone and run locally
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://github.com/muhammedaksam/easiarr.git
|
|
45
|
+
cd easiarr
|
|
46
|
+
bun install
|
|
47
|
+
bun run start
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Requirements
|
|
51
|
+
|
|
52
|
+
- [Bun](https://bun.sh/) >= 1.0
|
|
53
|
+
- [Docker](https://www.docker.com/) with Docker Compose v2
|
|
54
|
+
|
|
55
|
+
## Supported Applications (41 apps across 10 categories)
|
|
56
|
+
|
|
57
|
+
### Media Management (Servarr)
|
|
58
|
+
|
|
59
|
+
- **Radarr** - Movie collection manager
|
|
60
|
+
- **Sonarr** - TV series collection manager
|
|
61
|
+
- **Lidarr** - Music collection manager
|
|
62
|
+
- **Readarr** - Book collection manager
|
|
63
|
+
- **Bazarr** - Subtitle manager for Sonarr/Radarr
|
|
64
|
+
- **Mylar3** - Comic book collection manager
|
|
65
|
+
- **Whisparr** - Adult media collection manager
|
|
66
|
+
- **Audiobookshelf** - Audiobook and podcast server
|
|
67
|
+
|
|
68
|
+
### Indexers
|
|
69
|
+
|
|
70
|
+
- **Prowlarr** - Indexer manager for \*arr apps
|
|
71
|
+
- **Jackett** - Alternative indexer manager
|
|
72
|
+
- **FlareSolverr** - Cloudflare bypass proxy
|
|
73
|
+
|
|
74
|
+
### Download Clients
|
|
75
|
+
|
|
76
|
+
- **qBittorrent** - BitTorrent client
|
|
77
|
+
- **SABnzbd** - Usenet downloader
|
|
78
|
+
|
|
79
|
+
### Media Servers
|
|
80
|
+
|
|
81
|
+
- **Plex** - Media server with streaming
|
|
82
|
+
- **Jellyfin** - Free open-source media server
|
|
83
|
+
- **Tautulli** - Plex monitoring and statistics
|
|
84
|
+
- **Tdarr** - Audio/video transcoding automation
|
|
85
|
+
|
|
86
|
+
### Request Management
|
|
87
|
+
|
|
88
|
+
- **Overseerr** - Request management for Plex
|
|
89
|
+
- **Jellyseerr** - Request management for Jellyfin
|
|
90
|
+
|
|
91
|
+
### Dashboards
|
|
92
|
+
|
|
93
|
+
- **Homarr** - Modern dashboard for all services
|
|
94
|
+
- **Heimdall** - Application dashboard and launcher
|
|
95
|
+
- **Homepage** - Highly customizable application dashboard
|
|
96
|
+
|
|
97
|
+
### Utilities
|
|
98
|
+
|
|
99
|
+
- **Portainer** - Docker container management UI
|
|
100
|
+
- **Huntarr** - Missing content manager for \*arr apps
|
|
101
|
+
- **Unpackerr** - Archive extraction for \*arr apps
|
|
102
|
+
- **FileBot** - Media file renaming and automator
|
|
103
|
+
- **Chromium** - Web browser for secure remote browsing
|
|
104
|
+
- **Guacamole** - Clientless remote desktop gateway
|
|
105
|
+
- **DDNS-Updater** - Dynamic DNS record updater
|
|
106
|
+
|
|
107
|
+
### VPN
|
|
108
|
+
|
|
109
|
+
- **Gluetun** - VPN client container for routing traffic
|
|
110
|
+
|
|
111
|
+
### Monitoring
|
|
112
|
+
|
|
113
|
+
- **Grafana** - Visual monitoring dashboard
|
|
114
|
+
- **Prometheus** - Systems and service monitoring
|
|
115
|
+
- **Dozzle** - Real-time log viewer for Docker containers
|
|
116
|
+
- **Uptime Kuma** - Self-hosted monitoring tool
|
|
117
|
+
|
|
118
|
+
### Infrastructure
|
|
119
|
+
|
|
120
|
+
- **Traefik** - Reverse proxy and load balancer
|
|
121
|
+
- **Traefik Certs Dumper** - Extracts certificates from Traefik
|
|
122
|
+
- **CrowdSec** - Intrusion prevention system
|
|
123
|
+
- **Headscale** - Open-source Tailscale control server
|
|
124
|
+
- **Headplane** - Headscale web UI
|
|
125
|
+
- **Tailscale** - VPN mesh network client
|
|
126
|
+
- **Authentik** - Identity provider and SSO
|
|
127
|
+
- **PostgreSQL** - Database server
|
|
128
|
+
- **Valkey** - Redis-compatible key-value store
|
|
129
|
+
|
|
130
|
+
## Configuration
|
|
131
|
+
|
|
132
|
+
easiarr stores its configuration in `~/.easiarr/`:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
~/.easiarr/
|
|
136
|
+
├── config.json # Your easiarr configuration
|
|
137
|
+
├── docker-compose.yml # Generated Docker Compose file
|
|
138
|
+
└── backups/ # Configuration backups
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Install dependencies
|
|
145
|
+
bun install
|
|
146
|
+
|
|
147
|
+
# Run in development mode (with watch)
|
|
148
|
+
bun run dev
|
|
149
|
+
|
|
150
|
+
# Type check
|
|
151
|
+
bun run typecheck
|
|
152
|
+
|
|
153
|
+
# Lint
|
|
154
|
+
bun run lint
|
|
155
|
+
|
|
156
|
+
# Format
|
|
157
|
+
bun run format
|
|
158
|
+
|
|
159
|
+
# Run all checks (typecheck + lint + format:check)
|
|
160
|
+
bun run check
|
|
161
|
+
|
|
162
|
+
# Fix all issues (lint:fix + format)
|
|
163
|
+
bun run fix
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
169
|
+
|
|
170
|
+
## Related Projects
|
|
171
|
+
|
|
172
|
+
- [TRaSH Guides](https://trash-guides.info/) - Quality guides for Radarr, Sonarr, and more
|
|
173
|
+
- [OpenTUI](https://github.com/opentui/opentui) - Terminal UI framework used by easiarr
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@muhammedaksam/easiarr",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TUI tool for generating docker-compose files for the *arr media ecosystem with 41 apps, TRaSH Guides best practices, VPN routing, and Traefik reverse proxy support",
|
|
5
|
+
"module": "src/index.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"easiarr": "./src/index.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src"
|
|
12
|
+
],
|
|
13
|
+
"author": "Muhammed Mustafa AKŞAM <info@muhammedaksam.com.tr> (https://github.com/muhammedaksam)",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/muhammedaksam/easiarr.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/muhammedaksam/easiarr/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/muhammedaksam/easiarr#readme",
|
|
23
|
+
"keywords": [
|
|
24
|
+
"arr",
|
|
25
|
+
"radarr",
|
|
26
|
+
"sonarr",
|
|
27
|
+
"prowlarr",
|
|
28
|
+
"docker",
|
|
29
|
+
"docker-compose",
|
|
30
|
+
"trash-guides",
|
|
31
|
+
"tui",
|
|
32
|
+
"opentui",
|
|
33
|
+
"cli",
|
|
34
|
+
"media-server"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"dev": "bun run --watch src/index.ts",
|
|
38
|
+
"build": "bun build src/index.ts --outdir dist --target bun",
|
|
39
|
+
"typecheck": "bun x tsc --noEmit",
|
|
40
|
+
"lint": "eslint src/",
|
|
41
|
+
"lint:fix": "eslint src/ --fix",
|
|
42
|
+
"format": "prettier --write src/",
|
|
43
|
+
"format:check": "prettier --check src/",
|
|
44
|
+
"test": "jest",
|
|
45
|
+
"test:watch": "jest --watch",
|
|
46
|
+
"check": "bun run typecheck && bun run lint && bun run format:check && bun run test",
|
|
47
|
+
"fix": "bun run lint:fix && bun run format",
|
|
48
|
+
"start": "bun run src/index.ts"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@eslint/js": "^9.39.1",
|
|
52
|
+
"@types/bun": "latest",
|
|
53
|
+
"@types/jest": "^30.0.0",
|
|
54
|
+
"@types/node": "^25.0.0",
|
|
55
|
+
"eslint": "^9.39.1",
|
|
56
|
+
"jest": "^30.2.0",
|
|
57
|
+
"jiti": "^2.6.1",
|
|
58
|
+
"prettier": "^3.7.4",
|
|
59
|
+
"ts-jest": "^29.4.6",
|
|
60
|
+
"typescript-eslint": "^8.49.0",
|
|
61
|
+
"yaml": "^2.8.2"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"typescript": "^5.9.3"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"@opentui/core": "^0.1.60"
|
|
68
|
+
},
|
|
69
|
+
"engines": {
|
|
70
|
+
"bun": ">=1.0"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import packageJson from "../package.json" with { type: "json" }
|
|
2
|
+
|
|
3
|
+
const pkg = packageJson
|
|
4
|
+
|
|
5
|
+
export const VersionInfo = {
|
|
6
|
+
version: pkg.version,
|
|
7
|
+
name: pkg.name,
|
|
8
|
+
description: pkg.description,
|
|
9
|
+
author: pkg.author,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const getVersion = () => `v${VersionInfo.version}`
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* *arr API Client
|
|
3
|
+
* Interacts with Radarr, Sonarr, Lidarr, Readarr, Whisparr APIs
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Types for Root Folder API
|
|
7
|
+
export interface RootFolder {
|
|
8
|
+
id?: number
|
|
9
|
+
path: string
|
|
10
|
+
accessible?: boolean
|
|
11
|
+
freeSpace?: number | null
|
|
12
|
+
unmappedFolders?: { name: string | null; path: string | null; relativePath: string | null }[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Types for Download Client API
|
|
16
|
+
export interface DownloadClientConfig {
|
|
17
|
+
name: string
|
|
18
|
+
implementation: string
|
|
19
|
+
configContract: string
|
|
20
|
+
enable?: boolean
|
|
21
|
+
priority?: number
|
|
22
|
+
fields: { name: string; value: unknown }[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DownloadClient extends DownloadClientConfig {
|
|
26
|
+
id?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
import type { AppId } from "../config/schema"
|
|
30
|
+
|
|
31
|
+
// Get category name for an app
|
|
32
|
+
function getCategoryForApp(appId: AppId): string {
|
|
33
|
+
switch (appId) {
|
|
34
|
+
case "radarr":
|
|
35
|
+
return "movies"
|
|
36
|
+
case "sonarr":
|
|
37
|
+
return "tv"
|
|
38
|
+
case "lidarr":
|
|
39
|
+
return "music"
|
|
40
|
+
case "readarr":
|
|
41
|
+
return "books"
|
|
42
|
+
case "whisparr":
|
|
43
|
+
return "adult"
|
|
44
|
+
default:
|
|
45
|
+
return "default"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Get category field name for an app (different apps use different field names)
|
|
50
|
+
function getCategoryFieldName(appId: AppId): string {
|
|
51
|
+
switch (appId) {
|
|
52
|
+
case "radarr":
|
|
53
|
+
case "whisparr":
|
|
54
|
+
return "movieCategory"
|
|
55
|
+
case "sonarr":
|
|
56
|
+
return "tvCategory"
|
|
57
|
+
case "lidarr":
|
|
58
|
+
return "musicCategory"
|
|
59
|
+
case "readarr":
|
|
60
|
+
return "bookCategory"
|
|
61
|
+
default:
|
|
62
|
+
return "category"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// qBittorrent download client config
|
|
67
|
+
export function createQBittorrentConfig(
|
|
68
|
+
host: string,
|
|
69
|
+
port: number,
|
|
70
|
+
username: string,
|
|
71
|
+
password: string,
|
|
72
|
+
appId?: AppId
|
|
73
|
+
): DownloadClientConfig {
|
|
74
|
+
const category = appId ? getCategoryForApp(appId) : "default"
|
|
75
|
+
const categoryField = appId ? getCategoryFieldName(appId) : "category"
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
name: "qBittorrent",
|
|
79
|
+
implementation: "QBittorrent",
|
|
80
|
+
configContract: "QBittorrentSettings",
|
|
81
|
+
enable: true,
|
|
82
|
+
priority: 1,
|
|
83
|
+
fields: [
|
|
84
|
+
{ name: "host", value: host },
|
|
85
|
+
{ name: "port", value: port },
|
|
86
|
+
{ name: "username", value: username },
|
|
87
|
+
{ name: "password", value: password },
|
|
88
|
+
{ name: categoryField, value: category },
|
|
89
|
+
{ name: "recentMoviePriority", value: 0 },
|
|
90
|
+
{ name: "olderMoviePriority", value: 0 },
|
|
91
|
+
{ name: "initialState", value: 0 },
|
|
92
|
+
{ name: "sequentialOrder", value: false },
|
|
93
|
+
{ name: "firstAndLast", value: false },
|
|
94
|
+
],
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// SABnzbd download client config
|
|
99
|
+
export function createSABnzbdConfig(host: string, port: number, apiKey: string, appId?: AppId): DownloadClientConfig {
|
|
100
|
+
const category = appId ? getCategoryForApp(appId) : "default"
|
|
101
|
+
const categoryField = appId ? getCategoryFieldName(appId) : "category"
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
name: "SABnzbd",
|
|
105
|
+
implementation: "Sabnzbd",
|
|
106
|
+
configContract: "SabnzbdSettings",
|
|
107
|
+
enable: true,
|
|
108
|
+
priority: 1,
|
|
109
|
+
fields: [
|
|
110
|
+
{ name: "host", value: host },
|
|
111
|
+
{ name: "port", value: port },
|
|
112
|
+
{ name: "apiKey", value: apiKey },
|
|
113
|
+
{ name: categoryField, value: category },
|
|
114
|
+
{ name: "recentMoviePriority", value: -100 },
|
|
115
|
+
{ name: "olderMoviePriority", value: -100 },
|
|
116
|
+
],
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type ApiVersion = "v1" | "v3"
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* *arr API Client
|
|
124
|
+
*/
|
|
125
|
+
export class ArrApiClient {
|
|
126
|
+
private baseUrl: string
|
|
127
|
+
private apiKey: string
|
|
128
|
+
private apiVersion: ApiVersion
|
|
129
|
+
|
|
130
|
+
constructor(host: string, port: number, apiKey: string, apiVersion: ApiVersion = "v3") {
|
|
131
|
+
this.baseUrl = `http://${host}:${port}`
|
|
132
|
+
this.apiKey = apiKey
|
|
133
|
+
this.apiVersion = apiVersion
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
|
137
|
+
const url = `${this.baseUrl}/api/${this.apiVersion}${endpoint}`
|
|
138
|
+
const headers = {
|
|
139
|
+
"X-Api-Key": this.apiKey,
|
|
140
|
+
"Content-Type": "application/json",
|
|
141
|
+
...options.headers,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const response = await fetch(url, { ...options, headers })
|
|
145
|
+
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
throw new Error(`API request failed: ${response.status} ${response.statusText}`)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Handle empty responses (DELETE returns empty body)
|
|
151
|
+
const text = await response.text()
|
|
152
|
+
if (!text) return {} as T
|
|
153
|
+
|
|
154
|
+
return JSON.parse(text) as T
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Root Folder methods
|
|
158
|
+
async getRootFolders(): Promise<RootFolder[]> {
|
|
159
|
+
return this.request<RootFolder[]>("/rootfolder")
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async addRootFolder(path: string): Promise<RootFolder> {
|
|
163
|
+
return this.request<RootFolder>("/rootfolder", {
|
|
164
|
+
method: "POST",
|
|
165
|
+
body: JSON.stringify({ path }),
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async deleteRootFolder(id: number): Promise<void> {
|
|
170
|
+
await this.request(`/rootfolder/${id}`, { method: "DELETE" })
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Download Client methods
|
|
174
|
+
async getDownloadClients(): Promise<DownloadClient[]> {
|
|
175
|
+
return this.request<DownloadClient[]>("/downloadclient")
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async addDownloadClient(config: DownloadClientConfig): Promise<DownloadClient> {
|
|
179
|
+
return this.request<DownloadClient>("/downloadclient", {
|
|
180
|
+
method: "POST",
|
|
181
|
+
body: JSON.stringify(config),
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async deleteDownloadClient(id: number): Promise<void> {
|
|
186
|
+
await this.request(`/downloadclient/${id}`, { method: "DELETE" })
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Health check
|
|
190
|
+
async isHealthy(): Promise<boolean> {
|
|
191
|
+
try {
|
|
192
|
+
await this.request("/system/status")
|
|
193
|
+
return true
|
|
194
|
+
} catch {
|
|
195
|
+
return false
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./arr-api"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AppCategory } from "../config/schema"
|
|
2
|
+
|
|
3
|
+
export const CATEGORY_ORDER: { id: AppCategory; short: string }[] = [
|
|
4
|
+
{ id: "servarr", short: "Media" },
|
|
5
|
+
{ id: "indexer", short: "Index" },
|
|
6
|
+
{ id: "downloader", short: "DL" },
|
|
7
|
+
{ id: "mediaserver", short: "Server" },
|
|
8
|
+
{ id: "request", short: "Request" },
|
|
9
|
+
{ id: "dashboard", short: "Dash" },
|
|
10
|
+
{ id: "utility", short: "Utils" },
|
|
11
|
+
{ id: "vpn", short: "VPN" },
|
|
12
|
+
{ id: "monitoring", short: "Monitor" },
|
|
13
|
+
{ id: "infrastructure", short: "Infra" },
|
|
14
|
+
]
|