unified-tvdevelopment-cli 1.0.1-beta.0 → 1.0.2
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 +255 -1
- package/dist/cli.mjs +41211 -750
- package/install.ps1 +247 -42
- package/install.sh +189 -68
- package/package.json +3 -3
package/install.ps1
CHANGED
|
@@ -1,81 +1,286 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Run:
|
|
1
|
+
# tvdev-cli — Windows installer
|
|
2
|
+
# Run:
|
|
3
|
+
# iwr -useb https://raw.githubusercontent.com/tvdev-cli/tvdev-cli/main/install.ps1 | iex
|
|
4
|
+
# iwr -useb https://raw.githubusercontent.com/tvdev-cli/tvdev-cli/main/install.ps1 | iex -Beta
|
|
5
|
+
#
|
|
6
|
+
param(
|
|
7
|
+
[switch]$Beta
|
|
8
|
+
)
|
|
3
9
|
|
|
4
10
|
$ErrorActionPreference = 'Stop'
|
|
5
|
-
$Package = "unified-tvdevelopment-cli"
|
|
6
|
-
$Bin = "tvdev"
|
|
7
11
|
|
|
12
|
+
$Repo = "tvdev-cli/tvdev-cli"
|
|
13
|
+
$Bin = "tvdev"
|
|
14
|
+
$Channel = if ($Beta) { "beta" } else { "stable" }
|
|
15
|
+
$RequiredNodeMajor = 18
|
|
16
|
+
$InstallDir = Join-Path $env:LOCALAPPDATA "tvdev\bin"
|
|
17
|
+
$BinPath = Join-Path $InstallDir "$Bin"
|
|
18
|
+
$VersionFile = Join-Path $InstallDir ".tvdev-version"
|
|
19
|
+
|
|
20
|
+
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
8
21
|
function Write-Banner {
|
|
9
22
|
Write-Host ""
|
|
10
|
-
Write-Host " [TV Dev Manager]" -ForegroundColor Cyan
|
|
23
|
+
Write-Host " [TV Dev Manager]" -ForegroundColor Cyan -NoNewline
|
|
24
|
+
if ($Channel -eq "beta") { Write-Host " channel: beta" -ForegroundColor Yellow } else { Write-Host "" }
|
|
11
25
|
Write-Host " Universal Smart TV Development CLI" -ForegroundColor DarkGray
|
|
12
26
|
Write-Host " LG webOS · Samsung Tizen · Amazon Fire TV · Android TV" -ForegroundColor DarkGray
|
|
13
27
|
Write-Host ""
|
|
14
28
|
}
|
|
15
29
|
|
|
16
|
-
function Write-Step
|
|
17
|
-
function Write-Ok
|
|
18
|
-
function Write-
|
|
19
|
-
function Write-
|
|
30
|
+
function Write-Step { param($msg) Write-Host "`n > $msg" -ForegroundColor Cyan }
|
|
31
|
+
function Write-Ok { param($msg) Write-Host " [OK] $msg" -ForegroundColor Green }
|
|
32
|
+
function Write-Info { param($msg) Write-Host " [..] $msg" -ForegroundColor Blue }
|
|
33
|
+
function Write-Warn { param($msg) Write-Host " [!!] $msg" -ForegroundColor Yellow }
|
|
34
|
+
function Write-Fail { param($msg) Write-Host "`n [XX] $msg`n" -ForegroundColor Red; exit 1 }
|
|
35
|
+
|
|
36
|
+
function Invoke-GhApi {
|
|
37
|
+
param([string]$Url)
|
|
38
|
+
$headers = @{
|
|
39
|
+
'Accept' = 'application/vnd.github+json'
|
|
40
|
+
'X-GitHub-Api-Version' = '2022-11-28'
|
|
41
|
+
'User-Agent' = 'tvdev-cli-installer'
|
|
42
|
+
}
|
|
43
|
+
Invoke-RestMethod -Uri $Url -Headers $headers
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function Compare-Semver {
|
|
47
|
+
param([string]$A, [string]$B)
|
|
48
|
+
# returns $true if A >= B (strip pre-release suffix)
|
|
49
|
+
$av = [Version](($A -split '-')[0] -replace '^v','')
|
|
50
|
+
$bv = [Version](($B -split '-')[0] -replace '^v','')
|
|
51
|
+
return $av -ge $bv
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function Add-ToUserPath {
|
|
55
|
+
param([string]$Dir)
|
|
56
|
+
$current = [Environment]::GetEnvironmentVariable("PATH", "User")
|
|
57
|
+
if ($current -split ';' -contains $Dir) { return $false }
|
|
58
|
+
[Environment]::SetEnvironmentVariable("PATH", "$current;$Dir", "User")
|
|
59
|
+
$env:PATH = "$env:PATH;$Dir"
|
|
60
|
+
return $true
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function Test-Command {
|
|
64
|
+
param([string]$Name)
|
|
65
|
+
return [bool](Get-Command $Name -ErrorAction SilentlyContinue)
|
|
66
|
+
}
|
|
20
67
|
|
|
21
68
|
Write-Banner
|
|
22
69
|
|
|
23
|
-
#
|
|
24
|
-
Write-Step "
|
|
70
|
+
# ── Resolve latest release from GitHub ───────────────────────────────────────
|
|
71
|
+
Write-Step "Resolving latest $Channel release from GitHub"
|
|
72
|
+
|
|
25
73
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
74
|
+
if ($Channel -eq "beta") {
|
|
75
|
+
$releases = Invoke-GhApi "https://api.github.com/repos/$Repo/releases"
|
|
76
|
+
$release = $releases | Where-Object { $_.prerelease -eq $true } | Select-Object -First 1
|
|
77
|
+
} else {
|
|
78
|
+
$release = Invoke-GhApi "https://api.github.com/repos/$Repo/releases/latest"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (-not $release -or -not $release.tag_name) {
|
|
82
|
+
Write-Fail "Could not resolve release from GitHub. Visit https://github.com/$Repo/releases"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
$ReleaseTag = $release.tag_name
|
|
86
|
+
$ReleaseVersion = $ReleaseTag -replace '^v', ''
|
|
28
87
|
} catch {
|
|
29
|
-
Write-Fail "
|
|
88
|
+
Write-Fail "GitHub API request failed: $_"
|
|
30
89
|
}
|
|
31
90
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
91
|
+
Write-Info "Latest release : $ReleaseTag"
|
|
92
|
+
|
|
93
|
+
# ── Idempotency check ─────────────────────────────────────────────────────────
|
|
94
|
+
Write-Step "Checking existing installation"
|
|
95
|
+
|
|
96
|
+
$InstalledVer = ""
|
|
97
|
+
if (Test-Path $VersionFile) {
|
|
98
|
+
$InstalledVer = (Get-Content $VersionFile -Raw).Trim().TrimStart('v')
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if ($InstalledVer -and (Test-Path $BinPath)) {
|
|
102
|
+
Write-Ok "$Bin already installed"
|
|
103
|
+
Write-Info "Installed : v$InstalledVer"
|
|
104
|
+
Write-Info "Latest : v$ReleaseVersion ($Channel)"
|
|
105
|
+
|
|
106
|
+
if (Compare-Semver $InstalledVer $ReleaseVersion) {
|
|
107
|
+
Write-Ok "Already up to date — nothing to do"
|
|
108
|
+
Write-Host "`n Run: $Bin`n" -ForegroundColor Cyan
|
|
109
|
+
exit 0
|
|
110
|
+
}
|
|
111
|
+
Write-Info "Update available — reinstalling"
|
|
112
|
+
} else {
|
|
113
|
+
Write-Info "$Bin not yet installed — starting fresh install"
|
|
39
114
|
}
|
|
40
115
|
|
|
41
|
-
#
|
|
42
|
-
Write-Step "
|
|
43
|
-
|
|
44
|
-
|
|
116
|
+
# ── Node.js ───────────────────────────────────────────────────────────────────
|
|
117
|
+
Write-Step "Checking Node.js"
|
|
118
|
+
|
|
119
|
+
if (-not (Test-Command "node")) {
|
|
120
|
+
Write-Warn "Node.js not found — attempting install via winget"
|
|
121
|
+
try {
|
|
122
|
+
winget install --id OpenJS.NodeJS.LTS --accept-source-agreements --accept-package-agreements --silent
|
|
123
|
+
# reload PATH for current session
|
|
124
|
+
$env:PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" +
|
|
125
|
+
[Environment]::GetEnvironmentVariable("PATH", "User")
|
|
126
|
+
Write-Ok "Node.js installed via winget"
|
|
127
|
+
} catch {
|
|
128
|
+
Write-Host " Install Node.js manually from https://nodejs.org (LTS recommended)" -ForegroundColor DarkGray
|
|
129
|
+
Write-Host " Or via winget: winget install OpenJS.NodeJS.LTS" -ForegroundColor DarkGray
|
|
130
|
+
Write-Fail "Node.js $RequiredNodeMajor+ required."
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (-not (Test-Command "node")) {
|
|
135
|
+
Write-Fail "Node.js not found after install. Restart terminal and re-run this script."
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
$nodeVer = (node --version).TrimStart('v')
|
|
139
|
+
$nodeMajor = [int]($nodeVer -split '\.')[0]
|
|
140
|
+
|
|
141
|
+
if ($nodeMajor -lt $RequiredNodeMajor) {
|
|
142
|
+
Write-Fail "Node.js $RequiredNodeMajor+ required (got v$nodeVer). Upgrade: https://nodejs.org"
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
Write-Ok "Node.js v$nodeVer"
|
|
146
|
+
|
|
147
|
+
# ── Download binary from GitHub release ───────────────────────────────────────
|
|
148
|
+
Write-Step "Downloading $Bin $ReleaseTag"
|
|
45
149
|
|
|
46
|
-
|
|
47
|
-
|
|
150
|
+
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
|
|
151
|
+
|
|
152
|
+
# Find the cli.mjs asset in the release
|
|
153
|
+
$asset = $release.assets | Where-Object { $_.name -eq "cli.mjs" } | Select-Object -First 1
|
|
154
|
+
|
|
155
|
+
if ($asset) {
|
|
156
|
+
$DownloadUrl = $asset.browser_download_url
|
|
157
|
+
} else {
|
|
158
|
+
$DownloadUrl = "https://github.com/$Repo/releases/download/$ReleaseTag/cli.mjs"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
Write-Info "Source : $DownloadUrl"
|
|
162
|
+
|
|
163
|
+
$downloaded = $false
|
|
48
164
|
try {
|
|
49
|
-
$
|
|
50
|
-
|
|
165
|
+
Invoke-WebRequest -Uri $DownloadUrl -OutFile $BinPath -UseBasicParsing
|
|
166
|
+
$downloaded = $true
|
|
167
|
+
Write-Ok "Binary downloaded to $BinPath"
|
|
51
168
|
} catch {
|
|
52
|
-
Write-Warn "
|
|
169
|
+
Write-Warn "GitHub download failed — falling back to npm"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (-not $downloaded) {
|
|
173
|
+
if (-not (Test-Command "npm")) {
|
|
174
|
+
Write-Fail "npm not found and GitHub download failed. Install Node.js from https://nodejs.org"
|
|
175
|
+
}
|
|
176
|
+
$NpmTag = if ($Channel -eq "beta") { "beta" } else { "latest" }
|
|
177
|
+
Write-Info "Running: npm install -g unified-tvdevelopment-cli@$NpmTag"
|
|
178
|
+
npm install -g "unified-tvdevelopment-cli@$NpmTag" 2>&1 | Where-Object { $_ -notmatch "^npm warn" -and $_.Trim() -ne "" }
|
|
179
|
+
# use npm global bin path
|
|
180
|
+
$BinPath = Join-Path (npm prefix -g) "bin\$Bin"
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# Create a wrapper .cmd so Windows can execute the .mjs without typing 'node'
|
|
184
|
+
$WrapperPath = Join-Path $InstallDir "$Bin.cmd"
|
|
185
|
+
$WrapperContent = "@echo off`r`nnode `"%~dp0$Bin`" %*"
|
|
186
|
+
Set-Content -Path $WrapperPath -Value $WrapperContent -Encoding ASCII
|
|
187
|
+
|
|
188
|
+
# Save installed version
|
|
189
|
+
Set-Content -Path $VersionFile -Value $ReleaseVersion -Encoding UTF8
|
|
190
|
+
Write-Ok "Installed to $InstallDir"
|
|
191
|
+
|
|
192
|
+
# ── PATH ──────────────────────────────────────────────────────────────────────
|
|
193
|
+
Write-Step "Setting up PATH"
|
|
194
|
+
|
|
195
|
+
if (Add-ToUserPath $InstallDir) {
|
|
196
|
+
Write-Ok "Added $InstallDir to user PATH"
|
|
197
|
+
Write-Warn "Restart your terminal for PATH to take effect in new sessions"
|
|
198
|
+
} else {
|
|
199
|
+
Write-Ok "PATH already contains $InstallDir"
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (Test-Command $Bin) {
|
|
203
|
+
Write-Ok "$Bin is available in PATH"
|
|
204
|
+
} else {
|
|
205
|
+
Write-Warn "$Bin not in PATH for this session — restart terminal to use it"
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
# ── Platform tools ────────────────────────────────────────────────────────────
|
|
209
|
+
Write-Step "Checking and installing platform-specific tools"
|
|
210
|
+
|
|
211
|
+
function Install-NpmPackage {
|
|
212
|
+
param([string]$Package, [string]$Label)
|
|
213
|
+
Write-Info "Installing $Label via npm..."
|
|
214
|
+
try {
|
|
215
|
+
npm install -g $Package 2>&1 | Where-Object { $_ -notmatch "^npm warn" -and $_.Trim() -ne "" }
|
|
216
|
+
Write-Ok "$Label installed"
|
|
217
|
+
} catch {
|
|
218
|
+
Write-Warn "$Label install failed — run manually: npm install -g $Package"
|
|
219
|
+
}
|
|
53
220
|
}
|
|
54
221
|
|
|
55
|
-
|
|
56
|
-
Write-
|
|
222
|
+
function Install-AdbViaWinget {
|
|
223
|
+
Write-Info "Installing adb via winget (Android Platform Tools)..."
|
|
224
|
+
try {
|
|
225
|
+
winget install --id Google.PlatformTools --accept-source-agreements --accept-package-agreements --silent
|
|
226
|
+
$env:PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" +
|
|
227
|
+
[Environment]::GetEnvironmentVariable("PATH", "User")
|
|
228
|
+
Write-Ok "adb (Fire TV/Android TV) installed"
|
|
229
|
+
} catch {
|
|
230
|
+
Write-Warn "winget adb install failed — install Android SDK Platform Tools: https://developer.android.com/studio/releases/platform-tools"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
57
233
|
|
|
58
|
-
|
|
59
|
-
|
|
234
|
+
# ares-cli (LG webOS) — auto-install via npm
|
|
235
|
+
if (Test-Command "ares-setup-device") {
|
|
236
|
+
Write-Ok "ares-cli (LG webOS) — found"
|
|
60
237
|
} else {
|
|
61
|
-
Write-Warn "ares-cli not found
|
|
238
|
+
Write-Warn "ares-cli (LG webOS) not found — installing..."
|
|
239
|
+
Install-NpmPackage "@webosose/ares-cli" "ares-cli"
|
|
62
240
|
}
|
|
63
241
|
|
|
64
|
-
|
|
65
|
-
|
|
242
|
+
# sdb (Samsung Tizen) — requires Tizen Studio GUI installer, warn only
|
|
243
|
+
if (Test-Command "sdb") {
|
|
244
|
+
Write-Ok "sdb (Samsung Tizen) — found"
|
|
66
245
|
} else {
|
|
67
|
-
Write-Warn "sdb not found
|
|
246
|
+
Write-Warn "sdb (Samsung Tizen) not found — requires Tizen Studio: https://developer.samsung.com/smarttv"
|
|
68
247
|
}
|
|
69
248
|
|
|
70
|
-
|
|
71
|
-
|
|
249
|
+
# adb (Fire TV / Android TV) — auto-install via winget
|
|
250
|
+
if (Test-Command "adb") {
|
|
251
|
+
Write-Ok "adb (Fire TV/Android TV) — found"
|
|
72
252
|
} else {
|
|
73
|
-
Write-Warn "adb
|
|
253
|
+
Write-Warn "adb (Fire TV/Android TV) not found — installing..."
|
|
254
|
+
Install-AdbViaWinget
|
|
74
255
|
}
|
|
75
256
|
|
|
257
|
+
# inputd-cli (optional Fire TV input simulation) — auto-install via npm
|
|
258
|
+
if (Test-Command "inputd-cli") {
|
|
259
|
+
Write-Ok "inputd-cli (Fire TV input) — found"
|
|
260
|
+
} else {
|
|
261
|
+
Write-Warn "inputd-cli (Fire TV input) not found — installing..."
|
|
262
|
+
Install-NpmPackage "inputd-cli" "inputd-cli"
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
# ── Done ──────────────────────────────────────────────────────────────────────
|
|
76
266
|
Write-Host ""
|
|
77
|
-
Write-Host " Installation complete!" -ForegroundColor Green
|
|
267
|
+
Write-Host " Installation complete! ($ReleaseTag)" -ForegroundColor Green
|
|
78
268
|
Write-Host ""
|
|
79
269
|
Write-Host " Launch TV Dev Manager: " -NoNewline
|
|
80
270
|
Write-Host $Bin -ForegroundColor Cyan
|
|
81
271
|
Write-Host ""
|
|
272
|
+
Write-Host " GitHub : https://github.com/tvdev-cli/tvdev-cli" -ForegroundColor DarkGray
|
|
273
|
+
Write-Host " npm : https://npmjs.com/package/unified-tvdevelopment-cli" -ForegroundColor DarkGray
|
|
274
|
+
Write-Host ""
|
|
275
|
+
|
|
276
|
+
$currentPath = [Environment]::GetEnvironmentVariable("PATH", "User")
|
|
277
|
+
if (-not ($currentPath -split ';' -contains $InstallDir)) {
|
|
278
|
+
Write-Host " Tip: to make " -NoNewline -ForegroundColor Yellow
|
|
279
|
+
Write-Host "$Bin" -NoNewline -ForegroundColor Cyan
|
|
280
|
+
Write-Host " available in every new terminal, add this to your user PATH:" -ForegroundColor Yellow
|
|
281
|
+
Write-Host ""
|
|
282
|
+
Write-Host " [Environment]::SetEnvironmentVariable('PATH', `$env:PATH + ';$InstallDir', 'User')" -ForegroundColor DarkGray
|
|
283
|
+
Write-Host ""
|
|
284
|
+
Write-Host " Or restart your terminal — the installer already added it." -ForegroundColor DarkGray
|
|
285
|
+
Write-Host ""
|
|
286
|
+
}
|