Skip to content

Commit

Permalink
refactor(lab): remove ionic serve --lab option (#4960)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

The `--lab` option has been removed from `ionic serve`. See https://ionicframework.com/docs/developing/previewing for alternatives.
  • Loading branch information
liamdebeasi committed Mar 29, 2023
1 parent 4ec0362 commit 4cb06ca
Show file tree
Hide file tree
Showing 45 changed files with 11 additions and 2,595 deletions.
1 change: 0 additions & 1 deletion packages/@ionic/cli/src/commands/index.ts
Expand Up @@ -81,7 +81,6 @@ export class IonicNamespace extends Namespace {
['state', async () => { const { StateCommand } = await import('./state'); return new StateCommand(this); }],
['telemetry', async () => { const { TelemetryCommand } = await import('./telemetry'); return new TelemetryCommand(this); }],
['version', async () => { const { VersionCommand } = await import('./version'); return new VersionCommand(this); }],
['lab', async () => { const { LabCommand } = await import('./serve'); return new LabCommand(this); }],
['g', 'generate'],
['s', 'serve'],
]);
Expand Down
63 changes: 4 additions & 59 deletions packages/@ionic/cli/src/commands/serve.ts
Expand Up @@ -3,34 +3,17 @@ import { sleepForever } from '@ionic/utils-process';
import * as lodash from 'lodash';

import { CommandInstanceInfo, CommandLineInputs, CommandLineOptions, CommandMetadata, CommandMetadataOption, CommandPreRun } from '../definitions';
import { input, strong, weak } from '../lib/color';
import { input } from '../lib/color';
import { Command } from '../lib/command';
import { FatalException, RunnerException } from '../lib/errors';
import { getFullCommandParts } from '../lib/executor';
import { BROWSERS, COMMON_SERVE_COMMAND_OPTIONS, DEFAULT_LAB_PORT } from '../lib/serve';
import { BROWSERS, COMMON_SERVE_COMMAND_OPTIONS } from '../lib/serve';

