UNPKG

3.17 kBJavaScriptView Raw
1const cp = require('child_process');
2const EOL = require('os').EOL;
3
4function close(process) {
5 return new Promise((resolve) => {
6 process.on('close', (code, signal) => {
7 resolve(code);
8 });
9 process.stdin.write(`-stay_open${EOL}`);
10 process.stdin.write(`false${EOL}`);
11 });
12}
13
14function writeStdIn(process, data) {
15 // console.log('write stdin', data);
16 process.stdin.write(data);
17 process.stdin.write(EOL);
18}
19
20/**
21 * Write command data to the exiftool's stdin.
22 * @param {ChildProcess} process - exiftool process executed with -stay_open True -@ -
23 * @param {string} command - which command to execute
24 * @param {string} commandNumber - text which will be echoed before and after results
25 * @param {Array} args - any additional arguments
26 */
27function execute(process, command, commandNumber, args) {
28 args = args !== undefined ? args : [];
29 const argsString = args.length ? args.map(arg => `-${arg}`).join(EOL) : '';
30
31 command = command !== undefined ? command : '';
32
33 if (argsString) writeStdIn(process, argsString);
34 writeStdIn(process, '-json');
35 writeStdIn(process, '-s');
36 writeStdIn(process, command);
37 writeStdIn(process, '-echo1');
38 writeStdIn(process, `{begin${commandNumber}}`);
39 writeStdIn(process, '-echo2');
40 writeStdIn(process, `{begin${commandNumber}}`);
41 writeStdIn(process, '-echo4');
42 writeStdIn(process, `{ready${commandNumber}}`);
43 writeStdIn(process, `-execute${commandNumber}`);
44}
45
46function getCommandNumber() {
47 return Math.floor(Math.random() * 1000000);
48}
49
50function createHandler(commandNumber, snitch, cb) {
51 const handler = (data) => {
52 if (data.commandNumber === commandNumber) {
53 snitch.removeListener('data', handler)
54 cb(data.data)
55 }
56 }
57 snitch.on('data', handler)
58}
59
60function executeCommand(process, stdoutSnitch, stderrSnitch, command, args) {
61 const commandNumber = getCommandNumber();
62
63 const dataPromise = new Promise(resolve =>
64 createHandler(commandNumber, stdoutSnitch, resolve)
65 );
66
67 const errPromise = new Promise(resolve =>
68 createHandler(commandNumber, stderrSnitch, resolve)
69 );
70
71 execute(process, command, commandNumber, args);
72
73 return Promise.all([
74 dataPromise,
75 errPromise
76 ])
77 .then(res => ({
78 data: res[0] ? JSON.parse(res[0]) : null,
79 error: res[1] || null,
80 }));
81}
82
83function spawn(bin) {
84 return new Promise((resolve, reject) => {
85 const echoString = Date.now().toString();
86 const process = cp.spawn(bin, ['-echo2', echoString, '-stay_open', 'True', '-@', '-']);
87 process.once('error', reject);
88 const echoHandler = (data) => {
89 const d = data.toString().trim();
90 // listening for echo2 in stderr (echo and echo1 won't work)
91 if (d === echoString) {
92 resolve(process);
93 } else {
94 reject(new Error(`Unexpected string on start: ${d}`))
95 }
96 }
97 process.stderr.once('data', echoHandler);
98 });
99}
100
101module.exports = {
102 spawn,
103 close,
104 executeCommand,
105}