Skip to content

Commit d7fc18b

Browse files
Merge pull request #96 from muhammedaksam/develop
Refactor setup architecture and improve code maintainability
2 parents 82bffdd + 47d3406 commit d7fc18b

118 files changed

Lines changed: 7441 additions & 8481 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.prettierrc

Lines changed: 0 additions & 11 deletions
This file was deleted.

.prettierrc.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/** @type {import("prettier").Config} */
2+
const config = {
3+
semi: false,
4+
singleQuote: false,
5+
tabWidth: 2,
6+
trailingComma: "es5",
7+
printWidth: 100,
8+
plugins: ["@ianvs/prettier-plugin-sort-imports"],
9+
importOrder: [
10+
"<TYPES>",
11+
"^node:(.*)$",
12+
"",
13+
"<THIRD_PARTY_MODULES>",
14+
"",
15+
"<TYPES>^[.|..|~]",
16+
"^~/(.*)$",
17+
"^[../]",
18+
"^[./]",
19+
],
20+
importOrderParserPlugins: ["typescript"],
21+
importOrderTypeScriptVersion: "5.0.0",
22+
}
23+
24+
export default config

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ A terminal-based wizard that helps you set up Radarr, Sonarr, Prowlarr, and othe
2323
- 🎮 **Container Control** - Start, stop, and restart containers directly from the TUI
2424
- 📋 **Container Logs Viewer** - View and save Docker container logs from the TUI
2525
- ⚙️ **App Management** - Add or remove apps from your stack with ease
26-
- 💾 **Persistent Configuration** - Settings saved to `~/.easiarr/config.json`
26+
- 💾 **Persistent Configuration** - Settings saved to `$XDG_CONFIG_HOME/easiarr/config.json`
2727
- 🔀 **Reverse Proxy** - Traefik or Caddy support with automatic SSL
2828
- 🖥️ **Unraid Support** - Automatic OS detection and compatibility
2929

@@ -163,10 +163,10 @@ The wizard will automatically:
163163

164164
## Configuration
165165

166-
easiarr stores its configuration in `~/.easiarr/`:
166+
easiarr stores its configuration in `$XDG_CONFIG_HOME/easiarr/`:
167167

