Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
*/
let details: ServeDetails | undefined;
let serverUrl = options['livereload-url'] ? String(options['livereload-url']) : undefined;
if (!serverUrl) {
details = await runner.run(runnerOpts);
if (details.externallyAccessible === false && !options['native-run']) {
const extra = LOCAL_ADDRESSES.includes(details.externalAddress) ? '\nEnsure you have proper port forwarding setup from your device to your computer.' : '';
this.env.log.warn(`Your device or emulator may not be able to access ${strong(details.externalAddress)}.${extra}\n\n`);
}
serverUrl = `${details.protocol || 'http'}://${details.externalAddress}:${details.port}`;
}
onBeforeExit(async () => {
conf.resetContentSrc();
await conf.save();
});
conf.writeContentSrc(serverUrl);
await conf.save();
const cordovalogws = createPrefixedWriteStream(this.env.log, weak(`[cordova]`));
const buildOpts: IShellRunOptions = { stream: cordovalogws };
// ignore very verbose compiler output on stdout unless --verbose
buildOpts.stdio = options['verbose'] ? 'inherit' : ['pipe', 'ignore', 'pipe'];
if (options['native-run']) {
const [ platform ] = inputs;
const packagePath = await getPackagePath(conf.getProjectInfo().name, platform, { emulator: !options['device'], release: !!options['release'] });
const forwardedPorts = details ? runner.getUsedPorts(runnerOpts, details) : [];
promise.p.stdout.pipe(s);
}
if (promise.p.stderr) {
const s = combineStreams(split2(), ws);
// TODO: https://github.com/angular/angular-cli/issues/10922
s.on('error', (err: Error) => {
debug('Error in subprocess stderr pipe: %o', err);
});
promise.p.stderr.pipe(s);
}
if (killOnExit) {
onBeforeExit(async () => {
if (promise.p.pid) {
await killProcessTree(promise.p.pid);
}
});
}
await promise;
} catch (e) {
if (e instanceof SubprocessError && e.code === ERROR_COMMAND_NOT_FOUND) {
if (fatalOnNotFound) {
throw new FatalException(`Command not found: ${input(command)}`, 127);
} else {
throw e;
}
}
try {
await shell.run('native-run', args, { showCommand: !args.includes('--json'), fatalOnNotFound: false, stream, ...options });
} catch (e) {
if (e instanceof SubprocessError && e.code === ERROR_COMMAND_NOT_FOUND) {
throw createNativeRunNotFoundError(config.get('npmClient'));
}
throw e;
}
// If we connect the `native-run` process to the running app, then we
// should also connect the Ionic CLI with the running `native-run` process.
// This will exit the Ionic CLI when `native-run` exits.
if (connect) {
processExit(0); // tslint:disable-line:no-floating-promises
}
}
protected prepareSpawnOptions(options: IShellSpawnOptions) {
// Create a `process.env`-type object from all key/values of `process.env`,
// then `options.env`, then add several key/values. PATH is supplemented
// with the `node_modules\.bin` folder in the project directory so that we
// can run binaries inside a project.
options.env = createProcessEnv(process.env, options.env, {
PATH: this.alterPath(process.env.PATH || ''),
FORCE_COLOR: chalk.level > 0 ? '1' : '0',
});
}
}
async function _findExecutables(program: string, { PATH = process.env.PATH, PATHEXT = process.env.PATHEXT || DEFAULT_PATHEXT }: WhichOptions = {}): Promise {
const pathParts = getPathParts(PATH);
let programNames: string[];
// if windows, cycle through all possible executable extensions
// ex: node.exe, npm.cmd, etc.
if (TERMINAL_INFO.windows) {
const exts = getPathParts(PATHEXT).map(ext => ext.toLowerCase());
// don't append extensions if one has already been provided
programNames = exts.includes(pathlib.extname(program).toLowerCase()) ? [program] : exts.map(ext => program + ext);
} else {
programNames = [program];
}
return ([] as string[]).concat(...await map(programNames, async (programName): Promise =>
concurrentFilter(pathParts.map(p => pathlib.join(p, programName)), async p => isExecutableFile(p))));
}
async function _findExecutables(program: string, { PATH = process.env.PATH, PATHEXT = process.env.PATHEXT || DEFAULT_PATHEXT }: WhichOptions = {}): Promise {
const pathParts = getPathParts(PATH);
let programNames: string[];
// if windows, cycle through all possible executable extensions
// ex: node.exe, npm.cmd, etc.
if (TERMINAL_INFO.windows) {
const exts = getPathParts(PATHEXT).map(ext => ext.toLowerCase());
// don't append extensions if one has already been provided
programNames = exts.includes(pathlib.extname(program).toLowerCase()) ? [program] : exts.map(ext => program + ext);
} else {
programNames = [program];
}
return ([] as string[]).concat(...await map(programNames, async (programName): Promise =>
concurrentFilter(pathParts.map(p => pathlib.join(p, programName)), async p => isExecutableFile(p))));
}
const cordovalogws = createPrefixedWriteStream(this.env.log, weak(`[cordova]`));
const buildOpts: IShellRunOptions = { stream: cordovalogws };
// ignore very verbose compiler output on stdout unless --verbose
buildOpts.stdio = options['verbose'] ? 'inherit' : ['pipe', 'ignore', 'pipe'];
if (options['native-run']) {
const [ platform ] = inputs;
const packagePath = await getPackagePath(conf.getProjectInfo().name, platform, { emulator: !options['device'], release: !!options['release'] });
const forwardedPorts = details ? runner.getUsedPorts(runnerOpts, details) : [];
await this.runCordova(filterArgumentsForCordova({ ...metadata, name: 'build' }, options), buildOpts);
await this.runNativeRun(createNativeRunArgs({ packagePath, platform, forwardedPorts }, options));
} else {
await this.runCordova(filterArgumentsForCordova(metadata, options), buildOpts);
await sleepForever();
}
}
it('should provide only PATH with empty env', async () => {
const PATH = process.env.PATH;
const cmd = new Subprocess('cmd', [], { env: {} });
expect(cmd.options).toEqual({ env: createProcessEnv({ PATH }) });
});
it('should call spawn with correct program/args with pathed name', async () => {
const result = {};
mockCrossSpawn.mockImplementation(() => result);
const name = path.resolve('/path', 'to', 'cmd');
const args = ['foo', 'bar', 'baz'];
const options = { env: { PATH: '' } };
const cmd = new Subprocess(name, args, options);
const expectedOptions = { env: createProcessEnv(options.env) };
expect(cmd.spawn()).toBe(result);
expect(mockCrossSpawn).toHaveBeenCalledTimes(1);
expect(mockCrossSpawn).toHaveBeenCalledWith(name, args, expectedOptions);
});
it('should provide default env option', async () => {
const cmd = new Subprocess('cmd', []);
expect(cmd.options).toEqual({ env: createProcessEnv(process.env) });
});