@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.
- package/dist/index.js +29837 -0
- package/package.json +15 -15
- package/src/VersionInfo.ts +0 -12
- package/src/api/arr-api.ts +0 -521
- package/src/api/auto-setup-types.ts +0 -64
- package/src/api/base-api.ts +0 -216
- package/src/api/bazarr-api.ts +0 -297
- package/src/api/cloudflare-api.ts +0 -493
- package/src/api/custom-format-api.ts +0 -224
- package/src/api/grafana-api.ts +0 -230
- package/src/api/heimdall-api.ts +0 -141
- package/src/api/homarr-api.ts +0 -209
- package/src/api/huntarr-api.ts +0 -457
- package/src/api/index.ts +0 -9
- package/src/api/jellyfin-api.ts +0 -389
- package/src/api/jellyseerr-api.ts +0 -559
- package/src/api/maintainerr-api.ts +0 -461
- package/src/api/naming-config.ts +0 -101
- package/src/api/overseerr-api.ts +0 -392
- package/src/api/plex-api.ts +0 -308
- package/src/api/portainer-api.ts +0 -374
- package/src/api/profilarr-api.ts +0 -391
- package/src/api/prowlarr-api.ts +0 -488
- package/src/api/qbittorrent-api.ts +0 -300
- package/src/api/quality-profile-api.ts +0 -272
- package/src/api/tautulli-api.ts +0 -244
- package/src/api/uptime-kuma-api.ts +0 -343
- package/src/apps/categories.ts +0 -14
- package/src/apps/index.ts +0 -2
- package/src/apps/registry.ts +0 -1275
- package/src/compose/caddy-config.ts +0 -130
- package/src/compose/generator.ts +0 -287
- package/src/compose/index.ts +0 -7
- package/src/compose/templates.ts +0 -78
- package/src/compose/traefik-config.ts +0 -187
- package/src/config/bookmarks-generator.ts +0 -160
- package/src/config/defaults.ts +0 -37
- package/src/config/homepage-config.ts +0 -381
- package/src/config/index.ts +0 -6
- package/src/config/manager.ts +0 -150
- package/src/config/recyclarr-config.ts +0 -181
- package/src/config/schema.ts +0 -310
- package/src/config/slskd-config.ts +0 -86
- package/src/config/soularr-config.ts +0 -105
- package/src/config/trash-quality-definitions.ts +0 -213
- package/src/data/lidarr-custom-formats.ts +0 -127
- package/src/data/trash-profiles.ts +0 -333
- package/src/docker/client.ts +0 -312
- package/src/docker/index.ts +0 -18
- package/src/index.ts +0 -77
- package/src/setup/actions/arr-common.ts +0 -307
- package/src/setup/actions/dashboards.ts +0 -79
- package/src/setup/actions/download-clients.ts +0 -54
- package/src/setup/actions/jellyseerr.ts +0 -331
- package/src/setup/actions/media-servers.ts +0 -68
- package/src/setup/actions/monitoring.ts +0 -120
- package/src/setup/actions/prowlarr.ts +0 -137
- package/src/setup/actions/utilities.ts +0 -490
- package/src/setup/index.ts +0 -78
- package/src/setup/types.ts +0 -144
- package/src/structure/manager.ts +0 -129
- package/src/ui/App.ts +0 -111
- package/src/ui/components/ApplicationSelector.ts +0 -275
- package/src/ui/components/CredentialsForm.ts +0 -180
- package/src/ui/components/DownloadClientForm.ts +0 -114
- package/src/ui/components/FileEditor.ts +0 -91
- package/src/ui/components/FooterHint.ts +0 -119
- package/src/ui/components/PageLayout.ts +0 -160
- package/src/ui/components/UpdateNotification.ts +0 -102
- package/src/ui/index.ts +0 -7
- package/src/ui/screens/AdvancedSettings.ts +0 -188
- package/src/ui/screens/ApiKeyViewer.ts +0 -511
- package/src/ui/screens/AppConfigurator.ts +0 -543
- package/src/ui/screens/AppManager.ts +0 -284
- package/src/ui/screens/ContainerControl.ts +0 -581
- package/src/ui/screens/LogsViewer.ts +0 -478
- package/src/ui/screens/MainMenu.ts +0 -299
- package/src/ui/screens/MonitorDashboard.ts +0 -881
- package/src/ui/screens/SecretsEditor.ts +0 -216
- package/src/ui/screens/SettingsScreen.ts +0 -633
- package/src/ui/screens/index.ts +0 -22
- package/src/ui/screens/setup/BaseAppSetupScreen.ts +0 -375
- package/src/ui/screens/setup/CloudflaredSetup.ts +0 -460
- package/src/ui/screens/setup/FullAutoSetup.ts +0 -766
- package/src/ui/screens/setup/HomepageSetup.ts +0 -165
- package/src/ui/screens/setup/JellyfinSetup.ts +0 -328
- package/src/ui/screens/setup/JellyseerrSetup.ts +0 -242
- package/src/ui/screens/setup/ProwlarrSetup.ts +0 -500
- package/src/ui/screens/setup/QBittorrentSetup.ts +0 -221
- package/src/ui/screens/setup/QuickSetup.ts +0 -1169
- package/src/ui/screens/setup/RecyclarrSetup.ts +0 -270
- package/src/ui/screens/setup/TRaSHProfileSetup.ts +0 -381
- package/src/utils/arch.ts +0 -78
- package/src/utils/browser.ts +0 -27
- package/src/utils/categories.ts +0 -61
- package/src/utils/debug.ts +0 -84
- package/src/utils/env.ts +0 -138
- package/src/utils/index.ts +0 -8
- package/src/utils/logs.ts +0 -119
- package/src/utils/migrations/1765626338_rename_env_variables.ts +0 -102
- package/src/utils/migrations/1765707135_rename_easiarr_status.ts +0 -91
- package/src/utils/migrations/1765732722_remove_cloudflare_dns_api_token.ts +0 -45
- package/src/utils/migrations/1769515650_migrate_to_xdg.ts +0 -114
- package/src/utils/migrations.ts +0 -165
- package/src/utils/password.ts +0 -42
- package/src/utils/paths.ts +0 -33
- package/src/utils/unraid.ts +0 -103
- package/src/utils/update-checker.ts +0 -210
- package/src/utils/url-utils.ts +0 -38
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TRaSH Guide Quality Profile Presets
|
|
3
|
-
* Pre-configured quality profiles based on TRaSH Guides recommendations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface TRaSHProfilePreset {
|
|
7
|
-
id: string
|
|
8
|
-
name: string
|
|
9
|
-
description: string
|
|
10
|
-
app: "radarr" | "sonarr" | "lidarr" | "both"
|
|
11
|
-
cutoffQuality: string
|
|
12
|
-
allowedQualities: string[]
|
|
13
|
-
cfScores: Record<string, number>
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Quality names for different resolutions
|
|
17
|
-
export const RADARR_QUALITIES = {
|
|
18
|
-
// HD
|
|
19
|
-
"Bluray-1080p": "Bluray-1080p",
|
|
20
|
-
"WEB-1080p": "WEBDL-1080p",
|
|
21
|
-
"HDTV-1080p": "HDTV-1080p",
|
|
22
|
-
"Bluray-720p": "Bluray-720p",
|
|
23
|
-
"WEB-720p": "WEBDL-720p",
|
|
24
|
-
// UHD
|
|
25
|
-
"Bluray-2160p": "Bluray-2160p",
|
|
26
|
-
"WEB-2160p": "WEBDL-2160p",
|
|
27
|
-
// Remux
|
|
28
|
-
"Remux-1080p": "Remux-1080p",
|
|
29
|
-
"Remux-2160p": "Remux-2160p",
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const SONARR_QUALITIES = {
|
|
33
|
-
"WEB-1080p": "WEBDL-1080p",
|
|
34
|
-
"WEB-720p": "WEBDL-720p",
|
|
35
|
-
"WEB-2160p": "WEBDL-2160p",
|
|
36
|
-
"HDTV-1080p": "HDTV-1080p",
|
|
37
|
-
"HDTV-720p": "HDTV-720p",
|
|
38
|
-
"Bluray-1080p": "Bluray-1080p",
|
|
39
|
-
"Bluray-720p": "Bluray-720p",
|
|
40
|
-
"Bluray-2160p": "Bluray-2160p",
|
|
41
|
-
"Remux-1080p": "Remux-1080p",
|
|
42
|
-
"Remux-2160p": "Remux-2160p",
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// TRaSH recommended Custom Format scores
|
|
46
|
-
export const CF_SCORES = {
|
|
47
|
-
// Unwanted (use negative scores)
|
|
48
|
-
"BR-DISK": -10000,
|
|
49
|
-
LQ: -10000,
|
|
50
|
-
"LQ (Release Title)": -10000,
|
|
51
|
-
"3D": -10000,
|
|
52
|
-
x265: -10000, // Only for HD, not UHD
|
|
53
|
-
Extras: -10000,
|
|
54
|
-
|
|
55
|
-
// Preferred (positive scores)
|
|
56
|
-
"Repack/Proper": 5,
|
|
57
|
-
Repack2: 6,
|
|
58
|
-
|
|
59
|
-
// HDR Formats
|
|
60
|
-
"DV HDR10Plus": 1600,
|
|
61
|
-
"DV HDR10": 1500,
|
|
62
|
-
DV: 1400,
|
|
63
|
-
"DV HLG": 1300,
|
|
64
|
-
"DV SDR": 1200,
|
|
65
|
-
HDR10Plus: 700,
|
|
66
|
-
HDR10: 600,
|
|
67
|
-
HDR: 500,
|
|
68
|
-
"HDR (undefined)": 400,
|
|
69
|
-
PQ: 300,
|
|
70
|
-
HLG: 200,
|
|
71
|
-
|
|
72
|
-
// Audio Formats
|
|
73
|
-
"TrueHD Atmos": 5000,
|
|
74
|
-
"DTS X": 4500,
|
|
75
|
-
TrueHD: 4000,
|
|
76
|
-
"DTS-HD MA": 3500,
|
|
77
|
-
FLAC: 3000,
|
|
78
|
-
PCM: 2500,
|
|
79
|
-
"DTS-HD HRA": 2000,
|
|
80
|
-
"DD+ Atmos": 1500,
|
|
81
|
-
"DD+": 1000,
|
|
82
|
-
"DTS-ES": 800,
|
|
83
|
-
DTS: 600,
|
|
84
|
-
AAC: 400,
|
|
85
|
-
DD: 300,
|
|
86
|
-
|
|
87
|
-
// Streaming Services
|
|
88
|
-
AMZN: 0,
|
|
89
|
-
ATVP: 100,
|
|
90
|
-
DSNP: 100,
|
|
91
|
-
HBO: 0,
|
|
92
|
-
HMAX: 0,
|
|
93
|
-
Hulu: 0,
|
|
94
|
-
MA: 0,
|
|
95
|
-
NF: 0,
|
|
96
|
-
PCOK: 0,
|
|
97
|
-
PMTP: 0,
|
|
98
|
-
|
|
99
|
-
// Movie Versions
|
|
100
|
-
"IMAX Enhanced": 800,
|
|
101
|
-
IMAX: 700,
|
|
102
|
-
Hybrid: 100,
|
|
103
|
-
"Criterion Collection": 100,
|
|
104
|
-
"Special Edition": 50,
|
|
105
|
-
"Theatrical Cut": 0,
|
|
106
|
-
|
|
107
|
-
// HQ Release Groups
|
|
108
|
-
"HQ-Remux": 1750,
|
|
109
|
-
"HQ-WEBDL": 1700,
|
|
110
|
-
HQ: 1600,
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Radarr Profile Presets
|
|
114
|
-
export const RADARR_PRESETS: TRaSHProfilePreset[] = [
|
|
115
|
-
{
|
|
116
|
-
id: "hd-bluray-web",
|
|
117
|
-
name: "HD Bluray + WEB",
|
|
118
|
-
description: "High-Quality HD Encodes (Bluray-720p/1080p). Size: 6-15 GB",
|
|
119
|
-
app: "radarr",
|
|
120
|
-
cutoffQuality: "Bluray-1080p",
|
|
121
|
-
allowedQualities: [
|
|
122
|
-
"Bluray-1080p",
|
|
123
|
-
"Bluray-720p",
|
|
124
|
-
"WEBDL-1080p",
|
|
125
|
-
"WEBDL-720p",
|
|
126
|
-
"WEBRip-1080p",
|
|
127
|
-
"WEBRip-720p",
|
|
128
|
-
],
|
|
129
|
-
cfScores: {
|
|
130
|
-
"BR-DISK": -10000,
|
|
131
|
-
LQ: -10000,
|
|
132
|
-
"LQ (Release Title)": -10000,
|
|
133
|
-
"3D": -10000,
|
|
134
|
-
"x265 (HD)": -10000,
|
|
135
|
-
"Repack/Proper": 5,
|
|
136
|
-
"HQ-WEBDL": 1700,
|
|
137
|
-
HQ: 1600,
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
id: "uhd-bluray-web",
|
|
142
|
-
name: "UHD Bluray + WEB",
|
|
143
|
-
description: "High-Quality UHD Encodes (Bluray-2160p). Size: 20-60 GB",
|
|
144
|
-
app: "radarr",
|
|
145
|
-
cutoffQuality: "Bluray-2160p",
|
|
146
|
-
allowedQualities: ["Bluray-2160p", "WEBDL-2160p", "WEBRip-2160p"],
|
|
147
|
-
cfScores: {
|
|
148
|
-
"BR-DISK": -10000,
|
|
149
|
-
LQ: -10000,
|
|
150
|
-
"LQ (Release Title)": -10000,
|
|
151
|
-
"DV HDR10Plus": 1600,
|
|
152
|
-
"DV HDR10": 1500,
|
|
153
|
-
DV: 1400,
|
|
154
|
-
HDR10Plus: 700,
|
|
155
|
-
HDR10: 600,
|
|
156
|
-
"Repack/Proper": 5,
|
|
157
|
-
"TrueHD Atmos": 5000,
|
|
158
|
-
"DTS X": 4500,
|
|
159
|
-
"HQ-WEBDL": 1700,
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
id: "remux-web-1080p",
|
|
164
|
-
name: "Remux + WEB 1080p",
|
|
165
|
-
description: "1080p Remuxes. Size: 20-40 GB",
|
|
166
|
-
app: "radarr",
|
|
167
|
-
cutoffQuality: "Remux-1080p",
|
|
168
|
-
allowedQualities: ["Remux-1080p", "WEBDL-1080p", "WEBRip-1080p"],
|
|
169
|
-
cfScores: {
|
|
170
|
-
"BR-DISK": -10000,
|
|
171
|
-
LQ: -10000,
|
|
172
|
-
"x265 (HD)": -10000,
|
|
173
|
-
"HQ-Remux": 1750,
|
|
174
|
-
"Repack/Proper": 5,
|
|
175
|
-
"TrueHD Atmos": 5000,
|
|
176
|
-
"DTS X": 4500,
|
|
177
|
-
TrueHD: 4000,
|
|
178
|
-
"DTS-HD MA": 3500,
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
id: "remux-web-2160p",
|
|
183
|
-
name: "Remux + WEB 2160p",
|
|
184
|
-
description: "2160p Remuxes. Size: 40-100 GB",
|
|
185
|
-
app: "radarr",
|
|
186
|
-
cutoffQuality: "Remux-2160p",
|
|
187
|
-
allowedQualities: ["Remux-2160p", "WEBDL-2160p", "WEBRip-2160p"],
|
|
188
|
-
cfScores: {
|
|
189
|
-
"BR-DISK": -10000,
|
|
190
|
-
LQ: -10000,
|
|
191
|
-
"DV HDR10Plus": 1600,
|
|
192
|
-
"DV HDR10": 1500,
|
|
193
|
-
DV: 1400,
|
|
194
|
-
HDR10Plus: 700,
|
|
195
|
-
HDR10: 600,
|
|
196
|
-
"HQ-Remux": 1750,
|
|
197
|
-
"Repack/Proper": 5,
|
|
198
|
-
"TrueHD Atmos": 5000,
|
|
199
|
-
"DTS X": 4500,
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
]
|
|
203
|
-
|
|
204
|
-
// Sonarr Profile Presets
|
|
205
|
-
export const SONARR_PRESETS: TRaSHProfilePreset[] = [
|
|
206
|
-
{
|
|
207
|
-
id: "web-1080p",
|
|
208
|
-
name: "WEB-1080p",
|
|
209
|
-
description: "720p/1080p WEBDL. Balanced quality and size",
|
|
210
|
-
app: "sonarr",
|
|
211
|
-
cutoffQuality: "WEBDL-1080p",
|
|
212
|
-
allowedQualities: ["WEBDL-1080p", "WEBRip-1080p", "WEBDL-720p", "WEBRip-720p"],
|
|
213
|
-
cfScores: {
|
|
214
|
-
"BR-DISK": -10000,
|
|
215
|
-
LQ: -10000,
|
|
216
|
-
"x265 (HD)": -10000,
|
|
217
|
-
"Repack/Proper": 5,
|
|
218
|
-
"HQ-WEBDL": 1700,
|
|
219
|
-
AMZN: 100,
|
|
220
|
-
ATVP: 100,
|
|
221
|
-
DSNP: 100,
|
|
222
|
-
NF: 100,
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
{
|
|
226
|
-
id: "web-2160p",
|
|
227
|
-
name: "WEB-2160p",
|
|
228
|
-
description: "2160p WEBDL with HDR. Premium quality",
|
|
229
|
-
app: "sonarr",
|
|
230
|
-
cutoffQuality: "WEBDL-2160p",
|
|
231
|
-
allowedQualities: ["WEBDL-2160p", "WEBRip-2160p"],
|
|
232
|
-
cfScores: {
|
|
233
|
-
"BR-DISK": -10000,
|
|
234
|
-
LQ: -10000,
|
|
235
|
-
"DV HDR10Plus": 1600,
|
|
236
|
-
"DV HDR10": 1500,
|
|
237
|
-
DV: 1400,
|
|
238
|
-
HDR10Plus: 700,
|
|
239
|
-
HDR10: 600,
|
|
240
|
-
"Repack/Proper": 5,
|
|
241
|
-
"HQ-WEBDL": 1700,
|
|
242
|
-
AMZN: 100,
|
|
243
|
-
ATVP: 100,
|
|
244
|
-
NF: 100,
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
]
|
|
248
|
-
|
|
249
|
-
// Lidarr Quality Names (Davo's Community Guide)
|
|
250
|
-
export const LIDARR_QUALITIES = {
|
|
251
|
-
FLAC: "FLAC",
|
|
252
|
-
"FLAC 24bit": "FLAC 24bit",
|
|
253
|
-
"MP3-320": "MP3-320",
|
|
254
|
-
"MP3-256": "MP3-256",
|
|
255
|
-
"MP3-128": "MP3-128",
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Lidarr Custom Format Scores (Davo's Community Guide)
|
|
259
|
-
// Scoring requires minimum 1 to grab, prefers CD > WEB, avoids Vinyl
|
|
260
|
-
export const LIDARR_CF_SCORES = {
|
|
261
|
-
// Preferred Release Groups
|
|
262
|
-
"Preferred Groups": 5,
|
|
263
|
-
|
|
264
|
-
// Source Preferences
|
|
265
|
-
CD: 3, // Prefer CD source
|
|
266
|
-
WEB: 2, // Accept WEB source
|
|
267
|
-
Lossless: 1, // Tag for lossless
|
|
268
|
-
|
|
269
|
-
// Avoid Vinyl (analog noise, pops, clicks)
|
|
270
|
-
Vinyl: -10000,
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Lidarr Profile Presets (Davo's Community Guide)
|
|
274
|
-
export const LIDARR_PRESETS: TRaSHProfilePreset[] = [
|
|
275
|
-
{
|
|
276
|
-
id: "high-quality-flac",
|
|
277
|
-
name: "High Quality FLAC",
|
|
278
|
-
description: "FLAC quality with MP3-320 fallback. Prefers CD source, avoids Vinyl.",
|
|
279
|
-
app: "lidarr",
|
|
280
|
-
cutoffQuality: "FLAC",
|
|
281
|
-
allowedQualities: ["FLAC", "FLAC 24bit", "MP3-320"],
|
|
282
|
-
cfScores: {
|
|
283
|
-
"Preferred Groups": 5,
|
|
284
|
-
CD: 3,
|
|
285
|
-
WEB: 2,
|
|
286
|
-
Lossless: 1,
|
|
287
|
-
Vinyl: -10000,
|
|
288
|
-
},
|
|
289
|
-
},
|
|
290
|
-
{
|
|
291
|
-
id: "flac-only",
|
|
292
|
-
name: "FLAC Only",
|
|
293
|
-
description: "Lossless FLAC only, no MP3 fallback. Best quality.",
|
|
294
|
-
app: "lidarr",
|
|
295
|
-
cutoffQuality: "FLAC",
|
|
296
|
-
allowedQualities: ["FLAC", "FLAC 24bit"],
|
|
297
|
-
cfScores: {
|
|
298
|
-
"Preferred Groups": 5,
|
|
299
|
-
CD: 3,
|
|
300
|
-
WEB: 2,
|
|
301
|
-
Lossless: 1,
|
|
302
|
-
Vinyl: -10000,
|
|
303
|
-
},
|
|
304
|
-
},
|
|
305
|
-
{
|
|
306
|
-
id: "any-quality",
|
|
307
|
-
name: "Any Quality",
|
|
308
|
-
description: "Accept any quality including MP3. For maximum availability.",
|
|
309
|
-
app: "lidarr",
|
|
310
|
-
cutoffQuality: "MP3-320",
|
|
311
|
-
allowedQualities: ["FLAC", "FLAC 24bit", "MP3-320", "MP3-256", "MP3-128"],
|
|
312
|
-
cfScores: {
|
|
313
|
-
"Preferred Groups": 5,
|
|
314
|
-
CD: 3,
|
|
315
|
-
WEB: 2,
|
|
316
|
-
Lossless: 1,
|
|
317
|
-
Vinyl: -10000,
|
|
318
|
-
},
|
|
319
|
-
},
|
|
320
|
-
]
|
|
321
|
-
|
|
322
|
-
// Get all presets for an app
|
|
323
|
-
export function getPresetsForApp(app: "radarr" | "sonarr" | "lidarr"): TRaSHProfilePreset[] {
|
|
324
|
-
if (app === "radarr") return RADARR_PRESETS
|
|
325
|
-
if (app === "sonarr") return SONARR_PRESETS
|
|
326
|
-
if (app === "lidarr") return LIDARR_PRESETS
|
|
327
|
-
return []
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Get a specific preset by ID
|
|
331
|
-
export function getPresetById(id: string): TRaSHProfilePreset | undefined {
|
|
332
|
-
return [...RADARR_PRESETS, ...SONARR_PRESETS, ...LIDARR_PRESETS].find((p) => p.id === id)
|
|
333
|
-
}
|
package/src/docker/client.ts
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Docker Client
|
|
3
|
-
* Wrapper for docker compose commands using Bun.$
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { $ } from "bun"
|
|
7
|
-
|
|
8
|
-
import { getComposePath } from "~/config/manager"
|
|
9
|
-
import { debugLog } from "~/utils/debug"
|
|
10
|
-
|
|
11
|
-
export interface ContainerStatus {
|
|
12
|
-
name: string
|
|
13
|
-
status: "running" | "stopped" | "not_found"
|
|
14
|
-
ports?: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function composeUp(): Promise<{
|
|
18
|
-
success: boolean
|
|
19
|
-
output: string
|
|
20
|
-
}> {
|
|
21
|
-
try {
|
|
22
|
-
const composePath = getComposePath()
|
|
23
|
-
debugLog("Docker", `compose up -d (path: ${composePath})`)
|
|
24
|
-
const result = await $`docker compose -f ${composePath} up -d`.text()
|
|
25
|
-
debugLog("Docker", `compose up success`)
|
|
26
|
-
return { success: true, output: result }
|
|
27
|
-
} catch (error) {
|
|
28
|
-
debugLog("Docker", `compose up failed: ${error}`)
|
|
29
|
-
return { success: false, output: String(error) }
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function composeDown(): Promise<{
|
|
34
|
-
success: boolean
|
|
35
|
-
output: string
|
|
36
|
-
}> {
|
|
37
|
-
try {
|
|
38
|
-
const composePath = getComposePath()
|
|
39
|
-
debugLog("Docker", `compose down (path: ${composePath})`)
|
|
40
|
-
const result = await $`docker compose -f ${composePath} down`.text()
|
|
41
|
-
debugLog("Docker", `compose down success`)
|
|
42
|
-
return { success: true, output: result }
|
|
43
|
-
} catch (error) {
|
|
44
|
-
debugLog("Docker", `compose down failed: ${error}`)
|
|
45
|
-
return { success: false, output: String(error) }
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Run a one-off container with docker compose run --rm
|
|
51
|
-
*/
|
|
52
|
-
export async function composeRun(
|
|
53
|
-
service: string,
|
|
54
|
-
command: string
|
|
55
|
-
): Promise<{ success: boolean; output: string }> {
|
|
56
|
-
try {
|
|
57
|
-
const composePath = getComposePath()
|
|
58
|
-
debugLog("Docker", `compose run --rm ${service} ${command}`)
|
|
59
|
-
const result = await $`docker compose -f ${composePath} run --rm ${service} ${command}`.text()
|
|
60
|
-
debugLog("Docker", `compose run success`)
|
|
61
|
-
return { success: true, output: result }
|
|
62
|
-
} catch (error) {
|
|
63
|
-
debugLog("Docker", `compose run failed: ${error}`)
|
|
64
|
-
return { success: false, output: String(error) }
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function composeRestart(
|
|
69
|
-
service?: string
|
|
70
|
-
): Promise<{ success: boolean; output: string }> {
|
|
71
|
-
try {
|
|
72
|
-
const composePath = getComposePath()
|
|
73
|
-
debugLog("Docker", `compose restart ${service || "all"}`)
|
|
74
|
-
const result = service
|
|
75
|
-
? await $`docker compose -f ${composePath} restart ${service}`.text()
|
|
76
|
-
: await $`docker compose -f ${composePath} restart`.text()
|
|
77
|
-
debugLog("Docker", `compose restart success`)
|
|
78
|
-
return { success: true, output: result }
|
|
79
|
-
} catch (error) {
|
|
80
|
-
debugLog("Docker", `compose restart failed: ${error}`)
|
|
81
|
-
return { success: false, output: String(error) }
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export async function composeStop(service?: string): Promise<{ success: boolean; output: string }> {
|
|
86
|
-
try {
|
|
87
|
-
const composePath = getComposePath()
|
|
88
|
-
debugLog("Docker", `compose stop ${service || "all"}`)
|
|
89
|
-
const result = service
|
|
90
|
-
? await $`docker compose -f ${composePath} stop ${service}`.text()
|
|
91
|
-
: await $`docker compose -f ${composePath} stop`.text()
|
|
92
|
-
return { success: true, output: result }
|
|
93
|
-
} catch (error) {
|
|
94
|
-
return { success: false, output: String(error) }
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export async function composeStart(
|
|
99
|
-
service?: string
|
|
100
|
-
): Promise<{ success: boolean; output: string }> {
|
|
101
|
-
try {
|
|
102
|
-
const composePath = getComposePath()
|
|
103
|
-
const result = service
|
|
104
|
-
? await $`docker compose -f ${composePath} start ${service}`.text()
|
|
105
|
-
: await $`docker compose -f ${composePath} start`.text()
|
|
106
|
-
return { success: true, output: result }
|
|
107
|
-
} catch (error) {
|
|
108
|
-
return { success: false, output: String(error) }
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export async function getContainerStatuses(): Promise<ContainerStatus[]> {
|
|
113
|
-
try {
|
|
114
|
-
const composePath = getComposePath()
|
|
115
|
-
const result = await $`docker compose -f ${composePath} ps --format json`.text()
|
|
116
|
-
|
|
117
|
-
if (!result.trim()) {
|
|
118
|
-
return []
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Parse JSON lines output
|
|
122
|
-
const lines = result.trim().split("\n")
|
|
123
|
-
const statuses: ContainerStatus[] = []
|
|
124
|
-
|
|
125
|
-
for (const line of lines) {
|
|
126
|
-
try {
|
|
127
|
-
const container = JSON.parse(line)
|
|
128
|
-
statuses.push({
|
|
129
|
-
name: container.Name || container.Service,
|
|
130
|
-
status: container.State === "running" ? "running" : "stopped",
|
|
131
|
-
ports: container.Ports,
|
|
132
|
-
})
|
|
133
|
-
} catch {
|
|
134
|
-
// Skip malformed lines
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return statuses
|
|
139
|
-
} catch {
|
|
140
|
-
return []
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export async function pullImages(): Promise<{
|
|
145
|
-
success: boolean
|
|
146
|
-
output: string
|
|
147
|
-
}> {
|
|
148
|
-
try {
|
|
149
|
-
const composePath = getComposePath()
|
|
150
|
-
const result = await $`docker compose -f ${composePath} pull`.text()
|
|
151
|
-
return { success: true, output: result }
|
|
152
|
-
} catch (error) {
|
|
153
|
-
return { success: false, output: String(error) }
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export async function isDockerAvailable(): Promise<boolean> {
|
|
158
|
-
try {
|
|
159
|
-
await $`docker --version`.quiet()
|
|
160
|
-
return true
|
|
161
|
-
} catch {
|
|
162
|
-
return false
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// ==========================================
|
|
167
|
-
// Individual Container Operations
|
|
168
|
-
// ==========================================
|
|
169
|
-
|
|
170
|
-
export interface ContainerDetails {
|
|
171
|
-
id: string
|
|
172
|
-
name: string
|
|
173
|
-
service: string
|
|
174
|
-
status: "running" | "stopped" | "exited" | "paused"
|
|
175
|
-
state: string
|
|
176
|
-
health?: string
|
|
177
|
-
ports: string
|
|
178
|
-
uptime?: string
|
|
179
|
-
image: string
|
|
180
|
-
createdAt: string
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Start a specific container by service name
|
|
185
|
-
*/
|
|
186
|
-
export async function startContainer(
|
|
187
|
-
service: string
|
|
188
|
-
): Promise<{ success: boolean; output: string }> {
|
|
189
|
-
try {
|
|
190
|
-
const composePath = getComposePath()
|
|
191
|
-
const result = await $`docker compose -f ${composePath} start ${service}`.text()
|
|
192
|
-
return { success: true, output: result }
|
|
193
|
-
} catch (error) {
|
|
194
|
-
return { success: false, output: String(error) }
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Stop a specific container by service name
|
|
200
|
-
*/
|
|
201
|
-
export async function stopContainer(
|
|
202
|
-
service: string
|
|
203
|
-
): Promise<{ success: boolean; output: string }> {
|
|
204
|
-
try {
|
|
205
|
-
const composePath = getComposePath()
|
|
206
|
-
const result = await $`docker compose -f ${composePath} stop ${service}`.text()
|
|
207
|
-
return { success: true, output: result }
|
|
208
|
-
} catch (error) {
|
|
209
|
-
return { success: false, output: String(error) }
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Restart a specific container by service name
|
|
215
|
-
*/
|
|
216
|
-
export async function restartContainer(
|
|
217
|
-
service: string
|
|
218
|
-
): Promise<{ success: boolean; output: string }> {
|
|
219
|
-
try {
|
|
220
|
-
const composePath = getComposePath()
|
|
221
|
-
const result = await $`docker compose -f ${composePath} restart ${service}`.text()
|
|
222
|
-
return { success: true, output: result }
|
|
223
|
-
} catch (error) {
|
|
224
|
-
return { success: false, output: String(error) }
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Get detailed info for a specific container
|
|
230
|
-
*/
|
|
231
|
-
export async function getContainerDetails(containerName: string): Promise<ContainerDetails | null> {
|
|
232
|
-
try {
|
|
233
|
-
const result =
|
|
234
|
-
await $`docker inspect ${containerName} --format '{"id":"{{.Id}}","name":"{{.Name}}","state":"{{.State.Status}}","health":"{{if .State.Health}}{{.State.Health.Status}}{{end}}","image":"{{.Config.Image}}","createdAt":"{{.Created}}"}'`.text()
|
|
235
|
-
|
|
236
|
-
if (!result.trim()) return null
|
|
237
|
-
|
|
238
|
-
const data = JSON.parse(result.trim())
|
|
239
|
-
|
|
240
|
-
// Get uptime from Status
|
|
241
|
-
const statusResult =
|
|
242
|
-
await $`docker ps --filter "name=${containerName}" --format "{{.Status}}"`.text()
|
|
243
|
-
|
|
244
|
-
// Get port mappings
|
|
245
|
-
const portsResult = await $`docker port ${containerName} 2>/dev/null`.text()
|
|
246
|
-
|
|
247
|
-
return {
|
|
248
|
-
id: data.id.substring(0, 12),
|
|
249
|
-
name: data.name.replace(/^\//, ""),
|
|
250
|
-
service: containerName,
|
|
251
|
-
status: data.state === "running" ? "running" : data.state === "exited" ? "exited" : "stopped",
|
|
252
|
-
state: data.state,
|
|
253
|
-
health: data.health || undefined,
|
|
254
|
-
ports: portsResult.trim() || "-",
|
|
255
|
-
uptime: statusResult.trim() || undefined,
|
|
256
|
-
image: data.image,
|
|
257
|
-
createdAt: data.createdAt,
|
|
258
|
-
}
|
|
259
|
-
} catch {
|
|
260
|
-
return null
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Get container logs
|
|
266
|
-
*/
|
|
267
|
-
export async function getContainerLogs(
|
|
268
|
-
service: string,
|
|
269
|
-
lines: number = 50
|
|
270
|
-
): Promise<{ success: boolean; output: string }> {
|
|
271
|
-
try {
|
|
272
|
-
const composePath = getComposePath()
|
|
273
|
-
const result =
|
|
274
|
-
await $`docker compose -f ${composePath} logs ${service} --tail ${lines} --no-color`.text()
|
|
275
|
-
return { success: true, output: result }
|
|
276
|
-
} catch (error) {
|
|
277
|
-
return { success: false, output: String(error) }
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Pull latest image for a specific service
|
|
283
|
-
*/
|
|
284
|
-
export async function pullServiceImage(
|
|
285
|
-
service: string
|
|
286
|
-
): Promise<{ success: boolean; output: string }> {
|
|
287
|
-
try {
|
|
288
|
-
const composePath = getComposePath()
|
|
289
|
-
const result = await $`docker compose -f ${composePath} pull ${service}`.text()
|
|
290
|
-
return { success: true, output: result }
|
|
291
|
-
} catch (error) {
|
|
292
|
-
return { success: false, output: String(error) }
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Recreate a specific service (pull + up)
|
|
298
|
-
*/
|
|
299
|
-
export async function recreateService(
|
|
300
|
-
service: string
|
|
301
|
-
): Promise<{ success: boolean; output: string }> {
|
|
302
|
-
try {
|
|
303
|
-
const composePath = getComposePath()
|
|
304
|
-
// Pull first, then recreate
|
|
305
|
-
await $`docker compose -f ${composePath} pull ${service}`.text()
|
|
306
|
-
const result =
|
|
307
|
-
await $`docker compose -f ${composePath} up -d --force-recreate ${service}`.text()
|
|
308
|
-
return { success: true, output: result }
|
|
309
|
-
} catch (error) {
|
|
310
|
-
return { success: false, output: String(error) }
|
|
311
|
-
}
|
|
312
|
-
}
|
package/src/docker/index.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export {
|
|
2
|
-
getContainerStatuses,
|
|
3
|
-
getContainerLogs,
|
|
4
|
-
composeUp,
|
|
5
|
-
composeDown,
|
|
6
|
-
composeRun,
|
|
7
|
-
composeRestart,
|
|
8
|
-
composeStop,
|
|
9
|
-
composeStart,
|
|
10
|
-
pullImages,
|
|
11
|
-
pullServiceImage,
|
|
12
|
-
startContainer,
|
|
13
|
-
stopContainer,
|
|
14
|
-
restartContainer,
|
|
15
|
-
getContainerDetails,
|
|
16
|
-
recreateService,
|
|
17
|
-
type ContainerStatus,
|
|
18
|
-
} from "./client"
|