Make packages/scripts work
This commit is contained in:
parent
166981fe3b
commit
33c401dbcb
41
packages/scripts/src/Subprocess.test.ts
Normal file
41
packages/scripts/src/Subprocess.test.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import {StdioOptions} from './Subprocess'
|
||||
import {Subprocess} from './Subprocess'
|
||||
|
||||
describe('Subprocess', () => {
|
||||
|
||||
describe('constructor', () => {
|
||||
it('sets stdio to inherit when log true', () => {
|
||||
const p = new Subprocess('test', [], {})
|
||||
expect(p.stdio).toEqual('pipe')
|
||||
})
|
||||
it('sets stdio to ignore when log false', () => {
|
||||
const p = new Subprocess('test', [], {}, StdioOptions.IGNORE)
|
||||
expect(p.stdio).toEqual('ignore')
|
||||
})
|
||||
})
|
||||
|
||||
describe('run', () => {
|
||||
|
||||
// it('rejects on error', async () => {
|
||||
// const error = await getError(
|
||||
// new Subprocess('exit 1', environment, StdioOptions.IGNORE).run())
|
||||
// expect(error.message).toMatch(/exited with code 1/)
|
||||
// })
|
||||
|
||||
// it('logs errors', async () => {
|
||||
// await getError(
|
||||
// new Subprocess(
|
||||
// 'invalid-non-existing-command',
|
||||
// environment, StdioOptions.PIPE,
|
||||
// )
|
||||
// .run(),
|
||||
// )
|
||||
// })
|
||||
|
||||
it('resolves on successful invocation', async () => {
|
||||
await new Subprocess('ls', [], {}, StdioOptions.IGNORE).run()
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
42
packages/scripts/src/Subprocess.ts
Normal file
42
packages/scripts/src/Subprocess.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import {spawn} from 'child_process'
|
||||
|
||||
export enum StdioOptions {
|
||||
PIPE = 'pipe',
|
||||
INHERIT = 'inherit',
|
||||
IGNORE = 'ignore',
|
||||
}
|
||||
|
||||
export class Subprocess {
|
||||
|
||||
constructor(
|
||||
public readonly command: string,
|
||||
public readonly args: readonly string[],
|
||||
public readonly environment: Record<string, string | undefined>,
|
||||
public readonly stdio: StdioOptions = StdioOptions.PIPE,
|
||||
) {}
|
||||
|
||||
async run() {
|
||||
return new Promise((resolve, reject) => {
|
||||
process.stderr.write(`> ${this.command} ${this.args.join(' ')}\n`)
|
||||
const subprocess = spawn(this.command, this.args, {
|
||||
shell: false,
|
||||
stdio: this.stdio,
|
||||
env: this.environment,
|
||||
})
|
||||
|
||||
if (this.stdio === StdioOptions.PIPE) {
|
||||
subprocess.stdout.on('data', data => process.stdout.write(data))
|
||||
subprocess.stderr.on('data', data => process.stderr.write(data))
|
||||
}
|
||||
|
||||
subprocess.on('close', code => {
|
||||
if (code === 0) {
|
||||
resolve()
|
||||
} else {
|
||||
reject(new Error(`"${this.command}" exited with code ${code}`))
|
||||
}
|
||||
})
|
||||
subprocess.on('error', reject)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,5 @@
|
||||
import * as childProcess from 'child_process'
|
||||
import {run} from '../run'
|
||||
|
||||
export async function build(path: string) {
|
||||
// TODO fix this
|
||||
await childProcess.spawn('npx', ['ttsc', '--build', path], {
|
||||
stdio: 'inherit',
|
||||
})
|
||||
await run('ttsc', ['--build', path])
|
||||
}
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export * from './help'
|
||||
export * from './build'
|
||||
export * from './watch'
|
||||
|
||||
5
packages/scripts/src/commands/watch.ts
Normal file
5
packages/scripts/src/commands/watch.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import {run} from '../run'
|
||||
|
||||
export async function watch(path: string) {
|
||||
await run('ttsc', ['--build', '--watch', '--preserveWatchOutput', path])
|
||||
}
|
||||
@ -5,7 +5,10 @@ import {TCommand} from './TCommand'
|
||||
async function run(...argv: string[]) {
|
||||
const commandName = argv[0] || 'help'
|
||||
if (!(commandName in commands)) {
|
||||
throw new Error('Command not found:' + commandName)
|
||||
const c = Object.keys(commands).filter(cmd => !cmd.startsWith('_'))
|
||||
console.log(
|
||||
`Available commands:\n\n${c.join('\n')}`)
|
||||
return
|
||||
}
|
||||
const command = (commands as any)[commandName] as TCommand
|
||||
await command(...argv.slice(1))
|
||||
@ -13,4 +16,8 @@ async function run(...argv: string[]) {
|
||||
|
||||
if (typeof require !== 'undefined' && require.main === module) {
|
||||
run(...process.argv.slice(2))
|
||||
.catch(err => {
|
||||
console.log('> ' + err.message)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
48
packages/scripts/src/modules.test.ts
Normal file
48
packages/scripts/src/modules.test.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import {getPathVariable, getPathSeparator, findNodeModules} from './modules'
|
||||
import {resolve} from 'path'
|
||||
import {platform} from 'os'
|
||||
|
||||
describe('modules', () => {
|
||||
|
||||
describe('getPathSeparator', () => {
|
||||
it('returns ";" when win32', () => {
|
||||
expect(getPathSeparator('win32')).toEqual(';')
|
||||
})
|
||||
it('returns ":" otherwise', () => {
|
||||
expect(getPathSeparator('linux')).toEqual(':')
|
||||
expect(getPathSeparator('darwin')).toEqual(':')
|
||||
expect(getPathSeparator('mac')).toEqual(':')
|
||||
})
|
||||
})
|
||||
|
||||
describe('findNodeModules', () => {
|
||||
it('should find node_modules/.bin dirs in parent path(s)', () => {
|
||||
const dirs = findNodeModules()
|
||||
expect(dirs.length).toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
it('should not fail when path does not exist', () => {
|
||||
const dirs = findNodeModules('/non/existing/path/bla/123')
|
||||
expect(dirs).toEqual([])
|
||||
})
|
||||
})
|
||||
|
||||
describe('addToPath', () => {
|
||||
it('does nothing when pathsToAdd is empty', () => {
|
||||
const paths = getPathVariable([])
|
||||
expect(paths).toEqual(process.env.PATH)
|
||||
})
|
||||
it('adds paths to path variable', () => {
|
||||
const separator = getPathSeparator(platform())
|
||||
const paths = getPathVariable(['/a', '/b'], '/c')
|
||||
expect(paths).toEqual(`/a${separator}/b${separator}/c`)
|
||||
})
|
||||
it('adds node modules paths to path variable by default', () => {
|
||||
const paths = findNodeModules()
|
||||
const separator = getPathSeparator(platform())
|
||||
expect(paths.length).toBeGreaterThanOrEqual(1)
|
||||
expect(getPathVariable())
|
||||
.toEqual(`${paths.join(separator)}${separator}${process.env.PATH}`)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
36
packages/scripts/src/modules.ts
Normal file
36
packages/scripts/src/modules.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import {platform} from 'os'
|
||||
|
||||
export function getPathSeparator(platformValue: string) {
|
||||
return platformValue === 'win32' ? ';' : ':'
|
||||
}
|
||||
|
||||
export function findNodeModules(dir: string = process.cwd()): string[] {
|
||||
let lastPath = ''
|
||||
const paths = []
|
||||
dir = path.resolve(dir)
|
||||
while (dir !== lastPath) {
|
||||
const nodeModulesDir = path.join(dir, 'node_modules', '.bin')
|
||||
if (
|
||||
fs.existsSync(nodeModulesDir)
|
||||
&& fs.statSync(nodeModulesDir).isDirectory()
|
||||
) {
|
||||
paths.push(nodeModulesDir)
|
||||
}
|
||||
lastPath = dir
|
||||
dir = path.resolve(dir, '..')
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
export function getPathVariable(
|
||||
pathsToAdd: string[] = findNodeModules(),
|
||||
currentPath = process.env.PATH,
|
||||
) {
|
||||
if (!pathsToAdd.length) {
|
||||
return currentPath
|
||||
}
|
||||
const separator = getPathSeparator(platform())
|
||||
return `${pathsToAdd.join(separator)}${separator}${currentPath}`
|
||||
}
|
||||
10
packages/scripts/src/run.ts
Normal file
10
packages/scripts/src/run.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import {Subprocess} from './Subprocess'
|
||||
import {getPathVariable} from './modules'
|
||||
|
||||
export async function run(command: string, args: string[]) {
|
||||
return new Subprocess(command, args, {
|
||||
...process.env,
|
||||
PATH: getPathVariable(),
|
||||
})
|
||||
.run()
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user