-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #42 from w3c/install-commands
Add install and uninstall subcommands
- Loading branch information
Showing
9 changed files
with
177 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,22 @@ | ||
'use strict'; | ||
|
||
const fs = require('fs/promises'); | ||
|
||
const yargs = require('yargs/yargs'); | ||
const { hideBin } = require('yargs/helpers'); | ||
|
||
const createCommandServer = require('./create-command-server'); | ||
const createVoiceServer = require('./create-voice-server'); | ||
const WINDOWS_NAMED_PIPE = '\\\\?\\pipe\\my_pipe'; | ||
const MACOS_SYSTEM_DIR = '/usr/local/var/at_driver_generic'; | ||
const MACOS_SOCKET_UNIX_PATH = '/usr/local/var/at_driver_generic/driver.socket'; | ||
const DEFAULT_PORT = 4382; | ||
const installCommand = require('./commands/install'); | ||
const serveCommand = require('./commands/serve'); | ||
const uninstallCommand = require('./commands/uninstall'); | ||
|
||
/** | ||
* Print logging information to the process's standard error stream, annotated | ||
* with a timestamp describing the moment that the message was emitted. | ||
* @param {import('process')} process | ||
*/ | ||
const log = (...args) => console.error(new Date().toISOString(), ...args); | ||
|
||
module.exports = async process => { | ||
const argv = await yargs(hideBin(process.argv)) | ||
.option('port', { | ||
coerce(string) { | ||
if (!/^(0|[1-9][0-9]*)$/.test(string)) { | ||
throw new TypeError( | ||
`"port" option: expected a non-negative integer value but received "${string}"`, | ||
); | ||
} | ||
return Number(string); | ||
}, | ||
default: DEFAULT_PORT, | ||
describe: 'TCP port on which to listen for WebSocket connections', | ||
// Do not use the `number` type provided by `yargs` because it tolerates | ||
// JavaScript numeric literal forms which are likely typos in this | ||
// context (e.g. `0xf` or `1e-0`). | ||
type: 'string', | ||
requiresArg: true, | ||
}) | ||
await yargs(hideBin(process.argv)) | ||
.command(installCommand) | ||
.command(uninstallCommand) | ||
.command(serveCommand) | ||
.demandCommand(1, 1) | ||
.strict() | ||
.help() | ||
.parse(); | ||
|
||
const socketPath = await prepareSocketPath(); | ||
|
||
const [commandServer, voiceServer] = await Promise.all([ | ||
createCommandServer(argv.port), | ||
createVoiceServer(socketPath), | ||
]); | ||
|
||
log(`listening on port ${argv.port}`); | ||
|
||
commandServer.on('error', error => { | ||
log(`error: ${error}`); | ||
}); | ||
|
||
voiceServer.on('message', message => { | ||
log(`voice server received message ${JSON.stringify(message)}`); | ||
if (message.name == 'speech') { | ||
commandServer.broadcast({ | ||
method: 'interaction.capturedOutput', | ||
params: { data: message.data }, | ||
}); | ||
} | ||
}); | ||
|
||
voiceServer.on('error', error => { | ||
log(`error: ${error}`); | ||
}); | ||
}; | ||
|
||
const prepareSocketPath = async () => { | ||
if (process.platform === 'win32') { | ||
return WINDOWS_NAMED_PIPE; | ||
} else if (process.platform === 'darwin') { | ||
await fs.mkdir(MACOS_SYSTEM_DIR, { recursive: true }); | ||
await fs.unlink(MACOS_SOCKET_UNIX_PATH).catch(error => { | ||
if (!error || error.code !== 'ENOENT') { | ||
throw error; | ||
} | ||
}); | ||
return MACOS_SOCKET_UNIX_PATH; | ||
} | ||
throw new Error(`unsupported host platform '${process.platform}'`); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use strict'; | ||
|
||
const { loadOsModule } = require('../helpers/load-os-module'); | ||
|
||
module.exports = /** @type {import('yargs').CommandModule} */ ({ | ||
command: 'install', | ||
describe: 'Install text to speech extension and other support', | ||
async handler() { | ||
const installDelegate = loadOsModule('install', { | ||
darwin: () => require('../install/macos'), | ||
win32: () => require('../install/win32'), | ||
}); | ||
await installDelegate.install(); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
'use strict'; | ||
|
||
const fs = require('fs/promises'); | ||
|
||
const createCommandServer = require('../create-command-server'); | ||
const createVoiceServer = require('../create-voice-server'); | ||
|
||
const WINDOWS_NAMED_PIPE = '\\\\?\\pipe\\my_pipe'; | ||
const MACOS_SYSTEM_DIR = '/usr/local/var/at_driver_generic'; | ||
const MACOS_SOCKET_UNIX_PATH = '/usr/local/var/at_driver_generic/driver.socket'; | ||
const DEFAULT_PORT = 4382; | ||
|
||
|
||
/** | ||
* Print logging information to the process's standard error stream, annotated | ||
* with a timestamp describing the moment that the message was emitted. | ||
*/ | ||
const log = (...args) => console.error(new Date().toISOString(), ...args); | ||
|
||
const prepareSocketPath = async () => { | ||
if (process.platform === 'win32') { | ||
return WINDOWS_NAMED_PIPE; | ||
} else if (process.platform === 'darwin') { | ||
await fs.mkdir(MACOS_SYSTEM_DIR, { recursive: true }); | ||
await fs.unlink(MACOS_SOCKET_UNIX_PATH).catch(error => { | ||
if (!error || error.code !== 'ENOENT') { | ||
throw error; | ||
} | ||
}); | ||
return MACOS_SOCKET_UNIX_PATH; | ||
} | ||
throw new Error(`unsupported host platform '${process.platform}'`); | ||
}; | ||
|
||
module.exports = /** @type {import('yargs').CommandModule} */ ({ | ||
command: 'serve', | ||
describe: 'Run at-driver server', | ||
builder(yargs) { | ||
return yargs.option('port', { | ||
coerce(string) { | ||
if (!/^(0|[1-9][0-9]*)$/.test(string)) { | ||
throw new TypeError( | ||
`"port" option: expected a non-negative integer value but received "${string}"`, | ||
); | ||
} | ||
return Number(string); | ||
}, | ||
default: DEFAULT_PORT, | ||
describe: 'TCP port on which to listen for WebSocket connections', | ||
// Do not use the `number` type provided by `yargs` because it tolerates | ||
// JavaScript numeric literal forms which are likely typos in this | ||
// context (e.g. `0xf` or `1e-0`). | ||
type: 'string', | ||
requiresArg: true, | ||
}); | ||
}, | ||
async handler(argv) { | ||
const socketPath = await prepareSocketPath(); | ||
|
||
const [commandServer, voiceServer] = await Promise.all([ | ||
createCommandServer(argv.port), | ||
createVoiceServer(socketPath), | ||
]); | ||
|
||
log(`listening on port ${argv.port}`); | ||
|
||
commandServer.on('error', error => { | ||
log(`error: ${error}`); | ||
}); | ||
|
||
voiceServer.on('message', message => { | ||
log(`voice server received message ${JSON.stringify(message)}`); | ||
if (message.name == 'speech') { | ||
commandServer.broadcast({ | ||
method: 'interaction.capturedOutput', | ||
params: { data: message.data }, | ||
}); | ||
} | ||
}); | ||
|
||
voiceServer.on('error', error => { | ||
log(`error: ${error}`); | ||
}); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use strict'; | ||
|
||
const { loadOsModule } = require('../helpers/load-os-module'); | ||
|
||
module.exports = /** @type {import('yargs').CommandModule} */ ({ | ||
command: 'uninstall', | ||
describe: 'Uninstall text to speech extension and other support', | ||
async handler() { | ||
const installDelegate = loadOsModule('install', { | ||
darwin: () => require('../install/macos'), | ||
win32: () => require('../install/win32'), | ||
}); | ||
await installDelegate.uninstall(); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
'use strict'; | ||
|
||
exports.install = async function() { | ||
throw new Error('macos install not implemented'); | ||
}; | ||
|
||
exports.uninstall = async function() { | ||
throw new Error('macos uninstall not implemented'); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
'use strict'; | ||
|
||
const { exec: _exec } = require('child_process'); | ||
const { resolve } = require('path'); | ||
const { promisify } = require('util'); | ||
|
||
const exec = promisify(_exec); | ||
|
||
const MAKE_VOICE_EXE = 'MakeVoice.exe'; | ||
|
||
exports.install = async function () { | ||
await exec(`${MAKE_VOICE_EXE}`, await getExecOptions()); | ||
}; | ||
|
||
exports.uninstall = async function () { | ||
await exec(`${MAKE_VOICE_EXE} /u`, await getExecOptions()); | ||
}; | ||
|
||
/** | ||
* @returns {Promise<import('child_process').ExecOptions>} | ||
*/ | ||
async function getExecOptions() { | ||
return { | ||
cwd: resolve(__dirname, '../../Release'), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters