pterm 0.0.24 → 0.0.25
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/README.md +181 -15
- package/endpoint.js +163 -0
- package/index.js +70 -15
- package/package.json +1 -1
- package/rpc.js +26 -8
- package/script.js +114 -59
- package/target.js +437 -0
- package/util.js +146 -18
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ npm install -g pterm
|
|
|
10
10
|
|
|
11
11
|
# Usage
|
|
12
12
|
|
|
13
|
+
This README documents the stable public CLI surface.
|
|
14
|
+
|
|
13
15
|
## version
|
|
14
16
|
|
|
15
17
|
prints the current version
|
|
@@ -20,10 +22,10 @@ prints the current version
|
|
|
20
22
|
pterm version <type>
|
|
21
23
|
```
|
|
22
24
|
|
|
23
|
-
- `type`: may be `terminal`, `pinokiod`, or `
|
|
25
|
+
- `type`: may be `terminal`, `pinokiod`, `pinokio`, or `script`
|
|
24
26
|
- `terminal`: returns the pterm version
|
|
25
27
|
- `pinokiod`: returns the pinokiod version
|
|
26
|
-
- `pinokio`: returns the
|
|
28
|
+
- `pinokio`: returns the Pinokio app wrapper version
|
|
27
29
|
- `script`: returns the valid script version for the current client. used for including in `pinokio.js`
|
|
28
30
|
|
|
29
31
|
### example
|
|
@@ -32,16 +34,88 @@ pterm version <type>
|
|
|
32
34
|
pterm version terminal
|
|
33
35
|
```
|
|
34
36
|
|
|
37
|
+
## refs
|
|
38
|
+
|
|
39
|
+
Pinokio resource references use this syntax:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
pinokio://<host>:<port>/<scope>/<id>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
pinokio://127.0.0.1:42000/api/cropper.git
|
|
49
|
+
pinokio://192.168.86.26:42000/api/facefusion-pinokio.git
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Currently documented scope:
|
|
53
|
+
|
|
54
|
+
- `api`: an installed Pinokio app under `PINOKIO_HOME/api`
|
|
55
|
+
|
|
56
|
+
How refs are used:
|
|
57
|
+
|
|
58
|
+
- the `host:port` in a ref identifies the target Pinokio control plane, not the app's `ready_url`
|
|
59
|
+
- `pterm` does not connect directly to the app endpoint described by the ref
|
|
60
|
+
- `pterm` talks to the local Pinokio control plane, and the local control plane resolves or forwards the ref to the target Pinokio node as needed
|
|
61
|
+
|
|
62
|
+
## open
|
|
63
|
+
|
|
64
|
+
Open a URL on the local Pinokio node or on a connected peer node.
|
|
65
|
+
|
|
66
|
+
### syntax
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
pterm open <url> [--peer <peer>] [--surface browser|popup] [--preset center-small|center-medium|center-large|fullscreen]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `--peer`: optional target Pinokio node. May be a peer host, `host:port`, or peer name.
|
|
73
|
+
- `--surface`: optional UI surface. `popup` requests a Pinokio popup window. `browser` forces the system browser. Default is popup-preferred.
|
|
74
|
+
- `--preset`: optional popup size preset. Only applies when popup is used.
|
|
75
|
+
|
|
76
|
+
Behavior:
|
|
77
|
+
|
|
78
|
+
- `pterm` still talks to the local Pinokio control plane first
|
|
79
|
+
- if `--peer` is set, the local node forwards the open request to that peer
|
|
80
|
+
- if `--peer` is set, the URL is opened from that peer node's point of view, so `http://127.0.0.1:7860` means the peer's loopback
|
|
81
|
+
- by default, `pterm open` prefers a Pinokio popup window
|
|
82
|
+
- on a full Pinokio desktop node, the default opens a desktop popup
|
|
83
|
+
- on a server-only or minimal node, the default automatically falls back to opening the system browser
|
|
84
|
+
- default popup preset is `center-medium`
|
|
85
|
+
- `center-medium` opens centered on the active display using roughly 64% of screen width and 72% of screen height, with minimum size `900x700`
|
|
86
|
+
|
|
87
|
+
### examples
|
|
88
|
+
|
|
89
|
+
Open a URL locally with the default popup-preferred behavior:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
pterm open http://127.0.0.1:7860
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Force the system browser instead of the default popup-preferred behavior:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
pterm open http://127.0.0.1:7860 --surface browser
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Open a URL on a peer node:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
pterm open http://127.0.0.1:7860 --peer 192.168.86.26
|
|
105
|
+
```
|
|
106
|
+
|
|
35
107
|
## start
|
|
36
108
|
|
|
37
|
-
Start a pinokio script.
|
|
109
|
+
Start a pinokio script. `pterm` options go before `--`. Script args go after `--`.
|
|
38
110
|
|
|
39
111
|
### syntax
|
|
40
112
|
|
|
41
113
|
```
|
|
42
|
-
pterm start <script_path> [
|
|
114
|
+
pterm start <script_path> [--ref <pinokio_ref>] [-- --<key>=<value> ...]
|
|
43
115
|
```
|
|
44
116
|
|
|
117
|
+
With `--ref`, prefer relative script paths like `start.js`. `~/...` expansion is only local.
|
|
118
|
+
|
|
45
119
|
### examples
|
|
46
120
|
|
|
47
121
|
Starting a script named `install.js`:
|
|
@@ -53,7 +127,7 @@ pterm start install.js
|
|
|
53
127
|
Starting a script named `start.js` with parameters:
|
|
54
128
|
|
|
55
129
|
```
|
|
56
|
-
pterm start start.js --port=3000 --model=google/gemma-3n-E4B-it
|
|
130
|
+
pterm start start.js -- --port=3000 --model=google/gemma-3n-E4B-it
|
|
57
131
|
```
|
|
58
132
|
|
|
59
133
|
Above command starts the script `start.js` with the following args:
|
|
@@ -65,6 +139,24 @@ Above command starts the script `start.js` with the following args:
|
|
|
65
139
|
}
|
|
66
140
|
```
|
|
67
141
|
|
|
142
|
+
Query parameters in the script path are also passed through as script input automatically:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
pterm start 'run.js?mode=Default'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Starting a relative script inside a selected app:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
pterm start start.js --ref pinokio://127.0.0.1:42000/api/metube-pinokio.git
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Passing a script argument named `app` without conflicting with `pterm --ref`:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
pterm start start.js --ref pinokio://127.0.0.1:42000/api/metube-pinokio.git -- --app=my-script-value
|
|
158
|
+
```
|
|
159
|
+
|
|
68
160
|
Which can be accessed in the `start.js` script, for example:
|
|
69
161
|
|
|
70
162
|
```json
|
|
@@ -90,8 +182,12 @@ Stops a script if running:
|
|
|
90
182
|
|
|
91
183
|
```
|
|
92
184
|
pterm stop <script_path>
|
|
185
|
+
pterm stop <script_path> --ref <pinokio_ref>
|
|
186
|
+
pterm stop <pinokio_ref>
|
|
93
187
|
```
|
|
94
188
|
|
|
189
|
+
With `--ref`, prefer relative script paths like `start.js`. `~/...` expansion is only local.
|
|
190
|
+
|
|
95
191
|
|
|
96
192
|
### example
|
|
97
193
|
|
|
@@ -101,6 +197,18 @@ Stop the `start.js` script if it's running:
|
|
|
101
197
|
pterm stop start.js
|
|
102
198
|
```
|
|
103
199
|
|
|
200
|
+
Stop a relative script inside a selected app:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
pterm stop start.js --ref pinokio://127.0.0.1:42000/api/metube-pinokio.git
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Stop all running scripts for an app:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
pterm stop pinokio://127.0.0.1:42000/api/metube-pinokio.git
|
|
210
|
+
```
|
|
211
|
+
|
|
104
212
|
## run
|
|
105
213
|
|
|
106
214
|
Run a launcher. Equivalent to the user visiting a launcher page. By default it will run whichever script is the current launcher default. If the launcher exposes no explicit default, you can provide repeated `--default` selectors and Pinokio will match the first selector that exists in the launcher's current menu state.
|
|
@@ -109,6 +217,7 @@ Run a launcher. Equivalent to the user visiting a launcher page. By default it w
|
|
|
109
217
|
|
|
110
218
|
```
|
|
111
219
|
pterm run <launcher_path_or_uri> [--default <selector>]... [--open]
|
|
220
|
+
pterm run <pinokio_ref> [--default <selector>]... [--open]
|
|
112
221
|
```
|
|
113
222
|
|
|
114
223
|
- `--open`: (optional) open URL results in the browser. Default behavior is to print the URL to stdout without opening a browser.
|
|
@@ -143,7 +252,16 @@ pterm run ~/pinokio/api/facefusion-pinokio.git \
|
|
|
143
252
|
--default install.js
|
|
144
253
|
```
|
|
145
254
|
|
|
146
|
-
|
|
255
|
+
Run an installed app by Pinokio ref:
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
pterm run pinokio://192.168.86.26:42000/api/facefusion-pinokio.git \
|
|
259
|
+
--default 'run.js?mode=Default' \
|
|
260
|
+
--default run.js \
|
|
261
|
+
--default install.js
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
For direct script execution with query parameters, use `pterm start`. Query parameters are passed through as script input automatically.
|
|
147
265
|
|
|
148
266
|
```
|
|
149
267
|
pterm start 'run.js?mode=Default'
|
|
@@ -272,14 +390,37 @@ pterm which node
|
|
|
272
390
|
pterm which git --json
|
|
273
391
|
```
|
|
274
392
|
|
|
393
|
+
## home
|
|
394
|
+
|
|
395
|
+
Get `PINOKIO_HOME`.
|
|
396
|
+
|
|
397
|
+
### syntax
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
pterm home [--json]
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
- `--json`: (optional) print the raw JSON response instead of only the path.
|
|
404
|
+
|
|
405
|
+
### examples
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
pterm home
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
pterm home --json
|
|
413
|
+
```
|
|
414
|
+
|
|
275
415
|
## status
|
|
276
416
|
|
|
277
|
-
Get app status by app id.
|
|
417
|
+
Get app status by app id or Pinokio ref.
|
|
278
418
|
|
|
279
419
|
### syntax
|
|
280
420
|
|
|
281
421
|
```
|
|
282
422
|
pterm status <app_id> [--probe] [--timeout=<ms>]
|
|
423
|
+
pterm status <pinokio_ref> [--probe] [--timeout=<ms>]
|
|
283
424
|
```
|
|
284
425
|
|
|
285
426
|
- `--probe`: (optional) actively probe app health.
|
|
@@ -295,6 +436,10 @@ pterm status comfyanonymous-comfyui
|
|
|
295
436
|
pterm status comfyanonymous-comfyui --probe --timeout=5000
|
|
296
437
|
```
|
|
297
438
|
|
|
439
|
+
```
|
|
440
|
+
pterm status pinokio://192.168.86.26:42000/api/comfyanonymous-comfyui --probe --timeout=5000
|
|
441
|
+
```
|
|
442
|
+
|
|
298
443
|
## stars
|
|
299
444
|
|
|
300
445
|
List starred apps.
|
|
@@ -350,12 +495,13 @@ pterm unstar comfyanonymous-comfyui
|
|
|
350
495
|
|
|
351
496
|
## logs
|
|
352
497
|
|
|
353
|
-
Get app logs by app id.
|
|
498
|
+
Get app logs by app id or Pinokio ref.
|
|
354
499
|
|
|
355
500
|
### syntax
|
|
356
501
|
|
|
357
502
|
```
|
|
358
503
|
pterm logs <app_id> [--script=<name>] [--tail=<lines>]
|
|
504
|
+
pterm logs <pinokio_ref> [--script=<name>] [--tail=<lines>]
|
|
359
505
|
```
|
|
360
506
|
|
|
361
507
|
- `--script`: (optional) filter to a script.
|
|
@@ -371,11 +517,15 @@ pterm logs comfyanonymous-comfyui
|
|
|
371
517
|
pterm logs comfyanonymous-comfyui --script=start --tail=200
|
|
372
518
|
```
|
|
373
519
|
|
|
520
|
+
```
|
|
521
|
+
pterm logs pinokio://192.168.86.26:42000/api/comfyanonymous-comfyui --script=start --tail=200
|
|
522
|
+
```
|
|
523
|
+
|
|
374
524
|
## filepicker
|
|
375
525
|
|
|
376
526
|
Display a file picker dialog, which lets the user select one or more file or folder paths, powered by tkinter.
|
|
377
527
|
|
|
378
|
-
This API is NOT for uploading the actual files but for submitting file paths.
|
|
528
|
+
This API is NOT for uploading the actual files but for submitting file paths. Use `pterm upload <pinokio_ref> <file...>` when a remote app needs real files staged onto its machine.
|
|
379
529
|
|
|
380
530
|
### syntax
|
|
381
531
|
|
|
@@ -408,12 +558,6 @@ The most basic command lets users select a single file:
|
|
|
408
558
|
pterm filepicker
|
|
409
559
|
```
|
|
410
560
|
|
|
411
|
-
which is equivalent to:
|
|
412
|
-
|
|
413
|
-
```
|
|
414
|
-
pterm filepicker --type=file
|
|
415
|
-
```
|
|
416
|
-
|
|
417
561
|
#### Select multiple files
|
|
418
562
|
|
|
419
563
|
```
|
|
@@ -438,6 +582,28 @@ pterm filepicker --filetype='images/*.png,*.jpg,*.jpeg'
|
|
|
438
582
|
pterm filepicker --filetype='images/*.png,*.jpg,*.jpeg' --filetype='docs/*.pdf'
|
|
439
583
|
```
|
|
440
584
|
|
|
585
|
+
## upload
|
|
586
|
+
|
|
587
|
+
Stage one or more local files onto the selected app's machine and return remote filesystem paths that can be passed to path-based tasks.
|
|
588
|
+
|
|
589
|
+
### syntax
|
|
590
|
+
|
|
591
|
+
```
|
|
592
|
+
pterm upload <app_id|pinokio_ref> <file...>
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
Quoted `~/...` file paths are expanded locally before upload.
|
|
596
|
+
|
|
597
|
+
### examples
|
|
598
|
+
|
|
599
|
+
```
|
|
600
|
+
pterm upload facefusion-pinokio.git ./face.jpg ./video.mp4
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
```
|
|
604
|
+
pterm upload pinokio://192.168.86.26:42000/api/facefusion-pinokio.git ./face.jpg ./video.mp4
|
|
605
|
+
```
|
|
606
|
+
|
|
441
607
|
## clipboard
|
|
442
608
|
|
|
443
609
|
write to or read from clipboard
|
package/endpoint.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const os = require('os')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const axios = require('axios')
|
|
5
|
+
|
|
6
|
+
const DEFAULT_PROTOCOL = 'http'
|
|
7
|
+
const DEFAULT_HOST = '127.0.0.1'
|
|
8
|
+
const DEFAULT_PORT = 42000
|
|
9
|
+
const DEFAULT_BASE_URL = `${DEFAULT_PROTOCOL}://${DEFAULT_HOST}:${DEFAULT_PORT}`
|
|
10
|
+
const CONFIG_PATH = path.resolve(os.homedir(), '.pinokio', 'config.json')
|
|
11
|
+
|
|
12
|
+
let resolvedHttpBaseUrlPromise = null
|
|
13
|
+
|
|
14
|
+
function formatHostForUrl(host) {
|
|
15
|
+
if (!host) {
|
|
16
|
+
return ''
|
|
17
|
+
}
|
|
18
|
+
const normalized = String(host).trim().replace(/^\[|\]$/g, '')
|
|
19
|
+
if (!normalized) {
|
|
20
|
+
return ''
|
|
21
|
+
}
|
|
22
|
+
return normalized.includes(':') ? `[${normalized}]` : normalized
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function normalizeBaseUrl(value) {
|
|
26
|
+
if (typeof value !== 'string') {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
const trimmed = value.trim()
|
|
30
|
+
if (!trimmed) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const url = new URL(trimmed)
|
|
35
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
return `${url.protocol}//${url.host}`
|
|
39
|
+
} catch (error) {
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildExplicitHttpBaseUrl(target) {
|
|
45
|
+
if (!target) {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
if (typeof target === 'string') {
|
|
49
|
+
const normalized = normalizeBaseUrl(target)
|
|
50
|
+
if (normalized) {
|
|
51
|
+
return normalized
|
|
52
|
+
}
|
|
53
|
+
const host = formatHostForUrl(target)
|
|
54
|
+
if (!host) {
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
return normalizeBaseUrl(`${DEFAULT_PROTOCOL}://${host}:${DEFAULT_PORT}`)
|
|
58
|
+
}
|
|
59
|
+
if (typeof target !== 'object') {
|
|
60
|
+
return null
|
|
61
|
+
}
|
|
62
|
+
const protocol = target.protocol === 'https' ? 'https' : DEFAULT_PROTOCOL
|
|
63
|
+
const host = formatHostForUrl(target.host)
|
|
64
|
+
if (!host) {
|
|
65
|
+
return null
|
|
66
|
+
}
|
|
67
|
+
const rawPort = Number.parseInt(String(target.port), 10)
|
|
68
|
+
const port = Number.isFinite(rawPort) && rawPort > 0 ? rawPort : DEFAULT_PORT
|
|
69
|
+
return normalizeBaseUrl(`${protocol}://${host}:${port}`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function readStoredAccessBaseUrl() {
|
|
73
|
+
try {
|
|
74
|
+
const raw = fs.readFileSync(CONFIG_PATH, 'utf8')
|
|
75
|
+
const parsed = JSON.parse(raw)
|
|
76
|
+
const access = parsed && parsed.access
|
|
77
|
+
if (!access) {
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
if (typeof access === 'string') {
|
|
81
|
+
const value = access.trim()
|
|
82
|
+
if (!value) {
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
if (/^https?:\/\//i.test(value)) {
|
|
86
|
+
return normalizeBaseUrl(value)
|
|
87
|
+
}
|
|
88
|
+
if (/^\[.*\](?::\d+)?$/.test(value) || /:\d+$/.test(value)) {
|
|
89
|
+
return normalizeBaseUrl(`${DEFAULT_PROTOCOL}://${value}`)
|
|
90
|
+
}
|
|
91
|
+
return normalizeBaseUrl(`${DEFAULT_PROTOCOL}://${formatHostForUrl(value)}:${DEFAULT_PORT}`)
|
|
92
|
+
}
|
|
93
|
+
if (typeof access !== 'object') {
|
|
94
|
+
return null
|
|
95
|
+
}
|
|
96
|
+
const protocol = access.protocol === 'https' ? 'https' : DEFAULT_PROTOCOL
|
|
97
|
+
const host = formatHostForUrl(access.host)
|
|
98
|
+
if (!host) {
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
const rawPort = Number.parseInt(String(access.port), 10)
|
|
102
|
+
const port = Number.isFinite(rawPort) && rawPort > 0 ? rawPort : DEFAULT_PORT
|
|
103
|
+
return normalizeBaseUrl(`${protocol}://${host}:${port}`)
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return null
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function canReachControlPlane(baseUrl) {
|
|
110
|
+
try {
|
|
111
|
+
await axios.get(`${baseUrl}/pinokio/version`, {
|
|
112
|
+
timeout: 1000,
|
|
113
|
+
headers: {
|
|
114
|
+
'x-pinokio-client': 'pterm'
|
|
115
|
+
},
|
|
116
|
+
validateStatus: () => true
|
|
117
|
+
})
|
|
118
|
+
return true
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function resolveHttpBaseUrl(target) {
|
|
125
|
+
const explicitBaseUrl = buildExplicitHttpBaseUrl(target)
|
|
126
|
+
if (explicitBaseUrl) {
|
|
127
|
+
return explicitBaseUrl
|
|
128
|
+
}
|
|
129
|
+
if (!resolvedHttpBaseUrlPromise) {
|
|
130
|
+
resolvedHttpBaseUrlPromise = (async () => {
|
|
131
|
+
if (await canReachControlPlane(DEFAULT_BASE_URL)) {
|
|
132
|
+
return DEFAULT_BASE_URL
|
|
133
|
+
}
|
|
134
|
+
return readStoredAccessBaseUrl() || DEFAULT_BASE_URL
|
|
135
|
+
})()
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
return await resolvedHttpBaseUrlPromise
|
|
139
|
+
} catch (error) {
|
|
140
|
+
resolvedHttpBaseUrlPromise = null
|
|
141
|
+
throw error
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function resolveWsBaseUrl(target) {
|
|
146
|
+
const httpBaseUrl = await resolveHttpBaseUrl(target)
|
|
147
|
+
const normalized = normalizeBaseUrl(httpBaseUrl)
|
|
148
|
+
if (!normalized) {
|
|
149
|
+
return `ws://${DEFAULT_HOST}:${DEFAULT_PORT}`
|
|
150
|
+
}
|
|
151
|
+
const url = new URL(normalized)
|
|
152
|
+
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
|
|
153
|
+
return `${url.protocol}//${url.host}`
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
DEFAULT_BASE_URL,
|
|
158
|
+
DEFAULT_PORT,
|
|
159
|
+
buildExplicitHttpBaseUrl,
|
|
160
|
+
readStoredAccessBaseUrl,
|
|
161
|
+
resolveHttpBaseUrl,
|
|
162
|
+
resolveWsBaseUrl,
|
|
163
|
+
}
|
package/index.js
CHANGED
|
@@ -1,18 +1,64 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const path = require('path')
|
|
3
|
+
const axios = require('axios')
|
|
3
4
|
const yargs = require('yargs/yargs')
|
|
4
5
|
const { hideBin } = require('yargs/helpers')
|
|
6
|
+
const { resolveHttpBaseUrl } = require('./endpoint')
|
|
7
|
+
const { isHttpUri, resolveAppControlTarget, resolveStartTarget } = require('./target')
|
|
8
|
+
const extractStartInput = (parsedArgv) => {
|
|
9
|
+
const rawScriptArgs = Array.isArray(parsedArgv && parsedArgv["--"]) ? parsedArgv["--"] : []
|
|
10
|
+
if (!rawScriptArgs.length) {
|
|
11
|
+
return undefined
|
|
12
|
+
}
|
|
13
|
+
const scriptArgv = yargs(rawScriptArgs)
|
|
14
|
+
.parserConfiguration({
|
|
15
|
+
'camel-case-expansion': false,
|
|
16
|
+
'dot-notation': false,
|
|
17
|
+
'duplicate-arguments-array': true,
|
|
18
|
+
'populate--': false
|
|
19
|
+
})
|
|
20
|
+
.help(false)
|
|
21
|
+
.version(false)
|
|
22
|
+
.parse()
|
|
23
|
+
const input = {}
|
|
24
|
+
for (const [key, value] of Object.entries(scriptArgv || {})) {
|
|
25
|
+
if (key === '_' || key === '$0' || value === undefined) {
|
|
26
|
+
continue
|
|
27
|
+
}
|
|
28
|
+
input[key] = value
|
|
29
|
+
}
|
|
30
|
+
return Object.keys(input).length > 0 ? input : undefined
|
|
31
|
+
}
|
|
5
32
|
const argv = yargs(hideBin(process.argv))
|
|
6
33
|
.option('default', {
|
|
7
34
|
type: 'string',
|
|
8
35
|
array: true
|
|
9
36
|
})
|
|
37
|
+
.option('peer', {
|
|
38
|
+
type: 'string'
|
|
39
|
+
})
|
|
40
|
+
.option('surface', {
|
|
41
|
+
type: 'string'
|
|
42
|
+
})
|
|
43
|
+
.option('preset', {
|
|
44
|
+
type: 'string'
|
|
45
|
+
})
|
|
46
|
+
.option('ref', {
|
|
47
|
+
type: 'string'
|
|
48
|
+
})
|
|
49
|
+
.parserConfiguration({
|
|
50
|
+
'populate--': true
|
|
51
|
+
})
|
|
10
52
|
.parse();
|
|
11
53
|
const Script = require('./script')
|
|
12
54
|
const Util = require('./util')
|
|
13
55
|
const script = new Script();
|
|
14
56
|
const util = new Util();
|
|
15
|
-
const
|
|
57
|
+
const fetchPinokioVersion = async () => {
|
|
58
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
59
|
+
const response = await axios.get(`${baseUrl}/pinokio/version`)
|
|
60
|
+
return response.data
|
|
61
|
+
}
|
|
16
62
|
(async () => {
|
|
17
63
|
if (argv._.length > 0) {
|
|
18
64
|
let cmd = argv._[0].toLowerCase()
|
|
@@ -27,27 +73,21 @@ const isHttpUri = (value) => typeof value === "string" && /^https?:\/\//i.test(v
|
|
|
27
73
|
console.log("pterm@" + require('./package.json').version)
|
|
28
74
|
} else if (app === "pinokiod") {
|
|
29
75
|
try {
|
|
30
|
-
let r = await
|
|
31
|
-
return res.json()
|
|
32
|
-
})
|
|
76
|
+
let r = await fetchPinokioVersion()
|
|
33
77
|
console.log(`pinokiod@${r.pinokiod}`)
|
|
34
78
|
} catch (e) {
|
|
35
79
|
}
|
|
36
80
|
} else if (app === "pinokio") {
|
|
37
81
|
try {
|
|
38
|
-
let r = await
|
|
39
|
-
return res.json()
|
|
40
|
-
})
|
|
82
|
+
let r = await fetchPinokioVersion()
|
|
41
83
|
if (r.pinokio) {
|
|
42
|
-
console.log(`
|
|
84
|
+
console.log(`pinokio@${r.pinokio}`)
|
|
43
85
|
}
|
|
44
86
|
} catch (e) {
|
|
45
87
|
}
|
|
46
88
|
} else if (app === "script") {
|
|
47
89
|
try {
|
|
48
|
-
let r = await
|
|
49
|
-
return res.json()
|
|
50
|
-
})
|
|
90
|
+
let r = await fetchPinokioVersion()
|
|
51
91
|
if (r.script) {
|
|
52
92
|
console.log(`${r.script}`)
|
|
53
93
|
}
|
|
@@ -57,6 +97,8 @@ const isHttpUri = (value) => typeof value === "string" && /^https?:\/\//i.test(v
|
|
|
57
97
|
}
|
|
58
98
|
} else if (cmd === "filepicker") {
|
|
59
99
|
await util.filepicker(argv)
|
|
100
|
+
} else if (cmd === "upload") {
|
|
101
|
+
await util.upload(argv)
|
|
60
102
|
} else if (cmd === "download") {
|
|
61
103
|
await util.appDownload(argv)
|
|
62
104
|
} else if (cmd === "registry") {
|
|
@@ -82,19 +124,27 @@ const isHttpUri = (value) => typeof value === "string" && /^https?:\/\//i.test(v
|
|
|
82
124
|
await util.status(argv)
|
|
83
125
|
} else if (cmd === "logs") {
|
|
84
126
|
await util.logs(argv)
|
|
127
|
+
} else if (cmd === "open") {
|
|
128
|
+
await util.open(argv)
|
|
85
129
|
} else if (cmd === "stop") {
|
|
86
130
|
await script.stop(argv)
|
|
87
131
|
} else if (cmd === "start") {
|
|
88
132
|
if (argv._.length > 1) {
|
|
89
133
|
let uri = argv._[1]
|
|
90
|
-
await
|
|
134
|
+
const startTarget = await resolveStartTarget(uri, argv.ref)
|
|
135
|
+
const startInput = extractStartInput(argv)
|
|
136
|
+
const startPayload = startInput
|
|
137
|
+
? { uri: startTarget.uri, input: startInput }
|
|
138
|
+
: startTarget.uri
|
|
139
|
+
await script.start(startPayload, true, null, startTarget.controlPlane)
|
|
91
140
|
} else {
|
|
92
141
|
console.error("required argument: <uri>")
|
|
93
142
|
}
|
|
94
143
|
} else if (cmd === "run") {
|
|
95
144
|
if (argv._.length > 1) {
|
|
96
145
|
let _uri = argv._[1]
|
|
97
|
-
const
|
|
146
|
+
const runTarget = await resolveAppControlTarget(_uri)
|
|
147
|
+
const uri = runTarget.uri
|
|
98
148
|
// try downloading first
|
|
99
149
|
if (isHttpUri(uri)) {
|
|
100
150
|
await util.download({
|
|
@@ -102,16 +152,18 @@ const isHttpUri = (value) => typeof value === "string" && /^https?:\/\//i.test(v
|
|
|
102
152
|
no_exit: true
|
|
103
153
|
})
|
|
104
154
|
}
|
|
155
|
+
let launched = false
|
|
105
156
|
while(true) {
|
|
106
|
-
let default_target = await script.default_script(uri, argv.default)
|
|
157
|
+
let default_target = await script.default_script(uri, argv.default, runTarget.controlPlane)
|
|
107
158
|
if (default_target) {
|
|
159
|
+
launched = true
|
|
108
160
|
if (path.isAbsolute(default_target.uri)) {
|
|
109
161
|
await new Promise((resolve, reject) => {
|
|
110
162
|
script.start(default_target, false, (packet) => {
|
|
111
163
|
if (packet.type === "result") {
|
|
112
164
|
resolve()
|
|
113
165
|
}
|
|
114
|
-
})
|
|
166
|
+
}, runTarget.controlPlane)
|
|
115
167
|
})
|
|
116
168
|
if (script.killed) {
|
|
117
169
|
break
|
|
@@ -133,6 +185,9 @@ const isHttpUri = (value) => typeof value === "string" && /^https?:\/\//i.test(v
|
|
|
133
185
|
if (script.killed) {
|
|
134
186
|
process.exit()
|
|
135
187
|
}
|
|
188
|
+
if (!launched) {
|
|
189
|
+
process.exit(0)
|
|
190
|
+
}
|
|
136
191
|
} else {
|
|
137
192
|
console.error("required argument: <uri>")
|
|
138
193
|
}
|