@muhammedaksam/easiarr 0.1.1 → 0.1.4
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/package.json +1 -1
- package/src/apps/registry.ts +33 -0
- package/src/config/schema.ts +13 -0
- package/src/ui/components/ApplicationSelector.ts +21 -5
- package/src/util/arch.ts +78 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muhammedaksam/easiarr",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
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
5
|
"module": "src/index.ts",
|
|
6
6
|
"type": "module",
|
package/src/apps/registry.ts
CHANGED
|
@@ -94,6 +94,10 @@ export const APPS: Record<AppId, AppDefinition> = {
|
|
|
94
94
|
path: "/data/media/books",
|
|
95
95
|
apiVersion: "v1",
|
|
96
96
|
},
|
|
97
|
+
arch: {
|
|
98
|
+
deprecated: ["arm64", "arm32"],
|
|
99
|
+
warning: "Readarr is deprecated - no ARM64 support (project abandoned by upstream)",
|
|
100
|
+
},
|
|
97
101
|
},
|
|
98
102
|
|
|
99
103
|
bazarr: {
|
|
@@ -866,3 +870,32 @@ export function getAllApps(): AppDefinition[] {
|
|
|
866
870
|
export function getAppIds(): AppId[] {
|
|
867
871
|
return Object.keys(APPS) as AppId[]
|
|
868
872
|
}
|
|
873
|
+
|
|
874
|
+
import { getSystemArch, isAppCompatible, getArchWarning, isAppDeprecated } from "../util/arch"
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Get all apps compatible with the current system architecture
|
|
878
|
+
*/
|
|
879
|
+
export function getCompatibleApps(): AppDefinition[] {
|
|
880
|
+
const arch = getSystemArch()
|
|
881
|
+
return Object.values(APPS).filter((app) => isAppCompatible(app, arch))
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Get apps that have warnings for the current architecture (deprecated but may work)
|
|
886
|
+
*/
|
|
887
|
+
export function getAppsWithArchWarnings(): { app: AppDefinition; warning: string }[] {
|
|
888
|
+
const arch = getSystemArch()
|
|
889
|
+
const result: { app: AppDefinition; warning: string }[] = []
|
|
890
|
+
|
|
891
|
+
for (const app of Object.values(APPS)) {
|
|
892
|
+
const warning = getArchWarning(app, arch)
|
|
893
|
+
if (warning) {
|
|
894
|
+
result.push({ app, warning })
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
return result
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
export { getSystemArch, isAppCompatible, getArchWarning, isAppDeprecated }
|
package/src/config/schema.ts
CHANGED
|
@@ -123,6 +123,17 @@ export type AppCategory =
|
|
|
123
123
|
| "monitoring"
|
|
124
124
|
| "infrastructure"
|
|
125
125
|
|
|
126
|
+
export type Architecture = "x64" | "arm64" | "arm32"
|
|
127
|
+
|
|
128
|
+
export interface ArchCompatibility {
|
|
129
|
+
/** Architectures with full support */
|
|
130
|
+
supported?: Architecture[]
|
|
131
|
+
/** Architectures with deprecated/broken support - will show warning */
|
|
132
|
+
deprecated?: Architecture[]
|
|
133
|
+
/** Warning message to show for deprecated architectures */
|
|
134
|
+
warning?: string
|
|
135
|
+
}
|
|
136
|
+
|
|
126
137
|
export interface AppDefinition {
|
|
127
138
|
id: AppId
|
|
128
139
|
name: string
|
|
@@ -141,6 +152,8 @@ export interface AppDefinition {
|
|
|
141
152
|
cap_add?: string[]
|
|
142
153
|
apiKeyMeta?: ApiKeyMeta
|
|
143
154
|
rootFolder?: RootFolderMeta
|
|
155
|
+
/** Architecture compatibility info - omit if supports all */
|
|
156
|
+
arch?: ArchCompatibility
|
|
144
157
|
}
|
|
145
158
|
|
|
146
159
|
export interface RootFolderMeta {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "@opentui/core"
|
|
12
12
|
import { AppId } from "../../config/schema"
|
|
13
13
|
import { CATEGORY_ORDER } from "../../apps/categories"
|
|
14
|
-
import { getAppsByCategory } from "../../apps"
|
|
14
|
+
import { getAppsByCategory, getArchWarning } from "../../apps"
|
|
15
15
|
|
|
16
16
|
export interface ApplicationSelectorOptions extends BoxOptions {
|
|
17
17
|
selectedApps: Set<AppId>
|
|
@@ -139,10 +139,15 @@ export class ApplicationSelector extends BoxRenderable {
|
|
|
139
139
|
const category = CATEGORY_ORDER[this.currentCategoryIndex]
|
|
140
140
|
const apps = getAppsByCategory()[category.id] || []
|
|
141
141
|
|
|
142
|
-
const options = apps.map((app) =>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
const options = apps.map((app) => {
|
|
143
|
+
const archWarning = getArchWarning(app)
|
|
144
|
+
const checkmark = this.selectedApps.has(app.id) ? "[✓]" : "[ ]"
|
|
145
|
+
const warnIcon = archWarning ? " ⚠️" : ""
|
|
146
|
+
return {
|
|
147
|
+
name: `${checkmark} ${app.name}${warnIcon}`,
|
|
148
|
+
description: archWarning ? `⚠️ ${archWarning}` : `Port ${app.defaultPort} - ${app.description}`,
|
|
149
|
+
}
|
|
150
|
+
})
|
|
146
151
|
|
|
147
152
|
this.appList.options = options
|
|
148
153
|
}
|
|
@@ -177,6 +182,17 @@ export class ApplicationSelector extends BoxRenderable {
|
|
|
177
182
|
check(["overseerr", "jellyseerr"], "Multiple request managers")
|
|
178
183
|
check(["prowlarr", "jackett"], "Multiple indexers")
|
|
179
184
|
|
|
185
|
+
// Architecture warnings for selected apps
|
|
186
|
+
const allApps = Object.values(getAppsByCategory()).flat()
|
|
187
|
+
for (const app of allApps) {
|
|
188
|
+
if (this.selectedApps.has(app.id)) {
|
|
189
|
+
const archWarn = getArchWarning(app)
|
|
190
|
+
if (archWarn) {
|
|
191
|
+
warnings.push(archWarn)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
180
196
|
return warnings
|
|
181
197
|
}
|
|
182
198
|
|
package/src/util/arch.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture Detection Utility
|
|
3
|
+
* Detects system architecture and checks app compatibility
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { AppDefinition, Architecture } from "../config/schema"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get the current system architecture
|
|
10
|
+
*/
|
|
11
|
+
export function getSystemArch(): Architecture {
|
|
12
|
+
const arch = process.arch
|
|
13
|
+
switch (arch) {
|
|
14
|
+
case "x64":
|
|
15
|
+
case "ia32":
|
|
16
|
+
return "x64"
|
|
17
|
+
case "arm64":
|
|
18
|
+
return "arm64"
|
|
19
|
+
case "arm":
|
|
20
|
+
return "arm32"
|
|
21
|
+
default:
|
|
22
|
+
return "x64" // Default to x64 for unknown
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Check if an app is compatible with the given architecture
|
|
28
|
+
* Returns true if compatible (no issues), false if deprecated/broken
|
|
29
|
+
*/
|
|
30
|
+
export function isAppCompatible(app: AppDefinition, arch?: Architecture): boolean {
|
|
31
|
+
const systemArch = arch ?? getSystemArch()
|
|
32
|
+
|
|
33
|
+
if (!app.arch) {
|
|
34
|
+
return true // No arch restrictions = supports all
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Check if explicitly deprecated
|
|
38
|
+
if (app.arch.deprecated?.includes(systemArch)) {
|
|
39
|
+
return false
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// If supported list exists, check if current arch is in it
|
|
43
|
+
if (app.arch.supported && !app.arch.supported.includes(systemArch)) {
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get warning message for an app on the current architecture
|
|
52
|
+
* Returns null if no warning
|
|
53
|
+
*/
|
|
54
|
+
export function getArchWarning(app: AppDefinition, arch?: Architecture): string | null {
|
|
55
|
+
const systemArch = arch ?? getSystemArch()
|
|
56
|
+
|
|
57
|
+
if (!app.arch) {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (app.arch.deprecated?.includes(systemArch)) {
|
|
62
|
+
return app.arch.warning || `${app.name} has deprecated support for ${systemArch}`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (app.arch.supported && !app.arch.supported.includes(systemArch)) {
|
|
66
|
+
return `${app.name} does not support ${systemArch} architecture`
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check if app is deprecated (but might still work)
|
|
74
|
+
*/
|
|
75
|
+
export function isAppDeprecated(app: AppDefinition, arch?: Architecture): boolean {
|
|
76
|
+
const systemArch = arch ?? getSystemArch()
|
|
77
|
+
return app.arch?.deprecated?.includes(systemArch) ?? false
|
|
78
|
+
}
|