pinggy 0.6.0 → 0.6.3
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/ARCHITECTURE.md +335 -10
- package/CLAUDE.md +20 -2
- package/README.md +90 -0
- package/dist/TunnelManager-NGSUBZYI.js +13 -0
- package/dist/{TunnelTui-OZ6AVGTY.js → TunnelTui-UCG2YSLX.js} +6 -18
- package/dist/{chunk-I4HXBP5G.js → chunk-7EQKHVQX.js} +34 -2
- package/dist/{chunk-GBYF2H4H.js → chunk-AFMTIELL.js} +4 -0
- package/dist/{chunk-2HGC37SK.js → chunk-GESMZQHI.js} +47 -119
- package/dist/{chunk-76SOSXXR.js → chunk-MV56U3E6.js} +2 -2
- package/dist/{chunk-MT44NAXX.js → chunk-PD7HXVQ3.js} +1 -1
- package/dist/{chunk-J2U6P376.js → chunk-QNUVQ6KD.js} +204 -21
- package/dist/{chunk-4G6SPMMV.js → chunk-TG6LBCPG.js} +3486 -236
- package/dist/chunk-XZ64ZAGO.js +18 -0
- package/dist/{chunk-H5XJMFNT.js → chunk-Y435RMHQ.js} +7 -3
- package/dist/{configStore-LLWSTN6X.js → configStore-RR5ZU4E3.js} +3 -3
- package/dist/{daemonChild-CV2UTL6T.js → daemonChild-E73NFWKE.js} +13 -8
- package/dist/{daemonConfig-G6S46GPJ.js → daemonConfig-QVXQ47XH.js} +2 -2
- package/dist/index.cjs +3924 -281
- package/dist/index.d.cts +135 -53
- package/dist/index.d.ts +135 -53
- package/dist/index.js +13 -10
- package/dist/ipcClient-XGF2KCQO.js +10 -0
- package/dist/{main-WQ7NUQL4.js → main-M6MACH7D.js} +9 -8
- package/dist/workers/file_serve_worker.js +1 -1
- package/package.json +5 -2
- package/scripts/install/install.ps1 +261 -0
- package/scripts/install/install.sh +387 -0
- package/dist/TunnelManager-I3NW6UXU.js +0 -11
- package/dist/ipcClient-URHJKNEH.js +0 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runDaemonChild
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TG6LBCPG.js";
|
|
5
5
|
import {
|
|
6
6
|
RemoteManagementUnauthorizedError,
|
|
7
7
|
TunnelOperations,
|
|
@@ -13,20 +13,21 @@ import {
|
|
|
13
13
|
getRemoteManagementState,
|
|
14
14
|
initiateRemoteManagement,
|
|
15
15
|
isDaemonRunning
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-GESMZQHI.js";
|
|
17
|
+
import "./chunk-PD7HXVQ3.js";
|
|
18
18
|
import {
|
|
19
19
|
DaemonHost
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-7EQKHVQX.js";
|
|
21
|
+
import "./chunk-Y435RMHQ.js";
|
|
22
|
+
import "./chunk-XZ64ZAGO.js";
|
|
22
23
|
import {
|
|
23
24
|
TunnelManager
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-QNUVQ6KD.js";
|
|
25
26
|
import "./chunk-UB26QJ4T.js";
|
|
26
27
|
import {
|
|
27
28
|
enablePackageLogging
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
29
|
+
} from "./chunk-MV56U3E6.js";
|
|
30
|
+
import "./chunk-AFMTIELL.js";
|
|
30
31
|
export {
|
|
31
32
|
DaemonHost,
|
|
32
33
|
RemoteManagementUnauthorizedError,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinggy",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Create secure, shareable tunnels to your localhost and manage them from the command line. ",
|
|
@@ -53,9 +53,12 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@pinggy/pinggy": "^0.5.3",
|
|
56
|
+
"@xterm/addon-serialize": "^0.14.0",
|
|
57
|
+
"@xterm/headless": "^6.0.0",
|
|
56
58
|
"blessed": "^0.1.81",
|
|
57
59
|
"clipboardy": "^5.0.0",
|
|
58
60
|
"mime": "^4.1.0",
|
|
61
|
+
"node-pty": "^1.1.0",
|
|
59
62
|
"picocolors": "^1.1.1",
|
|
60
63
|
"qrcode": "^1.5.4",
|
|
61
64
|
"winston": "^3.17.0",
|
|
@@ -71,7 +74,7 @@
|
|
|
71
74
|
"@types/ws": "^8.18.1",
|
|
72
75
|
"@typescript-eslint/eslint-plugin": "^8.60.0",
|
|
73
76
|
"@typescript-eslint/parser": "^8.60.0",
|
|
74
|
-
"@yao-pkg/pkg": "
|
|
77
|
+
"@yao-pkg/pkg": "6.19.0",
|
|
75
78
|
"eslint": "^10.4.0",
|
|
76
79
|
"jest": "^30.1.2",
|
|
77
80
|
"ts-jest": "^29.4.1",
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Installs or updates the Pinggy CLI on Windows, then signs this machine in as a Pinggy device.
|
|
2
|
+
#
|
|
3
|
+
# irm https://pinggy.io/install.ps1 | iex
|
|
4
|
+
# $env:DEVICE_AGENT_TOKEN='<token>'; irm https://pinggy.io/install.ps1 | iex
|
|
5
|
+
#
|
|
6
|
+
# The binary goes to %LOCALAPPDATA%\Pinggy\bin\pinggy.exe, and that directory goes on the user PATH. No admin.
|
|
7
|
+
#
|
|
8
|
+
# Setting, from the dashboard's command:
|
|
9
|
+
# $env:DEVICE_AGENT_TOKEN a device token. An older pinggy updates without asking, then `pinggy device connect`
|
|
10
|
+
# runs with no email and no code. The token reaches it in its environment, never on a
|
|
11
|
+
# command line. The script removes the variable from this window when it ends
|
|
12
|
+
#
|
|
13
|
+
# Overrides, for dev and tests:
|
|
14
|
+
# $env:PINGGY_VERSION a release tag, such as v0.6.1. Default: the latest release
|
|
15
|
+
# $env:PINGGY_BINARY_URL a full binary URL, file:// included. Replaces the installed binary without a version check
|
|
16
|
+
# $env:PINGGY_MANAGE a non-production dashboard host, passed to `pinggy device login` or `connect` as --manage
|
|
17
|
+
#
|
|
18
|
+
# The source lives in Pinggy-io/cli-js, scripts/install/. A release copies it to pinggy.io.
|
|
19
|
+
# Design: docs/pinggy-devices/install-script-plan.md in the pinggy_backend repo.
|
|
20
|
+
#
|
|
21
|
+
# iex runs this inside the user's own session. So it never calls exit, which would close their window, and every
|
|
22
|
+
# helper and preference is local to Install-Pinggy. Nothing runs until the last line.
|
|
23
|
+
|
|
24
|
+
function Install-Pinggy {
|
|
25
|
+
# Write-Host, because iex also prints the output stream, and these lines are messages, not output.
|
|
26
|
+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '')]
|
|
27
|
+
param()
|
|
28
|
+
|
|
29
|
+
$ErrorActionPreference = 'Stop'
|
|
30
|
+
# The progress bar makes Invoke-WebRequest many times slower in Windows PowerShell 5.1.
|
|
31
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
32
|
+
|
|
33
|
+
$releasesUrl = 'https://github.com/Pinggy-io/cli-js/releases'
|
|
34
|
+
$installDir = Join-Path $env:LOCALAPPDATA 'Pinggy\bin'
|
|
35
|
+
$installPath = Join-Path $installDir 'pinggy.exe'
|
|
36
|
+
$versionPattern = 'Pinggy CLI version:\s*(\S+)'
|
|
37
|
+
$cpuArchitectureX64 = 9
|
|
38
|
+
$cpuArchitectureArm64 = 12
|
|
39
|
+
|
|
40
|
+
# Win32_Processor describes the machine. PROCESSOR_ARCHITECTURE describes this process, and reads AMD64 in an
|
|
41
|
+
# x64 PowerShell emulated on ARM64.
|
|
42
|
+
function Get-Cpu {
|
|
43
|
+
$architecture = $null
|
|
44
|
+
try {
|
|
45
|
+
$architecture = (Get-CimInstance -ClassName Win32_Processor | Select-Object -First 1).Architecture
|
|
46
|
+
} catch {
|
|
47
|
+
$architecture = $null
|
|
48
|
+
}
|
|
49
|
+
if ($architecture -eq $cpuArchitectureX64) { return 'x64' }
|
|
50
|
+
if ($architecture -eq $cpuArchitectureArm64) { return 'arm64' }
|
|
51
|
+
|
|
52
|
+
$processArchitecture = $env:PROCESSOR_ARCHITEW6432
|
|
53
|
+
if (-not $processArchitecture) { $processArchitecture = $env:PROCESSOR_ARCHITECTURE }
|
|
54
|
+
if ($processArchitecture -eq 'AMD64') { return 'x64' }
|
|
55
|
+
if ($processArchitecture -eq 'ARM64') { return 'arm64' }
|
|
56
|
+
throw "pinggy install: unsupported CPU: $processArchitecture. The pinggy binaries are built for x64 and arm64."
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# GitHub redirects /releases/latest to /releases/tag/<tag>. Reading the redirect costs no API call, so the
|
|
60
|
+
# API's 60 requests an hour per IP do not apply.
|
|
61
|
+
function Get-TargetTag {
|
|
62
|
+
if ($env:PINGGY_VERSION) {
|
|
63
|
+
if ($env:PINGGY_VERSION.StartsWith('v')) { return $env:PINGGY_VERSION }
|
|
64
|
+
return "v$($env:PINGGY_VERSION)"
|
|
65
|
+
}
|
|
66
|
+
$response = Invoke-WebRequest -Uri "$releasesUrl/latest" -Method Head -UseBasicParsing
|
|
67
|
+
$baseResponse = $response.BaseResponse
|
|
68
|
+
if ($baseResponse.PSObject.Properties['ResponseUri']) {
|
|
69
|
+
# Windows PowerShell 5.1: HttpWebResponse
|
|
70
|
+
$finalUrl = $baseResponse.ResponseUri.AbsoluteUri
|
|
71
|
+
} else {
|
|
72
|
+
# PowerShell 7: HttpResponseMessage
|
|
73
|
+
$finalUrl = $baseResponse.RequestMessage.RequestUri.AbsoluteUri
|
|
74
|
+
}
|
|
75
|
+
$tag = ($finalUrl -split '/')[-1]
|
|
76
|
+
if ($tag -notmatch '^v\d') {
|
|
77
|
+
throw "pinggy install: could not read the latest release tag from $releasesUrl/latest"
|
|
78
|
+
}
|
|
79
|
+
return $tag
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# The version a binary reports, or '' when it does not run. 'Continue', because Windows PowerShell 5.1 turns a
|
|
83
|
+
# native command's stderr into a terminating error under 'Stop'.
|
|
84
|
+
function Get-BinaryVersion([string] $path) {
|
|
85
|
+
$ErrorActionPreference = 'Continue'
|
|
86
|
+
try {
|
|
87
|
+
$output = & $path --version 2>$null | Out-String
|
|
88
|
+
} catch {
|
|
89
|
+
return ''
|
|
90
|
+
}
|
|
91
|
+
if ($output -match $versionPattern) { return $Matches[1] }
|
|
92
|
+
return ''
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function Test-Interactive {
|
|
96
|
+
return [Environment]::UserInteractive -and -not [Console]::IsInputRedirected
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
# Enter, or no terminal, means yes. Only an answer starting with n means no.
|
|
100
|
+
function Confirm-Update([string] $question) {
|
|
101
|
+
if (-not (Test-Interactive)) { return $true }
|
|
102
|
+
$answer = Read-Host $question
|
|
103
|
+
return -not ($answer -match '^\s*n')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function Save-Binary([string] $url, [string] $destination) {
|
|
107
|
+
if ($url -like 'file://*') {
|
|
108
|
+
# Invoke-WebRequest in PowerShell 7 cannot read file:// URLs.
|
|
109
|
+
Copy-Item -LiteralPath ([Uri] $url).LocalPath -Destination $destination -Force
|
|
110
|
+
} elseif ($url -like 'https://*') {
|
|
111
|
+
Invoke-WebRequest -Uri $url -OutFile $destination -UseBasicParsing
|
|
112
|
+
} else {
|
|
113
|
+
throw 'pinggy install: PINGGY_BINARY_URL must start with https:// or file://'
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Windows refuses to overwrite a running .exe, but allows a rename. So the old file moves aside under a unique
|
|
118
|
+
# name, and a later run deletes it once nothing runs it. A .old still locked never blocks the next update.
|
|
119
|
+
function Move-BinaryIntoPlace([string] $newPath) {
|
|
120
|
+
Get-ChildItem -LiteralPath $installDir -Filter 'pinggy.exe.*.old' |
|
|
121
|
+
Remove-Item -Force -ErrorAction SilentlyContinue
|
|
122
|
+
if (Test-Path -LiteralPath $installPath) {
|
|
123
|
+
Move-Item -LiteralPath $installPath -Destination "$installPath.$([DateTime]::UtcNow.Ticks).old"
|
|
124
|
+
}
|
|
125
|
+
Move-Item -LiteralPath $newPath -Destination $installPath
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function Install-Binary([string] $tag, [string] $cpu) {
|
|
129
|
+
if ($env:PINGGY_BINARY_URL) {
|
|
130
|
+
$url = $env:PINGGY_BINARY_URL
|
|
131
|
+
} else {
|
|
132
|
+
$url = "$releasesUrl/download/$tag/pinggy-win-$cpu.exe"
|
|
133
|
+
}
|
|
134
|
+
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
|
|
135
|
+
$newPath = "$installPath.new.exe"
|
|
136
|
+
|
|
137
|
+
Write-Host "Downloading $url"
|
|
138
|
+
try {
|
|
139
|
+
try {
|
|
140
|
+
Save-Binary $url $newPath
|
|
141
|
+
} catch {
|
|
142
|
+
throw "pinggy install: the download failed: $url. $($_.Exception.Message)"
|
|
143
|
+
}
|
|
144
|
+
$downloadedVersion = Get-BinaryVersion $newPath
|
|
145
|
+
if (-not $downloadedVersion) {
|
|
146
|
+
throw "pinggy install: the downloaded file does not run on this machine (windows-$cpu). " +
|
|
147
|
+
'The installed pinggy is unchanged.'
|
|
148
|
+
}
|
|
149
|
+
Move-BinaryIntoPlace $newPath
|
|
150
|
+
} finally {
|
|
151
|
+
Remove-Item -LiteralPath $newPath -Force -ErrorAction SilentlyContinue
|
|
152
|
+
}
|
|
153
|
+
Write-Host "Installed pinggy $downloadedVersion to $installPath"
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# Steps 2 to 6 of the plan: compare with the installed binary, then download only when needed.
|
|
157
|
+
function Install-OrUpdate([string] $cpu) {
|
|
158
|
+
if ($env:PINGGY_BINARY_URL) {
|
|
159
|
+
Install-Binary '' $cpu
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
$tag = Get-TargetTag
|
|
164
|
+
$targetVersion = $tag.Substring(1)
|
|
165
|
+
if (-not (Test-Path -LiteralPath $installPath)) {
|
|
166
|
+
Install-Binary $tag $cpu
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
$installedVersion = Get-BinaryVersion $installPath
|
|
171
|
+
if (-not $installedVersion) {
|
|
172
|
+
Write-Host "$installPath does not run. Replacing it."
|
|
173
|
+
Install-Binary $tag $cpu
|
|
174
|
+
} elseif ($installedVersion -eq $targetVersion) {
|
|
175
|
+
Write-Host "pinggy $installedVersion is up to date."
|
|
176
|
+
} elseif ($env:DEVICE_AGENT_TOKEN) {
|
|
177
|
+
# An older CLI ignores DEVICE_AGENT_TOKEN, so keeping it would leave the machine unconnected.
|
|
178
|
+
Write-Host "Updating pinggy $installedVersion to $targetVersion."
|
|
179
|
+
Install-Binary $tag $cpu
|
|
180
|
+
} elseif (Confirm-Update "pinggy $installedVersion is installed. Update to $($targetVersion)? [Y/n]") {
|
|
181
|
+
Install-Binary $tag $cpu
|
|
182
|
+
} else {
|
|
183
|
+
Write-Host "Keeping pinggy $installedVersion."
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function Test-PathListHasInstallDir([string] $pathList) {
|
|
188
|
+
$wanted = $installDir.TrimEnd('\')
|
|
189
|
+
foreach ($entry in ($pathList -split ';')) {
|
|
190
|
+
if ([Environment]::ExpandEnvironmentVariables($entry).TrimEnd('\') -ieq $wanted) { return $true }
|
|
191
|
+
}
|
|
192
|
+
return $false
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
# Reads and writes the registry, not [Environment]::GetEnvironmentVariable: that returns %USERPROFILE%-style
|
|
196
|
+
# entries expanded, and writing them back would flatten them.
|
|
197
|
+
function Add-InstallDirToPath {
|
|
198
|
+
$environmentKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Environment', $true)
|
|
199
|
+
try {
|
|
200
|
+
$userPath = [string] $environmentKey.GetValue('Path', '',
|
|
201
|
+
[Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
|
|
202
|
+
if (-not (Test-PathListHasInstallDir $userPath)) {
|
|
203
|
+
$entries = @($userPath -split ';' | Where-Object { $_ }) + $installDir
|
|
204
|
+
$environmentKey.SetValue('Path', ($entries -join ';'), [Microsoft.Win32.RegistryValueKind]::ExpandString)
|
|
205
|
+
# Any user variable set through .NET broadcasts WM_SETTINGCHANGE, so new terminals read the new PATH.
|
|
206
|
+
[Environment]::SetEnvironmentVariable('PINGGY_INSTALLER', $null, 'User')
|
|
207
|
+
Write-Host "Added $installDir to your user PATH. New terminals find pinggy."
|
|
208
|
+
}
|
|
209
|
+
} finally {
|
|
210
|
+
$environmentKey.Close()
|
|
211
|
+
}
|
|
212
|
+
if (-not (Test-PathListHasInstallDir $env:Path)) {
|
|
213
|
+
$env:Path = "$installDir;$env:Path"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
# Runs the installed file by its full path, so an npm-installed pinggy earlier on PATH does not answer.
|
|
218
|
+
function Invoke-DeviceLogin {
|
|
219
|
+
$loginArguments = @('device', 'login')
|
|
220
|
+
if ($env:PINGGY_MANAGE) { $loginArguments += @('--manage', $env:PINGGY_MANAGE) }
|
|
221
|
+
|
|
222
|
+
if (-not (Test-Interactive)) {
|
|
223
|
+
Write-Host "Installed. To sign this machine in, run: pinggy $($loginArguments -join ' ')"
|
|
224
|
+
Write-Host ('On a machine without a keyboard, add the device in the dashboard and run: ' +
|
|
225
|
+
'pinggy device connect --token <TOKEN>')
|
|
226
|
+
return
|
|
227
|
+
}
|
|
228
|
+
Write-Host ''
|
|
229
|
+
& $installPath @loginArguments
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
# Runs the installed file by its full path, as Invoke-DeviceLogin does. connect reads DEVICE_AGENT_TOKEN from
|
|
233
|
+
# the environment it inherits, and reads no key, so it runs the same with no console.
|
|
234
|
+
function Invoke-DeviceConnect {
|
|
235
|
+
$connectArguments = @('device', 'connect')
|
|
236
|
+
if ($env:PINGGY_MANAGE) { $connectArguments += @('--manage', $env:PINGGY_MANAGE) }
|
|
237
|
+
Write-Host ''
|
|
238
|
+
& $installPath @connectArguments
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# Older Windows PowerShell 5.1 setups offer less than TLS 1.2, and GitHub refuses them.
|
|
242
|
+
[Net.ServicePointManager]::SecurityProtocol =
|
|
243
|
+
[Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
$cpu = Get-Cpu
|
|
247
|
+
Install-OrUpdate $cpu
|
|
248
|
+
Add-InstallDirToPath
|
|
249
|
+
if ($env:DEVICE_AGENT_TOKEN) {
|
|
250
|
+
Invoke-DeviceConnect
|
|
251
|
+
} else {
|
|
252
|
+
Invoke-DeviceLogin
|
|
253
|
+
}
|
|
254
|
+
} finally {
|
|
255
|
+
# iex runs in the user's own session, so every later command in this window would carry the token. A
|
|
256
|
+
# finally runs after an error and after Ctrl+C too.
|
|
257
|
+
Remove-Item -Path Env:\DEVICE_AGENT_TOKEN -ErrorAction SilentlyContinue
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
Install-Pinggy
|