@muhammedaksam/easiarr 1.4.0 → 1.4.1

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.
Files changed (109) hide show
  1. package/dist/index.js +29837 -0
  2. package/package.json +15 -15
  3. package/src/VersionInfo.ts +0 -12
  4. package/src/api/arr-api.ts +0 -521
  5. package/src/api/auto-setup-types.ts +0 -64
  6. package/src/api/base-api.ts +0 -216
  7. package/src/api/bazarr-api.ts +0 -297
  8. package/src/api/cloudflare-api.ts +0 -493
  9. package/src/api/custom-format-api.ts +0 -224
  10. package/src/api/grafana-api.ts +0 -230
  11. package/src/api/heimdall-api.ts +0 -141
  12. package/src/api/homarr-api.ts +0 -209
  13. package/src/api/huntarr-api.ts +0 -457
  14. package/src/api/index.ts +0 -9
  15. package/src/api/jellyfin-api.ts +0 -389
  16. package/src/api/jellyseerr-api.ts +0 -559
  17. package/src/api/maintainerr-api.ts +0 -461
  18. package/src/api/naming-config.ts +0 -101
  19. package/src/api/overseerr-api.ts +0 -392
  20. package/src/api/plex-api.ts +0 -308
  21. package/src/api/portainer-api.ts +0 -374
  22. package/src/api/profilarr-api.ts +0 -391
  23. package/src/api/prowlarr-api.ts +0 -488
  24. package/src/api/qbittorrent-api.ts +0 -300
  25. package/src/api/quality-profile-api.ts +0 -272
  26. package/src/api/tautulli-api.ts +0 -244
  27. package/src/api/uptime-kuma-api.ts +0 -343
  28. package/src/apps/categories.ts +0 -14
  29. package/src/apps/index.ts +0 -2
  30. package/src/apps/registry.ts +0 -1275
  31. package/src/compose/caddy-config.ts +0 -130
  32. package/src/compose/generator.ts +0 -287
  33. package/src/compose/index.ts +0 -7
  34. package/src/compose/templates.ts +0 -78
  35. package/src/compose/traefik-config.ts +0 -187
  36. package/src/config/bookmarks-generator.ts +0 -160
  37. package/src/config/defaults.ts +0 -37
  38. package/src/config/homepage-config.ts +0 -381
  39. package/src/config/index.ts +0 -6
  40. package/src/config/manager.ts +0 -150
  41. package/src/config/recyclarr-config.ts +0 -181
  42. package/src/config/schema.ts +0 -310
  43. package/src/config/slskd-config.ts +0 -86
  44. package/src/config/soularr-config.ts +0 -105
  45. package/src/config/trash-quality-definitions.ts +0 -213
  46. package/src/data/lidarr-custom-formats.ts +0 -127
  47. package/src/data/trash-profiles.ts +0 -333
  48. package/src/docker/client.ts +0 -312
  49. package/src/docker/index.ts +0 -18
  50. package/src/index.ts +0 -77
  51. package/src/setup/actions/arr-common.ts +0 -307
  52. package/src/setup/actions/dashboards.ts +0 -79
  53. package/src/setup/actions/download-clients.ts +0 -54
  54. package/src/setup/actions/jellyseerr.ts +0 -331
  55. package/src/setup/actions/media-servers.ts +0 -68
  56. package/src/setup/actions/monitoring.ts +0 -120
  57. package/src/setup/actions/prowlarr.ts +0 -137
  58. package/src/setup/actions/utilities.ts +0 -490
  59. package/src/setup/index.ts +0 -78
  60. package/src/setup/types.ts +0 -144
  61. package/src/structure/manager.ts +0 -129
  62. package/src/ui/App.ts +0 -111
  63. package/src/ui/components/ApplicationSelector.ts +0 -275
  64. package/src/ui/components/CredentialsForm.ts +0 -180
  65. package/src/ui/components/DownloadClientForm.ts +0 -114
  66. package/src/ui/components/FileEditor.ts +0 -91
  67. package/src/ui/components/FooterHint.ts +0 -119
  68. package/src/ui/components/PageLayout.ts +0 -160
  69. package/src/ui/components/UpdateNotification.ts +0 -102
  70. package/src/ui/index.ts +0 -7
  71. package/src/ui/screens/AdvancedSettings.ts +0 -188
  72. package/src/ui/screens/ApiKeyViewer.ts +0 -511
  73. package/src/ui/screens/AppConfigurator.ts +0 -543
  74. package/src/ui/screens/AppManager.ts +0 -284
  75. package/src/ui/screens/ContainerControl.ts +0 -581
  76. package/src/ui/screens/LogsViewer.ts +0 -478
  77. package/src/ui/screens/MainMenu.ts +0 -299
  78. package/src/ui/screens/MonitorDashboard.ts +0 -881
  79. package/src/ui/screens/SecretsEditor.ts +0 -216
  80. package/src/ui/screens/SettingsScreen.ts +0 -633
  81. package/src/ui/screens/index.ts +0 -22
  82. package/src/ui/screens/setup/BaseAppSetupScreen.ts +0 -375
  83. package/src/ui/screens/setup/CloudflaredSetup.ts +0 -460
  84. package/src/ui/screens/setup/FullAutoSetup.ts +0 -766
  85. package/src/ui/screens/setup/HomepageSetup.ts +0 -165
  86. package/src/ui/screens/setup/JellyfinSetup.ts +0 -328
  87. package/src/ui/screens/setup/JellyseerrSetup.ts +0 -242
  88. package/src/ui/screens/setup/ProwlarrSetup.ts +0 -500
  89. package/src/ui/screens/setup/QBittorrentSetup.ts +0 -221
  90. package/src/ui/screens/setup/QuickSetup.ts +0 -1169
  91. package/src/ui/screens/setup/RecyclarrSetup.ts +0 -270
  92. package/src/ui/screens/setup/TRaSHProfileSetup.ts +0 -381
  93. package/src/utils/arch.ts +0 -78
  94. package/src/utils/browser.ts +0 -27
  95. package/src/utils/categories.ts +0 -61
  96. package/src/utils/debug.ts +0 -84
  97. package/src/utils/env.ts +0 -138
  98. package/src/utils/index.ts +0 -8
  99. package/src/utils/logs.ts +0 -119
  100. package/src/utils/migrations/1765626338_rename_env_variables.ts +0 -102
  101. package/src/utils/migrations/1765707135_rename_easiarr_status.ts +0 -91
  102. package/src/utils/migrations/1765732722_remove_cloudflare_dns_api_token.ts +0 -45
  103. package/src/utils/migrations/1769515650_migrate_to_xdg.ts +0 -114
  104. package/src/utils/migrations.ts +0 -165
  105. package/src/utils/password.ts +0 -42
  106. package/src/utils/paths.ts +0 -33
  107. package/src/utils/unraid.ts +0 -103
  108. package/src/utils/update-checker.ts +0 -210
  109. package/src/utils/url-utils.ts +0 -38
