-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
121 lines (99 loc) · 2.3 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { spawn } from "node-pty"
import { EventEmitter } from "events"
export function terminal(...argv) {
let options = setupOptions(...argv)
let {
args,
command,
cols, rows,
cwd,
env,
epoch,
onData,
record,
session,
silent,
stdin
} = options
let pty = spawn(command, args, {
cols, cwd, env, name: "xterm-color", rows
})
pty.on("close", data => {
if (stdin) teardownStdin(pty)
})
pty.on("data", data => {
options.out += data
if (onData) {
onData({ out: options.out, pty })
}
writeSession({ data, epoch, record, session })
if (!silent) process.stdout.write(data)
})
if (stdin) setupStdin(pty)
return { pty, options }
}
export async function run(command, args, opts) {
let { pty, options } = terminal(command, args, opts)
return new Promise((resolve, reject) => {
pty.on("exit", (code, signal) =>
resolve({ ...options, code, signal })
)
pty.on("error", e => reject(e))
})
}
export async function replay(session) {
let id, ms = 0
return new Promise(resolve => {
id = setInterval(() => {
if (!session.length) {
clearInterval(id)
resolve()
}
ms += 100
playTime({ ms, session })
}, 100)
})
}
function playTime({ ms, session }) {
if (session[0] && session[0][0] <= ms) {
let data = session.shift()[1]
process.stdout.write(new Buffer(data))
playTime({ ms, session })
}
}
function setupOptions(command, args, opts) {
let epoch = Date.now()
let session = []
if (command && command.constructor.name == "Object") {
opts = command
command = opts.command
args = opts.args
}
if (args && args.constructor.name == "Object") {
opts = args
args = []
}
return {
command: "bash",
cols: 100, rows: 100,
out: "",
record: false,
silent: false,
...opts, command, args, epoch, session
}
}
function setupStdin(pty) {
process.stdin.setEncoding("utf8")
process.stdin.setRawMode(true)
process.stdin.pipe(pty)
}
function teardownStdin(pty) {
process.stdin.unpipe(pty)
process.stdin.setRawMode(false)
}
function writeSession({ data, epoch, record = true, session }) {
if (!record) return
let time = Date.now() - epoch
data = Buffer.from(data, "utf8")
session.push([ time, data ])
}