Skip to content

Commit 9723dfd

Browse files
committed
wip
1 parent 28fbc71 commit 9723dfd

24 files changed

Lines changed: 279 additions & 158 deletions

File tree

packages/@ionic/cli-framework/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,19 @@
3535
},
3636
"dependencies": {
3737
"chalk": "^2.3.0",
38+
"debug": "^3.1.0",
3839
"ncp": "^2.0.0",
3940
"rimraf": "^2.6.2",
4041
"strip-ansi": "^4.0.0",
4142
"superagent": "^3.8.1",
4243
"tslib": "^1.8.0"
4344
},
4445
"devDependencies": {
46+
"@types/debug": "0.0.30",
4547
"@types/minimist": "^1.2.0",
4648
"@types/ncp": "^2.0.1",
4749
"@types/rimraf": "^2.0.2",
50+
"@types/strip-ansi": "^3.0.0",
4851
"@types/superagent": "^3.5.6"
4952
}
5053
}

packages/@ionic/cli-framework/src/lib/__tests__/validators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import chalk from 'chalk';
22

33
import { validators } from '../validators';
44

5-
import * as stripAnsi from 'strip-ansi';
5+
import stripAnsi = require('strip-ansi');
66

77
describe('@ionic/cli-framework', () => {
88

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import * as Debug from 'debug';
2+
3+
export const createDebugLogger = Debug;

packages/@ionic/cli-plugin-proxy/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
"../../../types/cross-spawn.d.ts",
2424
"../../../types/dargs.d.ts",
2525
"../../../types/slice-ansi.d.ts",
26-
"../../../types/strip-ansi.d.ts",
2726
"../../../types/string-width.d.ts",
2827
"../../../types/superagent.d.ts",
2928
"../../../types/superagent-proxy.d.ts",

packages/@ionic/cli-utils/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@
5959
"os-name": "^2.0.1",
6060
"semver": "^5.4.1",
6161
"slice-ansi": "^1.0.0",
62+
"split2": "^2.2.0",
6263
"ssh-config": "^1.1.1",
6364
"string-width": "^2.1.1",
65+
"strip-ansi": "^4.0.0",
6466
"superagent": "^3.8.1",
6567
"tar": "^4.0.2",
6668
"tiny-lr": "^1.0.5",
@@ -84,6 +86,8 @@
8486
"@types/minimist": "^1.2.0",
8587
"@types/opn": "^5.1.0",
8688
"@types/semver": "^5.4.0",
89+
"@types/split2": "^2.1.6",
90+
"@types/strip-ansi": "^3.0.0",
8791
"@types/tar": "^4.0.0",
8892
"@types/uuid": "^3.4.3",
8993
"@types/ws": "^3.2.0",

packages/@ionic/cli-utils/src/commands/serve.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ const WATCH_BEFORE_HOOK = 'watch:before';
2222
const WATCH_BEFORE_SCRIPT = `ionic:${WATCH_BEFORE_HOOK}`;
2323

2424
export async function serve(env: IonicEnvironment, inputs: CommandLineInputs, options: CommandLineOptions): Promise<ServeDetails> {
25+
env.keepopen = true;
26+
2527
const { detectAndWarnAboutDeprecatedPlugin } = await import('../lib/plugins');
2628

2729
const packageJson = await env.project.loadPackageJson();

packages/@ionic/cli-utils/src/definitions.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@ export interface LoggerOptions {
3030
level?: LogLevel;
3131
prefix?: string | (() => string);
3232
stream?: NodeJS.WritableStream;
33+
wrap?: boolean;
3334
}
3435

3536
export interface ILogger {
36-
level: LogLevel;
37-
prefix: LogPrefix;
37+
readonly level: LogLevel;
38+
readonly prefix: LogPrefix;
3839
stream: NodeJS.WritableStream;
40+
readonly wrap: boolean;
3941

42+
// log functions
4043
debug: LogFn;
4144
info: LogFn;
4245
ok: LogFn;
@@ -46,6 +49,9 @@ export interface ILogger {
4649
msg: LogFn;
4750
log: LogFn;
4851
nl(num?: number): void;
52+
53+
createWriteStream(): NodeJS.WritableStream;
54+
clone(opts?: Partial<LoggerOptions>): ILogger;
4955
shouldLog(level: LogLevel): boolean;
5056
}
5157

@@ -295,18 +301,25 @@ export interface ISession {
295301
getAppUserToken(app_id?: string): Promise<string>;
296302
}
297303

298-
export interface IShellRunOptions extends crossSpawnType.SpawnOptions {
304+
export interface IShellSpawnOptions extends crossSpawnType.SpawnOptions {
299305
showCommand?: boolean;
306+
}
307+
308+
export interface IShellRunOptions extends IShellSpawnOptions {
300309
showExecution?: boolean;
301310
showError?: boolean;
302311
showSpinner?: boolean;
303312
fatalOnNotFound?: boolean;
304313
fatalOnError?: boolean;
305314
truncateErrorOutput?: number;
315+
logOptions?: IShellRunLogOptions;
306316
}
307317

318+
export type IShellRunLogOptions = Partial<LoggerOptions> & { stdoutTransform?: NodeJS.ReadWriteStream; stderrTransform?: NodeJS.ReadWriteStream };
319+
308320
export interface IShell {
309321
run(command: string, args: string[], options: IShellRunOptions): Promise<string>;
322+
spawn(command: string, args: string[], options: IShellSpawnOptions): Promise<crossSpawnType.ChildProcess>;
310323
cmdinfo(cmd: string, args?: string[]): Promise<string | undefined>;
311324
}
312325

@@ -561,6 +574,7 @@ export interface IonicEnvironment {
561574
readonly tasks: ITaskChain;
562575
readonly telemetry: ITelemetry;
563576
readonly namespace: IRootNamespace;
577+
keepopen: boolean;
564578

565579
open(): Promise<void>;
566580
close(): Promise<void>;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createDebugLogger as genlogger} from '@ionic/cli-framework/utils/debug';
2+
3+
export function createDebugLogger(context: string) {
4+
return genlogger(`ionic:cli-utils:${context}`);
5+
}

packages/@ionic/cli-utils/src/lib/environment.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export class Environment implements IonicEnvironment {
4141
readonly tasks: ITaskChain;
4242
readonly telemetry: ITelemetry;
4343
readonly namespace: IRootNamespace;
44+
keepopen = false;
4445

4546
private bottomBar?: inquirerType.ui.BottomBar;
4647

@@ -126,16 +127,18 @@ export class Environment implements IonicEnvironment {
126127
}
127128

128129
async close() {
129-
this.tasks.cleanup();
130+
if (!this.keepopen) {
131+
this.tasks.cleanup();
130132

131-
// instantiating inquirer.ui.BottomBar hangs, so when close() is called,
132-
// we close BottomBar streams and replace the log stream with stdout.
133-
// This means inquirer shouldn't be used after command execution finishes
134-
// (which could happen during long-running processes like serve).
135-
if (this.bottomBar) {
136-
this.bottomBar.close();
137-
this.bottomBar = undefined;
138-
this.log.stream = process.stdout;
133+
// instantiating inquirer.ui.BottomBar hangs, so when close() is called,
134+
// we close BottomBar streams and replace the log stream with stdout.
135+
// This means inquirer shouldn't be used after command execution finishes
136+
// (which could happen during long-running processes like serve).
137+
if (this.bottomBar) {
138+
this.bottomBar.close();
139+
this.bottomBar = undefined;
140+
this.log.stream = process.stdout;
141+
}
139142
}
140143
}
141144

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import chalk from 'chalk';
22

33
import { IonicEnvironment, ServeDetails, ServeOptions } from '../../definitions';
4-
5-
import { BIND_ALL_ADDRESS, LOCAL_ADDRESSES, selectExternalIP } from '../serve';
4+
import { BIND_ALL_ADDRESS, LOCAL_ADDRESSES, findOpenPorts, selectExternalIP } from '../serve';
65
import { FatalException } from '../errors';
7-
import { importAppScripts } from './app-scripts';
86

97
export interface AppScriptsServeOptions extends ServeOptions {
108
platform: string;
@@ -13,57 +11,35 @@ export interface AppScriptsServeOptions extends ServeOptions {
1311
}
1412

1513
export async function serve({ env, options }: { env: IonicEnvironment, options: AppScriptsServeOptions }): Promise<ServeDetails> {
14+
const split2 = await import('split2');
15+
const { registerShutdownFunction } = await import('../process');
16+
const { isHostConnectable } = await import('../utils/network');
1617
const [ externalIP, availableInterfaces ] = await selectExternalIP(env, options);
1718

18-
const appScriptsArgs = await serveOptionsToAppScriptsArgs(options);
19-
process.argv = ['node', 'appscripts'].concat(appScriptsArgs);
19+
const { port } = await findOpenPorts(env, options.address, options);
20+
21+
const p = await env.shell.spawn('ng', ['serve', '--host', options.address, '--port', String(port), '--progress', 'false'], { cwd: env.project.directory });
22+
23+
const log = env.log.clone({ prefix: chalk.dim('[ng]'), wrap: false });
24+
const ws = log.createWriteStream();
2025

21-
const AppScripts = await importAppScripts(env);
22-
const context = AppScripts.generateContext();
26+
p.stdout.pipe(split2()).pipe(ws);
27+
p.stderr.pipe(split2()).pipe(ws);
2328

24-
// using app-scripts and livereload is requested
25-
// Also remove commandName from the rawArgs passed
26-
env.log.info(`Starting app-scripts server: ${chalk.bold(appScriptsArgs.join(' '))} - Ctrl+C to cancel`);
27-
const settings = await AppScripts.serve(context);
29+
registerShutdownFunction(() => { p.kill(); });
2830

29-
if (!settings) { // TODO: shouldn've been fixed after app-scripts 1.3.7
30-
throw new FatalException(
31-
`app-scripts serve unexpectedly failed.` +
32-
`settings: ${settings}` +
33-
`context: ${context}`
34-
);
31+
const connectable = await isHostConnectable(externalIP, port, 20000);
32+
33+
if (!connectable) {
34+
throw new FatalException(`Could not connect to ng server at ${options.address}:${String(port)}.`);
3535
}
3636

3737
return {
3838
protocol: 'http',
3939
localAddress: 'localhost',
4040
externalAddress: externalIP,
4141
externalNetworkInterfaces: availableInterfaces,
42-
port: settings.httpPort,
42+
port,
4343
externallyAccessible: ![BIND_ALL_ADDRESS, ...LOCAL_ADDRESSES].includes(externalIP),
4444
};
4545
}
46-
47-
export async function serveOptionsToAppScriptsArgs(options: AppScriptsServeOptions) {
48-
const { minimistOptionsToArray } = await import('../utils/command');
49-
50-
const minimistArgs = {
51-
_: [],
52-
address: options.address,
53-
port: String(options.port),
54-
livereloadPort: String(options.livereloadPort),
55-
devLoggerPort: String(options.notificationPort),
56-
consolelogs: options.consolelogs,
57-
serverlogs: options.serverlogs,
58-
nobrowser: true,
59-
nolivereload: !options.livereload,
60-
noproxy: !options.proxy,
61-
lab: options.lab,
62-
iscordovaserve: options.iscordovaserve,
63-
platform: options.platform,
64-
target: options.target,
65-
env: options.env,
66-
};
67-
68-
return minimistOptionsToArray(minimistArgs, { useEquals: false });
69-
}

0 commit comments

Comments
 (0)