export class ServeCommand extends Command implements CommandPreRun {
async getMetadata(): Promise<CommandMetadata> {
const groups: string[] = [];

let options: CommandMetadataOption[] = [
...COMMON_SERVE_COMMAND_OPTIONS,
{
name: 'lab-host',
summary: 'Use specific host for Ionic Lab server',
default: 'localhost',
groups: [MetadataGroup.ADVANCED],
spec: { value: 'host' },
hint: weak('(--lab)'),
},
{
name: 'lab-port',
summary: 'Use specific port for Ionic Lab server',
default: DEFAULT_LAB_PORT.toString(),
groups: [MetadataGroup.ADVANCED],
spec: { value: 'port' },
hint: weak('(--lab)'),
},
{
name: 'open',
summary: 'Do not open a browser window',
Expand All @@ -51,23 +34,15 @@ export class ServeCommand extends Command implements CommandPreRun {
groups: [MetadataGroup.ADVANCED],
spec: { value: 'path' },
},
{
name: 'lab',
summary: 'Test your apps on multiple platform types in the browser',
type: Boolean,
aliases: ['l'],
},
];

const exampleCommands = ['', '--external', '--lab'];
const exampleCommands = ['', '--external'];
const footnotes: Footnote[] = [];

let description = `
Easily spin up a development server which launches in your browser. It watches for changes in your source files and automatically reloads with the updated build.
By default, ${input('ionic serve')} boots up a development server on ${input('localhost')}. To serve to your LAN, specify the ${input('--external')} option, which will use all network interfaces and print the external address(es) on which your app is being served.
Try the ${input('--lab')} option to see multiple platforms at once.`;
By default, ${input('ionic serve')} boots up a development server on ${input('localhost')}. To serve to your LAN, specify the ${input('--external')} option, which will use all network interfaces and print the external address(es) on which your app is being served.`;

const runner = this.project && await this.project.getServeRunner();

Expand All @@ -93,17 +68,6 @@ Try the ${input('--lab')} option to see multiple platforms at once.`;
}

async preRun(inputs: CommandLineInputs, options: CommandLineOptions, { location }: CommandInstanceInfo): Promise<void> {
const parts = getFullCommandParts(location);
const alias = lodash.last(parts);

if (alias === 'lab') {
options['lab'] = true;
}

if (options['lab']) {
this.env.log.warn(`The ${input('--lab')} option has been deprecated and will be removed in an upcoming major release of the Ionic CLI. Please visit ${strong('https://ionicframework.com/docs/developing/previewing')} for alternatives to Ionic Lab.`);
}

if (options['nolivereload']) {
this.env.log.warn(`The ${input('--nolivereload')} option has been deprecated. Please use ${input('--no-livereload')}.`);
options['livereload'] = false;
Expand Down Expand Up @@ -149,22 +113,3 @@ Try the ${input('--lab')} option to see multiple platforms at once.`;
await sleepForever();
}
}

export class LabCommand extends ServeCommand {
async getMetadata(): Promise<CommandMetadata> {
const metadata = await super.getMetadata();
const groups = [...metadata.groups || [], MetadataGroup.HIDDEN];
const exampleCommands = [...metadata.exampleCommands || []].filter(c => !c.includes('--lab'));

return {
...metadata,
summary: 'Start Ionic Lab for multi-platform dev/testing',
description: `
Start an instance of ${strong('Ionic Lab')}, a tool for developing Ionic apps for multiple platforms at once side-by-side.
${input('ionic lab')} is just a convenient shortcut for ${input('ionic serve --lab')}.`,
groups,
exampleCommands,
};
}
}
3 changes: 0 additions & 3 deletions packages/@ionic/cli/src/definitions.ts
Expand Up @@ -712,9 +712,6 @@ export interface ServeOptions {
publicHost?: string;
livereload: boolean;
proxy: boolean;
lab: boolean;
labHost: string;
labPort: number;
open: boolean;
browser?: string;
browserOption?: string;
Expand Down
7 changes: 2 additions & 5 deletions packages/@ionic/cli/src/lib/__tests__/serve.ts
Expand Up @@ -26,9 +26,6 @@ describe('@ionic/cli', () => {
browserOption: undefined,
engine: 'browser',
externalAddressRequired: false,
lab: false,
labHost: 'localhost',
labPort: 8200,
livereload: true,
open: false,
port: 8100,
Expand All @@ -45,8 +42,8 @@ describe('@ionic/cli', () => {

it('should provide options from negations of cli flag defaults', () => {
const runner = new MyServeRunner({});
const result = runner.createOptionsFromCommandLine([], { _: [], livereload: false, proxy: false, lab: true, open: true, externalAddressRequired: true });
expect(result).toEqual({ ...defaults, livereload: false, proxy: false, lab: true, open: true, externalAddressRequired: true });
const result = runner.createOptionsFromCommandLine([], { _: [], livereload: false, proxy: false, open: true, externalAddressRequired: true });
expect(result).toEqual({ ...defaults, livereload: false, proxy: false, open: true, externalAddressRequired: true });
});

it('should allow overrides of default values', () => {
Expand Down
Expand Up @@ -17,9 +17,6 @@ describe('@ionic/cli', () => {
browserOption: undefined,
engine: 'browser',
externalAddressRequired: false,
lab: false,
labHost: 'localhost',
labPort: 8200,
livereload: true,
open: false,
port: 8100,
Expand All @@ -38,8 +35,8 @@ describe('@ionic/cli', () => {

it('should provide options from negations of cli flag defaults', () => {
const runner = new AngularServeRunner({} as any);
const result = runner.createOptionsFromCommandLine([], { _: [], livereload: false, proxy: false, lab: true, open: true, externalAddressRequired: true });
expect(result).toEqual({ ...defaults, livereload: false, proxy: false, lab: true, open: true, externalAddressRequired: true });
const result = runner.createOptionsFromCommandLine([], { _: [], livereload: false, proxy: false, open: true, externalAddressRequired: true });
expect(result).toEqual({ ...defaults, livereload: false, proxy: false, open: true, externalAddressRequired: true });
});

it('should allow overrides of default values', () => {
Expand Down
61 changes: 3 additions & 58 deletions packages/@ionic/cli/src/lib/serve.ts
Expand Up @@ -2,7 +2,7 @@ import { BaseError, MetadataGroup, ParsedArgs, unparseArgs } from '@ionic/cli-fr
import { LOGGER_LEVELS, createPrefixedFormatter } from '@ionic/cli-framework-output';
import { PromptModule } from '@ionic/cli-framework-prompts';
import { str2num } from '@ionic/cli-framework/utils/string';
import { NetworkInterface, findClosestOpenPort, getExternalIPv4Interfaces, isHostConnectable } from '@ionic/utils-network';
import { NetworkInterface, getExternalIPv4Interfaces, isHostConnectable } from '@ionic/utils-network';
import { createProcessEnv, killProcessTree, onBeforeExit, processExit } from '@ionic/utils-process';
import * as chalk from 'chalk';
import * as Debug from 'debug';
Expand All @@ -11,7 +11,7 @@ import * as lodash from 'lodash';
import * as split2 from 'split2';
import * as stream from 'stream';

import { CommandLineInputs, CommandLineOptions, CommandMetadata, CommandMetadataOption, IConfig, ILogger, IProject, IShell, IonicEnvironmentFlags, LabServeDetails, NpmClient, Runner, ServeDetails, ServeOptions } from '../definitions';
import { CommandLineInputs, CommandLineOptions, CommandMetadata, CommandMetadataOption, IConfig, ILogger, IProject, IShell, IonicEnvironmentFlags, NpmClient, Runner, ServeDetails, ServeOptions } from '../definitions';

import { ancillary, input, strong, weak } from './color';
import { FatalException, ServeCLIProgramNotFoundException } from './errors';
Expand All @@ -25,7 +25,6 @@ const debug = Debug('ionic:lib:serve');
export const DEFAULT_DEV_LOGGER_PORT = 53703;
export const DEFAULT_LIVERELOAD_PORT = 35729;
export const DEFAULT_SERVER_PORT = 8100;
export const DEFAULT_LAB_PORT = 8200;
export const DEFAULT_DEVAPP_COMM_PORT = 53233;

export const DEFAULT_ADDRESS = 'localhost';
Expand Down Expand Up @@ -138,7 +137,6 @@ export abstract class ServeRunner<T extends ServeOptions> implements Runner<T, S

const engine = this.determineEngineFromCommandLine(options);
const host = options['host'] ? String(options['host']) : DEFAULT_ADDRESS;
const labPort = str2num(options['lab-port'], DEFAULT_LAB_PORT);
const port = str2num(options['port'], DEFAULT_SERVER_PORT);
const [ platform ] = options['platform'] ? [String(options['platform'])] : inputs;

Expand All @@ -149,9 +147,6 @@ export abstract class ServeRunner<T extends ServeOptions> implements Runner<T, S
browserOption: options['browseroption'] ? String(options['browseroption']) : undefined,
engine,
externalAddressRequired: !!options['externalAddressRequired'],
lab: !!options['lab'],
labHost: options['lab-host'] ? String(options['lab-host']) : 'localhost',
labPort,
livereload: typeof options['livereload'] === 'boolean' ? Boolean(options['livereload']) : true,
open: !!options['open'],
platform,
Expand Down Expand Up @@ -195,24 +190,21 @@ export abstract class ServeRunner<T extends ServeOptions> implements Runner<T, S
await this.beforeServe(options);

const details = await this.serveProject(options);
const labDetails = options.lab ? await this.runLab(options, details) : undefined;

const localAddress = `${details.protocol}://${options.publicHost ? options.publicHost : 'localhost'}:${details.port}`;
const fmtExternalAddress = (host: string) => `${details.protocol}://${host}:${details.port}`;
const labHost = labDetails ? `http://${labDetails.host}:${labDetails.port}` : undefined;

this.e.log.nl();
this.e.log.info(
`Development server running!` +
(labHost ? `\nLab: ${strong(labHost)}` : '') +
`\nLocal: ${strong(localAddress)}` +
(details.externalNetworkInterfaces.length > 0 ? `\nExternal: ${details.externalNetworkInterfaces.map(v => strong(fmtExternalAddress(v.address))).join(', ')}` : '') +
`\n\n${chalk.yellow('Use Ctrl+C to quit this process')}`
);
this.e.log.nl();

if (options.open) {
const openAddress = labHost ? labHost : localAddress;
const openAddress = localAddress;
const url = this.modifyOpenUrl(openAddress, options);

await openUrl(url, { app: options.browser });
Expand Down Expand Up @@ -251,19 +243,6 @@ export abstract class ServeRunner<T extends ServeOptions> implements Runner<T, S
return [details.port];
}

async runLab(options: T, serveDetails: ServeDetails): Promise<LabServeDetails> {
const labDetails: LabServeDetails = {
projectType: this.e.project.type,
host: options.labHost,
port: await findClosestOpenPort(options.labPort),
};

const lab = new IonicLabServeCLI(this.e);
await lab.serve({ serveDetails, ...labDetails });

return labDetails;
}

async selectExternalIP(options: T): Promise<[string, NetworkInterface[]]> {
let availableInterfaces: NetworkInterface[] = [];
let chosenIP = options.host;
Expand Down Expand Up @@ -647,37 +626,3 @@ export class YarnServeCLI extends PkgManagerServeCLI {
readonly program = 'yarn';
readonly prefix = 'yarn';
}

interface IonicLabServeCLIOptions extends Readonly<LabServeDetails> {
readonly serveDetails: Readonly<ServeDetails>;
}

class IonicLabServeCLI extends ServeCLI<IonicLabServeCLIOptions> {
readonly name = 'Ionic Lab';
readonly pkg = '@ionic/lab';
readonly program = 'ionic-lab';
readonly prefix = 'lab';
readonly script = undefined;

protected stdoutFilter(line: string): boolean {
if (line.includes('running')) {
this.emit('ready');
}

return false; // no stdout
}

protected async buildArgs(options: IonicLabServeCLIOptions): Promise<string[]> {
const { serveDetails, ...labDetails } = options;

const pkg = await this.e.project.requirePackageJson();

const url = `${serveDetails.protocol}://localhost:${serveDetails.port}`;
const appName = this.e.project.config.get('name');
const labArgs = [url, '--host', labDetails.host, '--port', String(labDetails.port), '--project-type', labDetails.projectType];
const nameArgs = appName ? ['--app-name', appName] : [];
const versionArgs = pkg.version ? ['--app-version', pkg.version] : [];

return [...labArgs, ...nameArgs, ...versionArgs];
}
}
3 changes: 0 additions & 3 deletions packages/@ionic/lab/.gitignore

This file was deleted.

1 change: 0 additions & 1 deletion packages/@ionic/lab/.npmrc

This file was deleted.

0 comments on commit 4cb06ca

Please sign in to comment.