@@ -1,375 +0,0 @@
1
- /**
2
- * Base App Setup Screen
3
- *
4
- * Abstract base class for all app setup screens.
5
- * Provides common UI patterns: menu navigation, results display, key handling.
6
- *
7
- * Subclasses implement:
8
- * - getTitle(): Screen title
9
- * - getStepInfo(): Step info text
10
- * - getMenuItems(): Menu items with actions
11
- *
12
- * @example
13
- * ```ts
14
- * export class JellyfinSetup extends BaseAppSetupScreen {
15
- * getTitle() { return "Jellyfin Setup" }
16
- * getStepInfo() { return "Configure Jellyfin" }
17
- * getMenuItems() {
18
- * return [
19
- * { name: "🚀 Run Wizard", description: "...", action: () => this.runWizard() },
20
- * { name: "↩️ Back", description: "Return", action: () => this.cleanup() },
21
- * ]
22
- * }
23
- * }
24
- * ```
25
- */
26
-
27
- import { BoxRenderable, CliRenderer, KeyEvent, TextRenderable } from "@opentui/core"
28
-
29
- import type { EasiarrConfig } from "~/config/schema"
30
- import { createPageLayout } from "~/ui/components/PageLayout"
31
-
32
- /**
33
- * Result of a setup step
34
- */
35
- export interface SetupResult {
36
- name: string
37
- status: "pending" | "configuring" | "success" | "error" | "skipped"
38
- message?: string
39
- }
40
-
41
- /**
42
- * Menu item definition
43
- */
44
- export interface MenuItem {
45
- name: string
46
- description: string
47
- action: () => void | Promise<void>
48
- }
49
-
50
- /**
51
- * Step state for the screen
52
- */
53
- export type SetupStep = "menu" | "running" | "done"
54
-
55
- /**
56
- * Footer hint item
57
- */
58
- interface FooterHint {
59
- type: "key"
60
- key: string
61
- value: string
62
- }
63
-
64
- export abstract class BaseAppSetupScreen extends BoxRenderable {
65
- protected config: EasiarrConfig
66
- protected cliRenderer: CliRenderer
67
- protected onBack: () => void
68
- protected keyHandler!: (key: KeyEvent) => void
69
- protected contentBox!: BoxRenderable
70
- protected pageContainer!: BoxRenderable
71
-
72
- protected results: SetupResult[] = []
73
- protected currentStep: SetupStep = "menu"
74
- protected menuIndex = 0
75
-
76
- constructor(cliRenderer: CliRenderer, config: EasiarrConfig, onBack: () => void) {
77
- super(cliRenderer, { width: "100%", height: "100%" })
78
-
79
- this.config = config
80
- this.cliRenderer = cliRenderer
81
- this.onBack = onBack
82
-
83
- // Create layout with values from subclass (works because JS allows calling
84
- // overridden methods from constructor, though TypeScript warns about it)
85
- const layout = createPageLayout(cliRenderer, {
86
- title: this.getTitle(),
87
- stepInfo: this.getStepInfo(),
88
- footerHint: this.getFooterHint(),
89
- })
90
- this.pageContainer = layout.container
91
- this.contentBox = layout.content
92
- this.add(this.pageContainer)
93
-
94
- this.initKeyHandler()
95
- this.refreshContent()
96
- }
97
-
98
- // ============================================
99
- // ABSTRACT METHODS - Subclasses must implement
100
- // ============================================
101
-
102
- /**
103
- * Screen title shown in header
104
- */
105
- abstract getTitle(): string
106
-
107
- /**
108
- * Step info text shown below title
109
- */
110
- abstract getStepInfo(): string
111
-
112
- /**
113
- * Menu items to display
114
- */
115
- abstract getMenuItems(): MenuItem[]
116
-
117
- // ============================================
118
- // OPTIONAL OVERRIDES
119
- // ============================================
120
-
121
- /**
122
- * Footer hints. Override to customize.
123
- */
124
- protected getFooterHint(): FooterHint[] {
125
- return [
126
- { type: "key", key: "↑↓", value: "Navigate" },
127
- { type: "key", key: "Enter", value: "Select" },
128
- { type: "key", key: "Esc", value: "Back" },
129
- ]
130
- }
131
-
132
- /**
133
- * Custom content rendering. Override to add custom steps.
134
- * Return false to use default rendering, true if handled.
135
- */
136
- protected renderCustomContent(): boolean {
137
- return false
138
- }
139
-
140
- /**
141
- * Handle custom key events. Override to add custom key handling.
142
- * Return true if handled, false to continue default handling.
143
- */
144
- protected handleCustomKeys(_key: KeyEvent): boolean {
145
- return false
146
- }
147
-
148
- // ============================================
149
- // COMMON IMPLEMENTATION
150
- // ============================================
151
-
152
- protected initKeyHandler(): void {
153
- this.keyHandler = (key: KeyEvent) => {
154
- // Allow subclass to handle first
155
- if (this.handleCustomKeys(key)) {
156
- return
157
- }
158
-
159
- // Escape always goes back
160
- if (key.name === "escape" || (key.name === "c" && key.ctrl)) {
161
- if (this.currentStep === "menu") {
162
- this.cleanup()
163
- } else {
164
- this.currentStep = "menu"
165
- this.refreshContent()
166
- }
167
- return
168
- }
169
-
170
- // Handle based on current step
171
- if (this.currentStep === "menu") {
172
- this.handleMenuKeys(key)
173
- } else if (this.currentStep === "done") {
174
- if (key.name === "return" || key.name === "escape") {
175
- this.currentStep = "menu"
176
- this.refreshContent()
177
- }
178
- }
179
- }
180
- this.cliRenderer.keyInput.on("keypress", this.keyHandler)
181
- }
182
-
183
- protected handleMenuKeys(key: KeyEvent): void {
184
- const menuItems = this.getMenuItems()
185
-
186
- if (key.name === "up" && this.menuIndex > 0) {
187
- this.menuIndex--
188
- this.refreshContent()
189
- } else if (key.name === "down" && this.menuIndex < menuItems.length - 1) {
190
- this.menuIndex++
191
- this.refreshContent()
192
- } else if (key.name === "return") {
193
- this.executeMenuItem(this.menuIndex)
194
- }
195
- }
196
-
197
- protected executeMenuItem(index: number): void {
198
- const items = this.getMenuItems()
199
- if (index >= 0 && index < items.length) {
200
- items[index].action()
201
- }
202
- }
203
-
204
- protected refreshContent(): void {
205
- this.contentBox.getChildren().forEach((child) => child.destroy())
206
-
207
- // Allow subclass custom rendering
208
- if (this.renderCustomContent()) {
209
- return
210
- }
211
-
212
- // Default rendering
213
- if (this.currentStep === "menu") {
214
- this.renderMenu()
215
- } else {
216
- this.renderResults()
217
- }
218
- }
219
-
220
- protected renderMenu(): void {
221
- this.contentBox.add(
222
- new TextRenderable(this.cliRenderer, {
223
- content: this.getMenuDescription() + "\n\n",
224
- fg: "#aaaaaa",
225
- })
226
- )
227
-
228
- this.getMenuItems().forEach((item, idx) => {
229
- const pointer = idx === this.menuIndex ? "→ " : " "
230
- const fg = idx === this.menuIndex ? "#50fa7b" : "#8be9fd"
231
-
232
- this.contentBox.add(
233
- new TextRenderable(this.cliRenderer, {
234
- content: `${pointer}${item.name}\n`,
235
- fg,
236
- })
237
- )
238
- this.contentBox.add(
239
- new TextRenderable(this.cliRenderer, {
240
- content: ` ${item.description}\n\n`,
241
- fg: "#6272a4",
242
- })
243
- )
244
- })
245
- }
246
-
247
- /**
248
- * Description shown above menu. Override to customize.
249
- */
250
- protected getMenuDescription(): string {
251
- return "Select an option:"
252
- }
253
-
254
- protected renderResults(): void {
255
- const headerText = this.currentStep === "done" ? "Results:\n\n" : "Configuring...\n\n"
256
- this.contentBox.add(
257
- new TextRenderable(this.cliRenderer, {
258
- content: headerText,
259
- fg: this.currentStep === "done" ? "#50fa7b" : "#f1fa8c",
260
- })
261
- )
262
-
263
- for (const result of this.results) {
264
- let status = ""
265
- let fg = "#aaaaaa"
266
- switch (result.status) {
267
- case "pending":
268
- status = "⏳"
269
- break
270
- case "configuring":
271
- status = "🔄"
272
- fg = "#f1fa8c"
273
- break
274
- case "success":
275
- status = "✓"
276
- fg = "#50fa7b"
277
- break
278
- case "error":
279
- status = "✗"
280
- fg = "#ff5555"
281
- break
282
- case "skipped":
283
- status = "⊘"
284
- fg = "#6272a4"
285
- break
286
- }
287
-
288
- let content = `${status} ${result.name}`
289
- if (result.message) {
290
- content += ` - ${result.message}`
291
- }
292
-
293
- this.contentBox.add(new TextRenderable(this.cliRenderer, { content: content + "\n", fg }))
294
- }
295
-
296
- if (this.currentStep === "done") {
297
- this.contentBox.add(
298
- new TextRenderable(this.cliRenderer, {
299
- content: "\nPress Enter or Esc to continue...",
300
- fg: "#6272a4",
301
- })
302
- )
303
- }
304
- }
305
-
306
- /**
307
- * Helper to run an action and display result
308
- */
309
- protected async runAction(
310
- name: string,
311
- action: () => Promise<{ success: boolean; message?: string }>
312
- ): Promise<void> {
313
- this.currentStep = "running"
314
- this.results = [{ name, status: "configuring" }]
315
- this.refreshContent()
316
-
317
- try {
318
- const result = await action()
319
- this.results[0] = {
320
- name,
321
- status: result.success ? "success" : "error",
322
- message: result.message,
323
- }
324
- } catch (error) {
325
- this.results[0] = {
326
- name,
327
- status: "error",
328
- message: error instanceof Error ? error.message : String(error),
329
- }
330
- }
331
-
332
- this.currentStep = "done"
333
- this.refreshContent()
334
- }
335
-
336
- /**
337
- * Helper to run multiple actions in sequence
338
- */
339
- protected async runActions(
340
- actions: Array<{ name: string; action: () => Promise<{ success: boolean; message?: string }> }>
341
- ): Promise<void> {
342
- this.currentStep = "running"
343
- this.results = actions.map((a) => ({ name: a.name, status: "pending" as const }))
344
- this.refreshContent()
345
-
346
- for (let i = 0; i < actions.length; i++) {
347
- this.results[i].status = "configuring"
348
- this.refreshContent()
349
-
350
- try {
351
- const result = await actions[i].action()
352
- this.results[i] = {
353
- name: actions[i].name,
354
- status: result.success ? "success" : "error",
355
- message: result.message,
356
- }
357
- } catch (error) {
358
- this.results[i] = {
359
- name: actions[i].name,
360
- status: "error",
361
- message: error instanceof Error ? error.message : String(error),
362
- }
363
- }
364
- }
365
-
366
- this.currentStep = "done"
367
- this.refreshContent()
368
- }
369
-
370
- protected cleanup(): void {
371
- this.cliRenderer.keyInput.off("keypress", this.keyHandler)
372
- this.destroy()
373
- this.onBack()
374
- }
375
- }