pterm 0.0.1 → 0.0.5
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 +220 -0
- package/icon.png +0 -0
- package/index.js +72 -0
- package/package.json +10 -2
- package/rpc.js +71 -0
- package/script.js +163 -0
- package/util.js +99 -0
package/README.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Pinokio Terminal
|
|
2
|
+
|
|
3
|
+
Interact with Pinokio through terminal commands
|
|
4
|
+
|
|
5
|
+
# Install
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm install -g pterm
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
# Usage
|
|
12
|
+
|
|
13
|
+
## version
|
|
14
|
+
|
|
15
|
+
prints the current version
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
pinokio version
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## start
|
|
22
|
+
|
|
23
|
+
Start a pinokio script. Arguments can be passed into the script
|
|
24
|
+
|
|
25
|
+
### syntax
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
pinokio start <script_path> [<arg1>, <arg2>, ...]
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### examples
|
|
32
|
+
|
|
33
|
+
Starting a script named `install.js`:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
pinokio start install.js
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Starting a script named `start.js` with parameters:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
pinokio start start.js --port=3000 --model=google/gemma-3n-E4B-it
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Above command starts the script `start.js` with the following args:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
{
|
|
49
|
+
port: 3000,
|
|
50
|
+
model: "google/gemma-3n-E4B-it"
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Which can be accessed in the `start.js` script, for example:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"daemon": true,
|
|
59
|
+
"run": [{
|
|
60
|
+
"method": "shell.run",
|
|
61
|
+
"params": {
|
|
62
|
+
"env": {
|
|
63
|
+
"PORT": "{{args.port}}"
|
|
64
|
+
},
|
|
65
|
+
"message": "python app.py --checkpoint={{args.model}}"
|
|
66
|
+
}
|
|
67
|
+
}]
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## stop
|
|
72
|
+
|
|
73
|
+
Stops a script if running:
|
|
74
|
+
|
|
75
|
+
### syntax
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
pinokio stop <script_path>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
### example
|
|
83
|
+
|
|
84
|
+
Stop the `start.js` script if it's running:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
pinokio stop start.js
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## run
|
|
91
|
+
|
|
92
|
+
Run a launcher. Equivalent to the user visiting a launcher page. Will run whichever script is the current default script.
|
|
93
|
+
|
|
94
|
+
### syntax
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
pinokio run <launcher_path>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### examples
|
|
101
|
+
|
|
102
|
+
Launch the launcher in the current path
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
pinokio run .
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Launch from absolute path
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
pinokio run /pinokio/api/test
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## filepicker
|
|
115
|
+
|
|
116
|
+
Display a file picker dialog, which lets the user select one or more file or folder paths, powered by tkinter.
|
|
117
|
+
|
|
118
|
+
This API is NOT for uploading the actual files but for submitting file paths.
|
|
119
|
+
|
|
120
|
+
### syntax
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
pinokio filepicker [<arg>, <arg>, ...]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Where args can be one of the following:
|
|
127
|
+
|
|
128
|
+
- `<arg>`: script flags
|
|
129
|
+
- `--title`: (optional) file dialog title.
|
|
130
|
+
- `--type`: (optional) which type to select. Either "folder" or "file". If not specified, the value is "file".
|
|
131
|
+
- `--path`: (optional) specify path to open the file dialog from. If not specified, just use the default path.
|
|
132
|
+
- `--multiple`: (optional) whether to allow multiple path selection (`true` or `false`). Default is `false`.
|
|
133
|
+
- `--filetype`: (optional) file types to accept. you can specify multiple `--filetype` flags. The format must follow `type/extension,extension,extension,...` (Example: `--filetype='image/*.png,*.jpg`)
|
|
134
|
+
|
|
135
|
+
### examples
|
|
136
|
+
|
|
137
|
+
#### Select a folder path
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
pinokio filepicker --type=folder
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Select a file path
|
|
144
|
+
|
|
145
|
+
The most basic command lets users select a single file:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
pinokio filepicker
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
which is equivalent to:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
pinokio filepicker --type=file
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
#### Select multiple files
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
pinokio filepicker --multiple
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### Open the filepicker from the current path
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
pinokio filepicker --path=.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### Open an image filepicker
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
pinokio filepicker --filetype='images/*.png,*.jpg,*.jpeg'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
#### Open a filepicker with multiple file types
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
pinokio filepicker --filetype='images/*.png,*.jpg,*.jpeg' --filetype='docs/*.pdf'
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
## push
|
|
183
|
+
|
|
184
|
+
Send a desktop notification
|
|
185
|
+
|
|
186
|
+
### syntax
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
pinokio push <message> [<arg>, <arg>, ...]
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- `message`: a message to send
|
|
193
|
+
- `<arg>`: script flags
|
|
194
|
+
- `--title`: (optional) push notification title
|
|
195
|
+
- `--subtitle`: (optional) push notification subtitle
|
|
196
|
+
- `--image`: (optional) custom image path (can be both relative and absolute paths)
|
|
197
|
+
- `--sound`: (optional) true|false (default is false)
|
|
198
|
+
- `--wait`: (optional) wait for 5 seconds
|
|
199
|
+
- `--timeout`: (optional) wait for N seconds
|
|
200
|
+
|
|
201
|
+
### examples
|
|
202
|
+
|
|
203
|
+
#### send a simple notification
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
pinokio push 'hello world'
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### notification with sound
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
pinokio push 'this is a notification' --sound
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### notification with an image
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
pinokio push 'this is an image notification' --image=icon.png
|
|
219
|
+
```
|
|
220
|
+
|
package/icon.png
ADDED
|
Binary file
|
package/index.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const yargs = require('yargs/yargs')
|
|
4
|
+
const { hideBin } = require('yargs/helpers')
|
|
5
|
+
const Script = require('./script')
|
|
6
|
+
const Util = require('./util')
|
|
7
|
+
const argv = yargs(hideBin(process.argv)).parse();
|
|
8
|
+
const script = new Script();
|
|
9
|
+
const util = new Util();
|
|
10
|
+
(async () => {
|
|
11
|
+
if (argv._.length > 0) {
|
|
12
|
+
let cmd = argv._[0].toLowerCase()
|
|
13
|
+
if (cmd === "push") {
|
|
14
|
+
let response = await util.push(argv)
|
|
15
|
+
} else if (cmd === "version") {
|
|
16
|
+
console.log("v" + require('./package.json').version)
|
|
17
|
+
} else if (cmd === "filepicker") {
|
|
18
|
+
await util.filepicker(argv)
|
|
19
|
+
} else if (cmd === "download") {
|
|
20
|
+
await util.download(argv)
|
|
21
|
+
} else if (cmd === "stop") {
|
|
22
|
+
await script.stop(argv)
|
|
23
|
+
} else if (cmd === "start") {
|
|
24
|
+
if (argv._.length > 1) {
|
|
25
|
+
let uri = argv._[1]
|
|
26
|
+
await script.start(uri, true)
|
|
27
|
+
} else {
|
|
28
|
+
console.error("required argument: <uri>")
|
|
29
|
+
}
|
|
30
|
+
} else if (cmd === "run") {
|
|
31
|
+
if (argv._.length > 1) {
|
|
32
|
+
let _uri = argv._[1]
|
|
33
|
+
const uri = path.resolve(process.cwd(), _uri)
|
|
34
|
+
// try downloading first
|
|
35
|
+
if (path.isAbsolute(uri)) {
|
|
36
|
+
} else {
|
|
37
|
+
// url
|
|
38
|
+
await util.download(argv)
|
|
39
|
+
}
|
|
40
|
+
while(true) {
|
|
41
|
+
let default_uri = await script.default_script(uri)
|
|
42
|
+
if (default_uri) {
|
|
43
|
+
if (path.isAbsolute(default_uri)) {
|
|
44
|
+
await new Promise((resolve, reject) => {
|
|
45
|
+
script.start(default_uri, false, (packet) => {
|
|
46
|
+
if (packet.type === "result") {
|
|
47
|
+
resolve()
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
if (script.killed) {
|
|
52
|
+
break
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
// open in browser
|
|
56
|
+
let response = await util.open_url(default_uri)
|
|
57
|
+
console.log({ response })
|
|
58
|
+
break
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
break
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (script.killed) {
|
|
65
|
+
process.exit()
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
console.error("required argument: <uri>")
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pterm",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"pinokio": "./index.js"
|
|
8
|
+
},
|
|
6
9
|
"scripts": {
|
|
7
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
11
|
},
|
|
9
12
|
"author": "",
|
|
10
|
-
"license": "ISC"
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"axios": "^1.10.0",
|
|
16
|
+
"unws": "^0.3.0",
|
|
17
|
+
"yargs": "^17.7.2"
|
|
18
|
+
}
|
|
11
19
|
}
|
package/rpc.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const { WebSocket } = require('unws')
|
|
2
|
+
class RPC {
|
|
3
|
+
constructor(url) {
|
|
4
|
+
this.url = url
|
|
5
|
+
}
|
|
6
|
+
async status(rpc) {
|
|
7
|
+
let res = await new Promise((resolve, reject) => {
|
|
8
|
+
this.run({
|
|
9
|
+
status: true,
|
|
10
|
+
...rpc
|
|
11
|
+
}, (stream) => {
|
|
12
|
+
resolve(stream.data)
|
|
13
|
+
this.ws.close()
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
return res
|
|
17
|
+
}
|
|
18
|
+
close() {
|
|
19
|
+
this.ws.close()
|
|
20
|
+
}
|
|
21
|
+
stop(rpc) {
|
|
22
|
+
this.run({
|
|
23
|
+
stop: true,
|
|
24
|
+
...rpc
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
run (rpc, ondata) {
|
|
28
|
+
// use fetch
|
|
29
|
+
/*
|
|
30
|
+
FormData := [
|
|
31
|
+
types_array: ['number', 'boolean']
|
|
32
|
+
]
|
|
33
|
+
body := {
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
*/
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
if (this.ws) {
|
|
39
|
+
this.ws.send(JSON.stringify(rpc))
|
|
40
|
+
} else {
|
|
41
|
+
this.ws = new WebSocket(this.url)
|
|
42
|
+
this.ws.addEventListener('open', () => {
|
|
43
|
+
this.ws.send(JSON.stringify(rpc))
|
|
44
|
+
});
|
|
45
|
+
this.ws.addEventListener('message', (message) => {
|
|
46
|
+
/******************************************************************************
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
******************************************************************************/
|
|
50
|
+
if (ondata) {
|
|
51
|
+
const packet = JSON.parse(message.data);
|
|
52
|
+
ondata(packet)
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
this.ws.addEventListener('close', () => {
|
|
56
|
+
// console.log('Disconnected from WebSocket endpoint', { error: this.error, result: this.result });
|
|
57
|
+
delete this.ws
|
|
58
|
+
resolve()
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
respond(response) {
|
|
64
|
+
if (this.ws) {
|
|
65
|
+
this.ws.send(JSON.stringify(response))
|
|
66
|
+
} else {
|
|
67
|
+
throw new Error("socket not connected")
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
module.exports = RPC
|
package/script.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const RPC = require('./rpc')
|
|
3
|
+
class Script {
|
|
4
|
+
listen(onKey) {
|
|
5
|
+
process.stdin.setRawMode(true);
|
|
6
|
+
process.stdin.resume();
|
|
7
|
+
process.stdin.setEncoding('utf8');
|
|
8
|
+
|
|
9
|
+
const handler = (key) => {
|
|
10
|
+
onKey(key);
|
|
11
|
+
|
|
12
|
+
// Optional: handle Ctrl+C (SIGINT)
|
|
13
|
+
if (key === '\u0003') { // Ctrl+C
|
|
14
|
+
cleanup();
|
|
15
|
+
process.exit();
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const cleanup = () => {
|
|
20
|
+
process.stdin.setRawMode(false);
|
|
21
|
+
process.stdin.pause();
|
|
22
|
+
process.stdin.off('data', handler);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
process.stdin.on('data', handler);
|
|
26
|
+
|
|
27
|
+
return cleanup; // call this to stop listening
|
|
28
|
+
}
|
|
29
|
+
async default_script (uri) {
|
|
30
|
+
const rpc = new RPC("ws://localhost:42000")
|
|
31
|
+
const stop = () => {
|
|
32
|
+
rpc.run({
|
|
33
|
+
method: "kernel.api.stop",
|
|
34
|
+
params: { uri }
|
|
35
|
+
}, (packet) => {
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
process.on("SIGINT", () => {
|
|
39
|
+
stop()
|
|
40
|
+
});
|
|
41
|
+
process.on("SIGTERM", () => {
|
|
42
|
+
stop()
|
|
43
|
+
});
|
|
44
|
+
process.on("beforeExit", (code) => {
|
|
45
|
+
stop()
|
|
46
|
+
});
|
|
47
|
+
process.on("exit", (code) => {
|
|
48
|
+
stop()
|
|
49
|
+
});
|
|
50
|
+
let default_uri = await new Promise((resolve, reject) => {
|
|
51
|
+
rpc.run({ uri, mode: "open" }, (packet) => {
|
|
52
|
+
if (packet.data && packet.data.uri) {
|
|
53
|
+
// start
|
|
54
|
+
//rpc.stop({ uri })
|
|
55
|
+
stop()
|
|
56
|
+
resolve(packet.data.uri)
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
return default_uri
|
|
61
|
+
}
|
|
62
|
+
async stop(argv) {
|
|
63
|
+
if (argv._.length > 1) {
|
|
64
|
+
let _uri = argv._[1]
|
|
65
|
+
const uri = path.resolve(process.cwd(), _uri)
|
|
66
|
+
const rpc = new RPC("ws://localhost:42000")
|
|
67
|
+
rpc.run({
|
|
68
|
+
method: "kernel.api.stop",
|
|
69
|
+
params: { uri }
|
|
70
|
+
}, (packet) => {
|
|
71
|
+
process.exit()
|
|
72
|
+
})
|
|
73
|
+
} else {
|
|
74
|
+
console.error("required argument: <uri>")
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async start(_uri, kill, ondata) {
|
|
78
|
+
const cols = process.stdout.columns;
|
|
79
|
+
const rows = process.stdout.rows;
|
|
80
|
+
const rpc = new RPC("ws://localhost:42000")
|
|
81
|
+
|
|
82
|
+
const uri = path.resolve(process.cwd(), _uri)
|
|
83
|
+
|
|
84
|
+
const stop = () => {
|
|
85
|
+
this.killed = true
|
|
86
|
+
rpc.run({
|
|
87
|
+
method: "kernel.api.stop",
|
|
88
|
+
params: { uri },
|
|
89
|
+
}, (packet) => {
|
|
90
|
+
rpc.stop({ uri })
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
process.on("SIGINT", () => {
|
|
94
|
+
stop()
|
|
95
|
+
});
|
|
96
|
+
process.on("SIGTERM", () => {
|
|
97
|
+
stop()
|
|
98
|
+
});
|
|
99
|
+
process.on("beforeExit", (code) => {
|
|
100
|
+
stop()
|
|
101
|
+
});
|
|
102
|
+
process.on("exit", (code) => {
|
|
103
|
+
stop()
|
|
104
|
+
});
|
|
105
|
+
this.key_stop = this.listen((key) => {
|
|
106
|
+
if (key.length >= 256) {
|
|
107
|
+
rpc.run({
|
|
108
|
+
id: this.shell_id,
|
|
109
|
+
paste: true,
|
|
110
|
+
key: key
|
|
111
|
+
})
|
|
112
|
+
} else {
|
|
113
|
+
rpc.run({
|
|
114
|
+
id: this.shell_id,
|
|
115
|
+
key: key
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
process.stdout.on('resize', () => {
|
|
120
|
+
const cols = process.stdout.columns;
|
|
121
|
+
const rows = process.stdout.rows;
|
|
122
|
+
rpc.run({
|
|
123
|
+
id: this.shell_id,
|
|
124
|
+
resize: {
|
|
125
|
+
cols,
|
|
126
|
+
rows,
|
|
127
|
+
}
|
|
128
|
+
}, (packet) => {
|
|
129
|
+
})
|
|
130
|
+
});
|
|
131
|
+
await rpc.run({
|
|
132
|
+
uri,
|
|
133
|
+
client: {
|
|
134
|
+
cols,
|
|
135
|
+
rows,
|
|
136
|
+
}
|
|
137
|
+
}, (packet) => {
|
|
138
|
+
if (packet.type === "stop") {
|
|
139
|
+
rpc.stop({ uri })
|
|
140
|
+
if (kill) {
|
|
141
|
+
this.key_stop()
|
|
142
|
+
process.exit()
|
|
143
|
+
}
|
|
144
|
+
} else if (packet.type === "disconnect") {
|
|
145
|
+
rpc.close()
|
|
146
|
+
if (kill) {
|
|
147
|
+
this.key_stop()
|
|
148
|
+
process.exit()
|
|
149
|
+
}
|
|
150
|
+
} else if (packet.type === "stream") {
|
|
151
|
+
if (packet.data.id) {
|
|
152
|
+
this.shell_id = packet.data.id
|
|
153
|
+
}
|
|
154
|
+
process.stdout.write(packet.data.raw)
|
|
155
|
+
}
|
|
156
|
+
if (ondata) {
|
|
157
|
+
ondata(packet)
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
module.exports = Script
|
package/util.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const os = require('os')
|
|
2
|
+
const axios = require('axios')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const RPC = require('./rpc')
|
|
5
|
+
class Util {
|
|
6
|
+
async filepicker(argv) {
|
|
7
|
+
const rpc = new RPC("ws://localhost:42000")
|
|
8
|
+
if (argv.path) {
|
|
9
|
+
argv.path = path.resolve(process.cwd(), argv.path)
|
|
10
|
+
}
|
|
11
|
+
await rpc.run({
|
|
12
|
+
method: "kernel.bin.filepicker",
|
|
13
|
+
params: argv
|
|
14
|
+
}, (packet) => {
|
|
15
|
+
if (packet.type === "result") {
|
|
16
|
+
rpc.close()
|
|
17
|
+
if (packet.data.paths.length > 0) {
|
|
18
|
+
for(let p of packet.data.paths) {
|
|
19
|
+
process.stdout.write(p)
|
|
20
|
+
process.stdout.write("\n")
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
} else if (packet.type === "stream") {
|
|
24
|
+
// process.stdout.write(packet.data.raw)
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
async push(argv) {
|
|
29
|
+
if (argv._ && argv._.length > 1 && !argv.message) {
|
|
30
|
+
argv.message = argv._[1]
|
|
31
|
+
}
|
|
32
|
+
if (argv.image && !path.isAbsolute(argv.image)) {
|
|
33
|
+
argv.image = path.resolve(process.cwd(), argv.image)
|
|
34
|
+
}
|
|
35
|
+
let response = await axios.post("http://localhost:42000/push", argv)
|
|
36
|
+
return response
|
|
37
|
+
}
|
|
38
|
+
async open_url(url) {
|
|
39
|
+
let response = await axios.post("http://localhost:42000/go", { url })
|
|
40
|
+
return response
|
|
41
|
+
}
|
|
42
|
+
async download(argv) {
|
|
43
|
+
if (argv._.length > 1) {
|
|
44
|
+
let uri = argv._[1]
|
|
45
|
+
const rpc = new RPC("ws://localhost:42000")
|
|
46
|
+
await rpc.run({
|
|
47
|
+
method: "kernel.bin.install2",
|
|
48
|
+
params: {}
|
|
49
|
+
}, (packet) => {
|
|
50
|
+
if (packet.type === "result") {
|
|
51
|
+
rpc.close()
|
|
52
|
+
} else if (packet.type === "stream") {
|
|
53
|
+
process.stdout.write(packet.data.raw)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
if (!uri.endsWith(".git")) {
|
|
57
|
+
uri = uri + ".git"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let exists;
|
|
61
|
+
await rpc.run({
|
|
62
|
+
method: "kernel.bin.path_exists",
|
|
63
|
+
params: { uri }
|
|
64
|
+
}, (packet) => {
|
|
65
|
+
if (packet.type === "result") {
|
|
66
|
+
exists = packet.data
|
|
67
|
+
rpc.close()
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
if (!exists) {
|
|
72
|
+
let message = `git clone ${uri}`
|
|
73
|
+
let name = new URL(uri).pathname.split("/").pop()
|
|
74
|
+
if (argv._.length > 2) {
|
|
75
|
+
name = argv._[2]
|
|
76
|
+
message = `git clone ${uri} ${name}`
|
|
77
|
+
}
|
|
78
|
+
if (argv.b) {
|
|
79
|
+
let branch = argv.b
|
|
80
|
+
message += ` -b ${branch}`
|
|
81
|
+
}
|
|
82
|
+
await rpc.run({
|
|
83
|
+
method: "shell.run",
|
|
84
|
+
params: { message, path: "~/api" }
|
|
85
|
+
}, (packet) => {
|
|
86
|
+
if (packet.type === "result") {
|
|
87
|
+
rpc.close()
|
|
88
|
+
} else if (packet.type === "stream") {
|
|
89
|
+
process.stdout.write(packet.data.raw)
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
process.exit()
|
|
94
|
+
} else {
|
|
95
|
+
console.error("required argument: <uri>")
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
module.exports = Util
|