pterm 0.0.23 → 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 +217 -15
- package/endpoint.js +163 -0
- package/index.js +71 -16
- package/package.json +1 -1
- package/rpc.js +26 -8
- package/script.js +114 -59
- package/target.js +437 -0
- package/util.js +197 -17
package/rpc.js
CHANGED
|
@@ -21,7 +21,16 @@ class RPC {
|
|
|
21
21
|
return res
|
|
22
22
|
}
|
|
23
23
|
close() {
|
|
24
|
-
this.ws
|
|
24
|
+
if (!this.ws) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
const ws = this.ws
|
|
28
|
+
delete this.ws
|
|
29
|
+
if (typeof ws.terminate === 'function') {
|
|
30
|
+
ws.terminate()
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
ws.close()
|
|
25
34
|
}
|
|
26
35
|
stop(rpc) {
|
|
27
36
|
this.run({
|
|
@@ -43,23 +52,32 @@ class RPC {
|
|
|
43
52
|
if (this.ws) {
|
|
44
53
|
this.ws.send(JSON.stringify(rpc))
|
|
45
54
|
} else {
|
|
46
|
-
|
|
47
|
-
this.ws
|
|
48
|
-
|
|
55
|
+
const ws = new WebSocket(this.url, this.wsOptions)
|
|
56
|
+
this.ws = ws
|
|
57
|
+
ws.addEventListener('open', () => {
|
|
58
|
+
ws.send(JSON.stringify(rpc))
|
|
49
59
|
});
|
|
50
|
-
|
|
60
|
+
ws.addEventListener('message', (message) => {
|
|
51
61
|
/******************************************************************************
|
|
52
62
|
|
|
53
63
|
|
|
54
64
|
******************************************************************************/
|
|
55
65
|
if (ondata) {
|
|
56
|
-
const
|
|
66
|
+
const rawMessage = message && typeof message === 'object' && typeof message.data !== 'undefined'
|
|
67
|
+
? message.data
|
|
68
|
+
: message
|
|
69
|
+
const packetSource = Buffer.isBuffer(rawMessage)
|
|
70
|
+
? rawMessage.toString('utf8')
|
|
71
|
+
: String(rawMessage)
|
|
72
|
+
const packet = JSON.parse(packetSource);
|
|
57
73
|
ondata(packet)
|
|
58
74
|
}
|
|
59
75
|
});
|
|
60
|
-
|
|
76
|
+
ws.addEventListener('close', () => {
|
|
61
77
|
// console.log('Disconnected from WebSocket endpoint', { error: this.error, result: this.result });
|
|
62
|
-
|
|
78
|
+
if (this.ws === ws) {
|
|
79
|
+
delete this.ws
|
|
80
|
+
}
|
|
63
81
|
resolve()
|
|
64
82
|
});
|
|
65
83
|
}
|
package/script.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
const os = require('os')
|
|
1
2
|
const path = require('path')
|
|
2
3
|
const RPC = require('./rpc')
|
|
4
|
+
const { resolveWsBaseUrl } = require('./endpoint')
|
|
5
|
+
const { resolveAppControlTarget, resolveStopTarget } = require('./target')
|
|
3
6
|
class Script {
|
|
4
7
|
listen(onKey) {
|
|
5
8
|
if (process.stdin.isTTY) {
|
|
@@ -42,33 +45,46 @@ class Script {
|
|
|
42
45
|
input[key] = value
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
|
-
|
|
48
|
+
const parseTargetUri = (rawUri) => {
|
|
49
|
+
let uri = rawUri
|
|
50
|
+
let input
|
|
51
|
+
if (!/^https?:\/\//i.test(uri)) {
|
|
52
|
+
let queryIndex = uri.indexOf("?")
|
|
53
|
+
if (queryIndex >= 0) {
|
|
54
|
+
input = {}
|
|
55
|
+
let params = new URLSearchParams(uri.slice(queryIndex + 1))
|
|
56
|
+
for (let [key, value] of params.entries()) {
|
|
57
|
+
appendInputValue(input, key, value)
|
|
58
|
+
}
|
|
59
|
+
uri = uri.slice(0, queryIndex)
|
|
60
|
+
}
|
|
61
|
+
if (uri.startsWith('~/')) {
|
|
62
|
+
uri = path.resolve(os.homedir(), uri.slice(2))
|
|
63
|
+
} else {
|
|
64
|
+
uri = path.resolve(process.cwd(), uri)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
46
67
|
return {
|
|
47
|
-
uri
|
|
48
|
-
input
|
|
68
|
+
uri,
|
|
69
|
+
input
|
|
49
70
|
}
|
|
50
71
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
uri = uri.slice(0, queryIndex)
|
|
72
|
+
if (target && typeof target === "object" && typeof target.uri === "string") {
|
|
73
|
+
const normalized = parseTargetUri(target.uri)
|
|
74
|
+
return {
|
|
75
|
+
uri: normalized.uri,
|
|
76
|
+
input: normalized.input
|
|
77
|
+
? {
|
|
78
|
+
...(target.input && typeof target.input === "object" ? target.input : {}),
|
|
79
|
+
...normalized.input
|
|
80
|
+
}
|
|
81
|
+
: (target.input && typeof target.input === "object" ? target.input : undefined)
|
|
62
82
|
}
|
|
63
|
-
uri = path.resolve(process.cwd(), uri)
|
|
64
|
-
}
|
|
65
|
-
return {
|
|
66
|
-
uri,
|
|
67
|
-
input
|
|
68
83
|
}
|
|
84
|
+
return parseTargetUri(target)
|
|
69
85
|
}
|
|
70
|
-
async default_script (uri, defaultSelectors) {
|
|
71
|
-
const rpc = new RPC(
|
|
86
|
+
async default_script (uri, defaultSelectors, targetControlPlane) {
|
|
87
|
+
const rpc = new RPC(await resolveWsBaseUrl(targetControlPlane))
|
|
72
88
|
const stop = () => {
|
|
73
89
|
rpc.run({
|
|
74
90
|
method: "kernel.api.stop",
|
|
@@ -98,14 +114,17 @@ class Script {
|
|
|
98
114
|
source: "pterm"
|
|
99
115
|
}
|
|
100
116
|
}, (packet) => {
|
|
101
|
-
if (packet
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
if (packet && packet.data) {
|
|
118
|
+
rpc.close()
|
|
119
|
+
if (packet.data.uri) {
|
|
120
|
+
stop()
|
|
121
|
+
resolve({
|
|
122
|
+
uri: packet.data.uri,
|
|
123
|
+
input: packet.data.input
|
|
124
|
+
})
|
|
125
|
+
} else {
|
|
126
|
+
resolve(null)
|
|
127
|
+
}
|
|
109
128
|
}
|
|
110
129
|
})
|
|
111
130
|
})
|
|
@@ -114,22 +133,42 @@ class Script {
|
|
|
114
133
|
async stop(argv) {
|
|
115
134
|
if (argv._.length > 1) {
|
|
116
135
|
let _uri = argv._[1]
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
136
|
+
const target = await resolveStopTarget(_uri, argv.ref)
|
|
137
|
+
if (!target.uris.length) {
|
|
138
|
+
process.exit(0)
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
for (const uri of target.uris) {
|
|
142
|
+
const rpc = new RPC(await resolveWsBaseUrl(target.controlPlane))
|
|
143
|
+
await new Promise((resolve) => {
|
|
144
|
+
let settled = false
|
|
145
|
+
const finish = () => {
|
|
146
|
+
if (settled) {
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
settled = true
|
|
150
|
+
rpc.close()
|
|
151
|
+
resolve()
|
|
152
|
+
}
|
|
153
|
+
const timer = setTimeout(finish, 800)
|
|
154
|
+
rpc.run({
|
|
155
|
+
method: "kernel.api.stop",
|
|
156
|
+
params: { uri }
|
|
157
|
+
}, () => {
|
|
158
|
+
clearTimeout(timer)
|
|
159
|
+
finish()
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
process.exit(0)
|
|
125
164
|
} else {
|
|
126
165
|
console.error("required argument: <uri>")
|
|
127
166
|
}
|
|
128
167
|
}
|
|
129
|
-
async start(_uri, kill, ondata) {
|
|
168
|
+
async start(_uri, kill, ondata, targetControlPlane) {
|
|
130
169
|
const cols = process.stdout.columns;
|
|
131
170
|
const rows = process.stdout.rows;
|
|
132
|
-
const rpc = new RPC(
|
|
171
|
+
const rpc = new RPC(await resolveWsBaseUrl(targetControlPlane))
|
|
133
172
|
|
|
134
173
|
const target = this.normalizeTarget(_uri)
|
|
135
174
|
const uri = target.uri
|
|
@@ -143,18 +182,22 @@ class Script {
|
|
|
143
182
|
rpc.stop({ uri })
|
|
144
183
|
})
|
|
145
184
|
}
|
|
146
|
-
|
|
185
|
+
const onSigInt = () => {
|
|
147
186
|
stop()
|
|
148
|
-
}
|
|
149
|
-
|
|
187
|
+
}
|
|
188
|
+
const onSigTerm = () => {
|
|
150
189
|
stop()
|
|
151
|
-
}
|
|
152
|
-
|
|
190
|
+
}
|
|
191
|
+
const onBeforeExit = () => {
|
|
153
192
|
stop()
|
|
154
|
-
}
|
|
155
|
-
|
|
193
|
+
}
|
|
194
|
+
const onExit = () => {
|
|
156
195
|
stop()
|
|
157
|
-
}
|
|
196
|
+
}
|
|
197
|
+
process.on("SIGINT", onSigInt);
|
|
198
|
+
process.on("SIGTERM", onSigTerm);
|
|
199
|
+
process.on("beforeExit", onBeforeExit);
|
|
200
|
+
process.on("exit", onExit);
|
|
158
201
|
this.key_stop = this.listen((key) => {
|
|
159
202
|
if (key.length >= 256) {
|
|
160
203
|
rpc.run({
|
|
@@ -169,7 +212,7 @@ class Script {
|
|
|
169
212
|
})
|
|
170
213
|
}
|
|
171
214
|
});
|
|
172
|
-
|
|
215
|
+
const resizeHandler = () => {
|
|
173
216
|
const cols = process.stdout.columns;
|
|
174
217
|
const rows = process.stdout.rows;
|
|
175
218
|
rpc.run({
|
|
@@ -180,7 +223,8 @@ class Script {
|
|
|
180
223
|
}
|
|
181
224
|
}, (packet) => {
|
|
182
225
|
})
|
|
183
|
-
}
|
|
226
|
+
}
|
|
227
|
+
process.stdout.on('resize', resizeHandler);
|
|
184
228
|
let payload = {
|
|
185
229
|
uri,
|
|
186
230
|
source: "pterm",
|
|
@@ -193,19 +237,30 @@ class Script {
|
|
|
193
237
|
if (target.input && Object.keys(target.input).length > 0) {
|
|
194
238
|
payload.input = target.input
|
|
195
239
|
}
|
|
240
|
+
let cleanedUp = false
|
|
241
|
+
const cleanupLocalSession = () => {
|
|
242
|
+
if (cleanedUp) {
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
cleanedUp = true
|
|
246
|
+
if (this.key_stop) {
|
|
247
|
+
this.key_stop()
|
|
248
|
+
this.key_stop = null
|
|
249
|
+
}
|
|
250
|
+
process.stdout.off('resize', resizeHandler)
|
|
251
|
+
process.off("SIGINT", onSigInt)
|
|
252
|
+
process.off("SIGTERM", onSigTerm)
|
|
253
|
+
process.off("beforeExit", onBeforeExit)
|
|
254
|
+
process.off("exit", onExit)
|
|
255
|
+
rpc.close()
|
|
256
|
+
}
|
|
196
257
|
await rpc.run(payload, (packet) => {
|
|
197
258
|
if (packet.type === "stop") {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
this.key_stop()
|
|
201
|
-
process.exit()
|
|
202
|
-
}
|
|
259
|
+
cleanupLocalSession()
|
|
260
|
+
process.exit(0)
|
|
203
261
|
} else if (packet.type === "disconnect") {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
this.key_stop()
|
|
207
|
-
process.exit()
|
|
208
|
-
}
|
|
262
|
+
cleanupLocalSession()
|
|
263
|
+
process.exit(0)
|
|
209
264
|
} else if (packet.type === "stream") {
|
|
210
265
|
if (packet.data.id) {
|
|
211
266
|
this.shell_id = packet.data.id
|