168168
```bash
169-
~/.easiarr/
169+
$XDG_CONFIG_HOME/easiarr/
170170
├── config.json # Your easiarr configuration
171171
├── docker-compose.yml # Generated Docker Compose file
172172
└── backups/ # Configuration backups

SECURITY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ If you discover a security vulnerability in easiarr, please report it responsibl
3232
easiarr stores sensitive information in `.env` files. Always:
3333

3434
- Never commit `.env` files to version control
35-
- Set restrictive file permissions: `chmod 600 ~/.easiarr/.env`
35+
- Set restrictive file permissions: `chmod 600 $XDG_CONFIG_HOME/easiarr/.env`
3636
- Use strong, unique passwords for each service
3737
- Regularly rotate API keys and credentials
3838

bun.lock

Lines changed: 286 additions & 64 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

eslint.config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import eslint from "@eslint/js"
2-
import tseslint from "typescript-eslint"
2+
import importPlugin from "eslint-plugin-import"
33
import { defineConfig, globalIgnores } from "eslint/config"
4+
import tseslint from "typescript-eslint"
45

56
export default defineConfig([
67
globalIgnores(["dist/", "node_modules/"]),
@@ -11,6 +12,7 @@ export default defineConfig([
1112
plugins: {
1213
js: eslint,
1314
"@typescript-eslint": tseslint.plugin,
15+
import: importPlugin,
1416
},
1517
extends: [eslint.configs.recommended, ...tseslint.configs.recommended],
1618
languageOptions: {
@@ -27,6 +29,9 @@ export default defineConfig([
2729
"@typescript-eslint/explicit-function-return-type": "off",
2830
"@typescript-eslint/no-non-null-assertion": "off",
2931

32+
// Import ordering
33+
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
34+
3035
// General
3136
"no-console": "off",
3237
"prefer-const": "error",

jest.config.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
},
1313
extensionsToTreatAsEsm: [".ts"],
1414
moduleNameMapper: {
15+
"^~/(.*)$": "<rootDir>/src/$1",
1516
"^(\\.{1,2}/.*)\\.js$": "$1",
1617
},
1718
}

package.json

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@muhammedaksam/easiarr",
3-
"version": "1.3.5",
3+
"version": "1.4.0",
44
"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",
55
"module": "src/index.ts",
66
"type": "module",
@@ -51,23 +51,25 @@
5151
"start": "bun run src/index.ts"
5252
},
5353
"devDependencies": {
54-
"@eslint/js": "^9.39.2",
54+
"@eslint/js": "^10.0.1",
55+
"@ianvs/prettier-plugin-sort-imports": "^4.7.1",
5556
"@types/bcrypt": "^6.0.0",
5657
"@types/bun": "latest",
5758
"@types/jest": "^30.0.0",
58-
"@types/node": "^25.0.10",
59-
"eslint": "^9.39.2",
59+
"@types/node": "^25.2.3",
60+
"eslint": "^10.0.0",
61+
"eslint-plugin-import": "^2.32.0",
6062
"jest": "^30.2.0",
6163
"jiti": "^2.6.1",
6264
"prettier": "^3.8.1",
6365
"ts-jest": "^29.4.6",
64-
"typescript-eslint": "^8.54.0"
66+
"typescript-eslint": "^8.55.0"
6567
},
6668
"peerDependencies": {
6769
"typescript": "^5.9.3"
6870
},
6971
"dependencies": {
70-
"@opentui/core": "^0.1.75",
72+
"@opentui/core": "^0.1.79",
7173
"bcrypt": "^6.0.0",
7274
"socket.io-client": "^4.8.3",
7375
"yaml": "^2.8.2"

src/api/arr-api.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
* Interacts with Radarr, Sonarr, Lidarr, Readarr, Whisparr APIs
44
*/
55

6-
import { debugLog } from "../utils/debug"
6+
import type { NamingConfig } from "./naming-config"
7+
import type { AppId } from "~/config/schema"
8+
import { getCategoryFieldName, getCategoryForApp } from "~/utils/categories"
9+
import { debugLog } from "~/utils/debug"
10+
import { TRASH_NAMING_CONFIG } from "./naming-config"
711

812
// Types for Root Folder API
913
export interface RootFolder {
@@ -44,10 +48,6 @@ export interface RemotePathMapping {
4448
localPath: string
4549
}
4650

47-
import type { AppId } from "../config/schema"
48-
import { getCategoryForApp, getCategoryFieldName } from "../utils/categories"
49-
import { TRASH_NAMING_CONFIG, type NamingConfig } from "./naming-config"
50-
5151
// qBittorrent download client config
5252
export function createQBittorrentConfig(
5353
host: string,
@@ -82,7 +82,12 @@ export function createQBittorrentConfig(
8282
}
8383

8484
// SABnzbd download client config
85-
export function createSABnzbdConfig(host: string, port: number, apiKey: string, appId?: AppId): DownloadClientConfig {
85+
export function createSABnzbdConfig(
86+
host: string,
87+
port: number,
88+
apiKey: string,
89+
appId?: AppId
90+
): DownloadClientConfig {
8691
const category = appId ? getCategoryForApp(appId) : "default"
8792
const categoryField = appId ? getCategoryFieldName(appId) : "category"
8893

@@ -214,7 +219,11 @@ export class ArrApiClient {
214219
return this.request<HostConfig>("/config/host")
215220
}
216221

217-
async updateHostConfig(username: string, password: string, override = false): Promise<HostConfig | null> {
222+
async updateHostConfig(
223+
username: string,
224+
password: string,
225+
override = false
226+
): Promise<HostConfig | null> {
218227
// First get current config to preserve all other settings
219228
const currentConfig = await this.getHostConfig()
220229

@@ -293,11 +302,15 @@ export class ArrApiClient {
293302
// 3. Update configuration
294303
await this.updateNamingConfig(newConfig)
295304
} catch (e) {
296-
throw new Error(`Failed to configure naming: ${e}`)
305+
throw new Error(`Failed to configure naming: ${e}`, { cause: e })
297306
}
298307
}
299308

300-
async addRemotePathMapping(host: string, remotePath: string, localPath: string): Promise<RemotePathMapping> {
309+
async addRemotePathMapping(
310+
host: string,
311+
remotePath: string,
312+
localPath: string
313+
): Promise<RemotePathMapping> {
301314
return this.request<RemotePathMapping>("/remotepathmapping", {
302315
method: "POST",
303316
body: JSON.stringify({ host, remotePath, localPath }),

src/api/auto-setup-types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Interfaces for auto-setup capability metadata and clients
44
*/
55

6-
import type { AppId } from "../config/schema"
6+
import type { AppId } from "~/config/schema"
77

88
/**
99
* Describes an app's auto-setup capability

0 commit comments

Comments
 (0)