Skip to content

Commit 89b6d33

Browse files
committed
fix(serve): handle error in opn with debug statement
If an unlikely error occurs in the child process within opn, we want to ignore it (but print it for debugging), instead of crashing the CLI due to an unhandled error event. references #3770
1 parent 514015f commit 89b6d33

File tree

6 files changed

+29
-14
lines changed

6 files changed

+29
-14
lines changed

packages/ionic/src/commands/docs.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import chalk from 'chalk';
44
import { CommandLineInputs, CommandLineOptions, CommandMetadata } from '../definitions';
55
import { isSuperAgentError } from '../guards';
66
import { Command } from '../lib/command';
7+
import { open } from '../lib/open';
78
import { BROWSERS } from '../lib/serve';
89
import { createRequest } from '../lib/utils/http';
910

@@ -25,8 +26,6 @@ export class DocsCommand extends Command {
2526
}
2627

2728
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
28-
const opn = await import('opn');
29-
3029
const browser = options['browser'] ? String(options['browser']) : undefined;
3130

3231
const homepage = 'https://ionicframework.com/docs';
@@ -38,14 +37,14 @@ export class DocsCommand extends Command {
3837
} catch (e) {
3938
if (isSuperAgentError(e) && e.response.status === 404) {
4039
this.env.log.warn(`Docs not found for your specific version of Ionic. Directing you to docs homepage.`);
41-
await opn(homepage, { app: browser, wait: false });
40+
await open(homepage, { app: browser });
4241
return;
4342
}
4443

4544
throw e;
4645
}
4746

48-
await opn(url, { app: browser, wait: false });
47+
await open(url, { app: browser });
4948
this.env.log.ok('Launched Ionic docs in your browser!');
5049
}
5150
}

packages/ionic/src/commands/link.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { isSuperAgentError } from '../guards';
99
import { Command } from '../lib/command';
1010
import { FatalException } from '../lib/errors';
1111
import { runCommand } from '../lib/executor';
12+
import { open } from '../lib/open';
1213

1314
const debug = Debug('ionic:commands:link');
1415

@@ -364,8 +365,6 @@ ${chalk.cyan('[2]')}: ${chalk.bold('https://ionicframework.com/support/request')
364365
}
365366

366367
async oAuthProcess(userId: number) {
367-
const opn = await import('opn');
368-
369368
const userClient = await this.getUserClient();
370369

371370
let confirm = false;
@@ -389,7 +388,7 @@ ${chalk.cyan('[2]')}: ${chalk.bold('https://ionicframework.com/support/request')
389388
}
390389

391390
const url = await userClient.oAuthGithubLogin(userId);
392-
await opn(url, { wait: false });
391+
await open(url);
393392

394393
confirm = await this.env.prompt({
395394
type: 'confirm',

packages/ionic/src/commands/signup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import chalk from 'chalk';
22

33
import { CommandLineInputs, CommandLineOptions, CommandMetadata } from '../definitions';
44
import { Command } from '../lib/command';
5+
import { open } from '../lib/open';
56

67
export class SignupCommand extends Command {
78
async getMetadata(): Promise<CommandMetadata> {
@@ -20,10 +21,9 @@ ${chalk.cyan('[1]')}: ${chalk.bold('https://ionicframework.com/support/request')
2021
}
2122

2223
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {
23-
const opn = await import('opn');
2424
const dashUrl = this.env.config.getDashUrl();
2525

26-
await opn(`${dashUrl}/signup?source=cli`, { wait: false });
26+
await open(`${dashUrl}/signup?source=cli`);
2727

2828
this.env.log.ok('Launched signup form in your browser!');
2929
}

packages/ionic/src/lib/open.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import * as Debug from 'debug';
2+
3+
const debug = Debug('ionic:lib:open');
4+
5+
export interface OpenOptions {
6+
app?: string | ReadonlyArray<string>;
7+
}
8+
9+
export async function open(target: string, options: OpenOptions = {}): Promise<void> {
10+
const opn = await import ('opn');
11+
12+
const p = await opn(target, { ...options, wait: false });
13+
14+
p.on('error', err => {
15+
debug('Error during open: %O', err);
16+
});
17+
}

packages/ionic/src/lib/serve.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { isCordovaPackageJson } from '../guards';
2020
import { FatalException, RunnerException, ServeCLIProgramNotFoundException } from './errors';
2121
import { emit } from './events';
2222
import { Hook } from './hooks';
23+
import { open } from './open';
2324
import { createDefaultLoggerHandlers } from './utils/logger';
2425

2526
const debug = Debug('ionic:lib:serve');
@@ -198,8 +199,7 @@ export abstract class ServeRunner<T extends ServeOptions> implements Runner<T, S
198199
const openAddress = labAddress ? labAddress : localAddress;
199200
const openURL = this.modifyOpenURL(openAddress, options);
200201

201-
const opn = await import('opn');
202-
await opn(openURL, { app: options.browser, wait: false });
202+
await open(openURL, { app: options.browser });
203203

204204
this.e.log.info(`Browser window opened to ${chalk.bold(openURL)}!`);
205205
this.e.log.nl();

packages/ionic/src/lib/sso.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import * as qs from 'querystring';
88
import { ASSETS_DIRECTORY } from '../constants';
99
import { IClient } from '../definitions';
1010

11+
import { open } from './open';
12+
1113
const REDIRECT_PORT = 8123;
1214
const REDIRECT_HOST = 'localhost';
1315

@@ -51,15 +53,13 @@ export abstract class OAuth2Flow {
5153
}
5254

5355
async run(): Promise<string> {
54-
const opn = await import('opn');
55-
5656
const verifier = this.generateVerifier();
5757
const challenge = this.generateChallenge(verifier);
5858

5959
const authorizationParams = this.generateAuthorizationParameters(challenge);
6060
const authorizationUrl = `${this.authorizationUrl}?${qs.stringify(authorizationParams)}`;
6161

62-
await opn(authorizationUrl, { wait: false });
62+
await open(authorizationUrl);
6363

6464
const authorizationCode = await this.getAuthorizationCode();
6565
const token = await this.getAccessToken(authorizationCode, verifier);

0 commit comments

Comments
 (0)