(property: P): T[P];
diff --git a/packages/@ionic/cli-framework/src/lib/help.ts b/packages/@ionic/cli-framework/src/lib/help.ts
index 96b7a8b707..a3df017c09 100644
--- a/packages/@ionic/cli-framework/src/lib/help.ts
+++ b/packages/@ionic/cli-framework/src/lib/help.ts
@@ -7,6 +7,8 @@ import { filter, map } from '../utils/array';
import { generateFillSpaceStringList, stringWidth, wordWrap } from '../utils/format';
import { Colors, DEFAULT_COLORS } from './colors';
+import { isCommandVisible } from './command';
+import { formatOptionName, isOptionVisible } from './options';
import { validators } from './validators';
const DEFAULT_DOTS_WIDTH = 25;
@@ -48,7 +50,9 @@ export abstract class NamespaceHelpFormatter (https://ionicframework.com) ",
@@ -17,9 +17,8 @@
"lint": "tslint --config tslint.js --project tsconfig.json",
"build": "npm run clean && tsc",
"watch": "tsc -w --preserveWatchOutput",
- "test": "jest",
- "prepublishOnly": "npm run build",
- "cli-scripts:pre-commit": "lint-staged"
+ "test": "jest --maxWorkers=4",
+ "prepublishOnly": "npm run build"
},
"lint-staged": {
"linters": {
@@ -49,10 +48,10 @@
},
"license": "MIT",
"dependencies": {
- "@ionic/cli-framework": "1.1.1",
- "@ionic/discover": "1.0.6",
- "@ionic/utils-fs": "0.0.3",
- "@ionic/utils-network": "0.0.3",
+ "@ionic/cli-framework": "1.2.0",
+ "@ionic/discover": "1.0.7",
+ "@ionic/utils-fs": "0.0.4",
+ "@ionic/utils-network": "0.0.4",
"chalk": "^2.3.0",
"debug": "^4.0.0",
"diff": "^3.4.0",
@@ -77,6 +76,7 @@
"@types/debug": "0.0.31",
"@types/diff": "^3.2.2",
"@types/elementtree": "^0.1.0",
+ "@types/jest": "^23.3.5",
"@types/lodash": "^4.14.104",
"@types/node": "^6.0.101",
"@types/opn": "^5.1.0",
@@ -89,10 +89,10 @@
"@types/uuid": "^3.4.3",
"jest": "^23.0.1",
"jest-cli": "^23.0.1",
- "lint-staged": "^7.2.0",
+ "lint-staged": "^8.0.0",
"rimraf": "^2.6.2",
"source-map": "^0.7.0",
- "ts-jest": "~23.1.0",
+ "ts-jest": "^23.10.1",
"tslint": "^5.9.1",
"typescript": "~3.1.1"
}
diff --git a/packages/ionic/src/__tests__/guards.ts b/packages/ionic/src/__tests__/guards.ts
index 6947139d60..2e813afb49 100644
--- a/packages/ionic/src/__tests__/guards.ts
+++ b/packages/ionic/src/__tests__/guards.ts
@@ -1,6 +1,8 @@
import * as guards from '../guards';
-const OBJECT_GUARDS = [
+type Guard = (o: any) => boolean;
+
+const OBJECT_GUARDS: Guard[] = [
guards.isCommand,
guards.isCommandPreRun,
guards.isStarterManifest,
@@ -42,9 +44,7 @@ const OBJECT_GUARDS = [
guards.isMultiProjectConfig,
];
-const ALL_GUARDS = [...OBJECT_GUARDS];
-
-const API_RESPONSE_SUCCESS_GUARDS = [
+const API_RESPONSE_SUCCESS_GUARDS: Guard[] = [
guards.isGithubRepoListResponse,
guards.isGithubBranchListResponse,
guards.isAppAssociationResponse,
diff --git a/packages/ionic/src/commands/capacitor/add.ts b/packages/ionic/src/commands/capacitor/add.ts
index 544ca9b630..b425083700 100644
--- a/packages/ionic/src/commands/capacitor/add.ts
+++ b/packages/ionic/src/commands/capacitor/add.ts
@@ -10,7 +10,7 @@ export class AddCommand extends CapacitorCommand implements CommandPreRun {
return {
name: 'add',
type: 'project',
- summary: 'Adds a new Capacitor native platform to your Ionic project',
+ summary: 'Add a native platform to your Ionic project',
description: `
${chalk.green('ionic capacitor add')} will do the following:
- Add a new platform specific folder to your project (ios, android, or electron)
diff --git a/packages/ionic/src/commands/capacitor/copy.ts b/packages/ionic/src/commands/capacitor/copy.ts
index 43cd423622..ca41338dad 100644
--- a/packages/ionic/src/commands/capacitor/copy.ts
+++ b/packages/ionic/src/commands/capacitor/copy.ts
@@ -10,7 +10,7 @@ export class CopyCommand extends CapacitorCommand implements CommandPreRun {
return {
name: 'copy',
type: 'project',
- summary: 'Copies web assets to Capacitor native platforms',
+ summary: 'Copy web assets to native platforms',
description: `
${chalk.green('ionic capacitor copy')} will do the following:
- Copy the ${chalk.bold('www/')} directory into your native platforms.
diff --git a/packages/ionic/src/commands/capacitor/open.ts b/packages/ionic/src/commands/capacitor/open.ts
index c665f72700..2a5fa536b0 100644
--- a/packages/ionic/src/commands/capacitor/open.ts
+++ b/packages/ionic/src/commands/capacitor/open.ts
@@ -10,7 +10,7 @@ export class OpenCommand extends CapacitorCommand implements CommandPreRun {
return {
name: 'open',
type: 'project',
- summary: 'Opens the IDE for the specified Capacitor native platform project',
+ summary: 'Open the IDE for a given native platform project',
description: `
${chalk.green('ionic capacitor open')} will do the following:
- Open the IDE for your native project (Xcode for iOS, Android Studio for Android)
diff --git a/packages/ionic/src/commands/capacitor/run.ts b/packages/ionic/src/commands/capacitor/run.ts
index 22b550ccef..dab43ca5d5 100644
--- a/packages/ionic/src/commands/capacitor/run.ts
+++ b/packages/ionic/src/commands/capacitor/run.ts
@@ -15,6 +15,13 @@ import { CapacitorCommand } from './base';
export class RunCommand extends CapacitorCommand implements CommandPreRun {
async getMetadata(): Promise {
let groups: string[] = [CommandGroup.Beta];
+ const exampleCommands = [
+ '',
+ 'android',
+ 'android -l',
+ 'ios --livereload',
+ 'ios --livereload-url=http://localhost:8100',
+ ].sort();
const options: CommandMetadataOption[] = [
// Build Options
{
@@ -30,6 +37,10 @@ export class RunCommand extends CapacitorCommand implements CommandPreRun {
type: Boolean,
aliases: ['l'],
},
+ {
+ name: 'livereload-url',
+ summary: 'Provide a custom URL to the dev server',
+ },
];
const serveRunner = this.project && await this.project.getServeRunner();
@@ -51,7 +62,7 @@ export class RunCommand extends CapacitorCommand implements CommandPreRun {
return {
name: 'run',
type: 'project',
- summary: 'Copies web assets to each Capacitor native platform',
+ summary: 'Run an Ionic project on a connected device',
description: `
${chalk.green('ionic capacitor run')} will do the following:
- Perform ${chalk.green('ionic build')} (or run the dev server from ${chalk.green('ionic serve')} with the ${chalk.green('--livereload')} option)
@@ -64,10 +75,7 @@ For Android and iOS, you can setup Remote Debugging on your device with browser
${chalk.cyan('[1]')}: ${chalk.bold('https://ionicframework.com/docs/developer-resources/developer-tips/')}
`,
- exampleCommands: [
- '',
- '-l',
- ],
+ exampleCommands,
inputs: [
{
name: 'platform',
@@ -94,6 +102,15 @@ ${chalk.cyan('[1]')}: ${chalk.bold('https://ionicframework.com/docs/developer-re
inputs[0] = platform.trim();
}
+ if (options['livereload-url']) {
+ options['livereload'] = true;
+ }
+
+ if (!options['build'] && options['livereload']) {
+ this.env.log.warn(`No livereload with ${chalk.green('--no-build')}.`);
+ options['livereload'] = false;
+ }
+
await this.checkForPlatformInstallation(inputs[0]);
}
@@ -105,21 +122,28 @@ ${chalk.cyan('[1]')}: ${chalk.bold('https://ionicframework.com/docs/developer-re
const [ platform ] = inputs;
if (options['livereload']) {
- const conf = new CapacitorConfig(path.resolve(this.project.directory, CAPACITOR_CONFIG_FILE));
+ let livereloadUrl = options['livereload-url'] ? String(options['livereload-url']) : undefined;
+
+ if (!livereloadUrl) {
+ // TODO: use runner directly
+ const details = await serve({ flags: this.env.flags, config: this.env.config, log: this.env.log, prompt: this.env.prompt, shell: this.env.shell, project: this.project }, inputs, generateOptionsForCapacitorBuild(inputs, options));
- // TODO: use runner directly
- const details = await serve({ flags: this.env.flags, config: this.env.config, log: this.env.log, prompt: this.env.prompt, shell: this.env.shell, project: this.project }, inputs, generateOptionsForCapacitorBuild(inputs, options));
+ if (details.externallyAccessible === false) {
+ 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 ${chalk.bold(details.externalAddress)}.${extra}\n\n`);
+ }
- if (details.externallyAccessible === false) {
- 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 ${chalk.bold(details.externalAddress)}.${extra}\n\n`);
+ livereloadUrl = `${details.protocol || 'http'}://${details.externalAddress}:${details.port}`;
}
- conf.setServerUrl(`${details.protocol || 'http'}://${details.externalAddress}:${details.port}`);
+ const conf = new CapacitorConfig(path.resolve(this.project.directory, CAPACITOR_CONFIG_FILE));
onBeforeExit(async () => {
conf.resetServerUrl();
});
+
+ conf.setServerUrl(livereloadUrl);
+
} else {
if (options['build']) {
// TODO: use runner directly
diff --git a/packages/ionic/src/commands/capacitor/sync.ts b/packages/ionic/src/commands/capacitor/sync.ts
index 4e00179f19..b5524275e5 100644
--- a/packages/ionic/src/commands/capacitor/sync.ts
+++ b/packages/ionic/src/commands/capacitor/sync.ts
@@ -10,7 +10,7 @@ export class SyncCommand extends CapacitorCommand implements CommandPreRun {
return {
name: 'sync',
type: 'project',
- summary: 'Syncs your Capacitor project, equivalent to performing a "copy followed by an "update"',
+ summary: 'Sync (copy + update) an Ionic project',
description: `
${chalk.green('ionic capacitor sync')} will do the following:
- Copy web assets to all Capacitor native platforms
diff --git a/packages/ionic/src/commands/capacitor/update.ts b/packages/ionic/src/commands/capacitor/update.ts
index 87cfc6aa4b..b32447ffce 100644
--- a/packages/ionic/src/commands/capacitor/update.ts
+++ b/packages/ionic/src/commands/capacitor/update.ts
@@ -10,7 +10,7 @@ export class UpdateCommand extends CapacitorCommand implements CommandPreRun {
return {
name: 'update',
type: 'project',
- summary: 'Updates each Capacitor native platform, and installs any Capacitor/Cordova plugins found',
+ summary: 'Update Capacitor native platforms, install Capacitor/Cordova plugins',
description: `
${chalk.green('ionic capacitor update')} will do the following:
- Update each Capacitor native project, such as any dependencies that need updating.
diff --git a/packages/ionic/src/commands/config/get.ts b/packages/ionic/src/commands/config/get.ts
index c5f23622db..980ab41625 100644
--- a/packages/ionic/src/commands/config/get.ts
+++ b/packages/ionic/src/commands/config/get.ts
@@ -1,5 +1,5 @@
import { OptionGroup } from '@ionic/cli-framework';
-import { columnar } from '@ionic/cli-framework/utils/format';
+import { columnar, prettyPath } from '@ionic/cli-framework/utils/format';
import { strcmp } from '@ionic/cli-framework/utils/string';
import chalk from 'chalk';
import * as lodash from 'lodash';
@@ -12,12 +12,14 @@ import { BaseConfigCommand, ConfigContext, getConfigValue } from './base';
export class ConfigGetCommand extends BaseConfigCommand {
async getMetadata(): Promise {
+ const projectFile = this.project ? prettyPath(this.project.filePath) : PROJECT_FILE;
+
return {
name: 'get',
type: 'global',
summary: 'Print config values',
description: `
-This command reads and prints configuration values from the project's ${chalk.bold(PROJECT_FILE)} file. It can also operate on the global CLI configuration (${chalk.bold('~/.ionic/config.json')}) using the ${chalk.green('--global')} option.
+This command reads and prints configuration values from the project's ${chalk.bold(projectFile)} file. It can also operate on the global CLI configuration (${chalk.bold('~/.ionic/config.json')}) using the ${chalk.green('--global')} option.
For nested properties, separate nest levels with dots. For example, the property name ${chalk.green('integrations.cordova')} will look in the ${chalk.bold('integrations')} object for the ${chalk.bold('cordova')} property.
@@ -50,7 +52,7 @@ This command will sanitize config output for known sensitive fields (disabled wh
},
{
name: 'root',
- summary: `Operate on root of ${chalk.bold(PROJECT_FILE)}`,
+ summary: `Operate on root of ${chalk.bold(projectFile)}`,
type: Boolean,
hint: chalk.dim('[multi-app]'),
groups: [OptionGroup.Advanced],
diff --git a/packages/ionic/src/commands/config/index.ts b/packages/ionic/src/commands/config/index.ts
index d173443edd..8648ea3521 100644
--- a/packages/ionic/src/commands/config/index.ts
+++ b/packages/ionic/src/commands/config/index.ts
@@ -1,3 +1,4 @@
+import { prettyPath } from '@ionic/cli-framework/utils/format';
import chalk from 'chalk';
import { PROJECT_FILE } from '../../constants';
@@ -5,13 +6,15 @@ import { CommandMap, Namespace } from '../../lib/namespace';
export class ConfigNamespace extends Namespace {
async getMetadata() {
+ const projectFile = this.project ? prettyPath(this.project.filePath) : PROJECT_FILE;
+
return {
name: 'config',
summary: 'Manage CLI and project config values',
description: `
These commands are used to programmatically read, write, and delete CLI and project config values.
-By default, these commands use your project's ${chalk.bold(PROJECT_FILE)} file.
+By default, these commands use your project's ${chalk.bold(prettyPath(projectFile))} file.
To use these commands for the global CLI config file (${chalk.bold('~/.ionic/config.json')}), use the ${chalk.green('--global')} flag.
`,
diff --git a/packages/ionic/src/commands/config/set.ts b/packages/ionic/src/commands/config/set.ts
index a7f5051b4d..d20141a942 100644
--- a/packages/ionic/src/commands/config/set.ts
+++ b/packages/ionic/src/commands/config/set.ts
@@ -1,4 +1,5 @@
import { OptionGroup, validators } from '@ionic/cli-framework';
+import { prettyPath } from '@ionic/cli-framework/utils/format';
import chalk from 'chalk';
import { PROJECT_FILE } from '../../constants';
@@ -9,12 +10,14 @@ import { BaseConfigCommand, getConfigValue, setConfigValue } from './base';
export class ConfigSetCommand extends BaseConfigCommand {
async getMetadata(): Promise {
+ const projectFile = this.project ? prettyPath(this.project.filePath) : PROJECT_FILE;
+
return {
name: 'set',
type: 'global',
summary: 'Set config values',
description: `
-This command writes configuration values to the project's ${chalk.bold(PROJECT_FILE)} file. It can also operate on the global CLI configuration (${chalk.bold('~/.ionic/config.json')}) using the ${chalk.green('--global')} option.
+This command writes configuration values to the project's ${chalk.bold(prettyPath(projectFile))} file. It can also operate on the global CLI configuration (${chalk.bold('~/.ionic/config.json')}) using the ${chalk.green('--global')} option.
For nested properties, separate nest levels with dots. For example, the property name ${chalk.green('integrations.cordova')} will look in the ${chalk.bold('integrations')} object for the ${chalk.bold('cordova')} property.
@@ -57,7 +60,7 @@ By default, if ${chalk.green('property')} exists and is an object or an array, t
},
{
name: 'root',
- summary: `Operate on root of ${chalk.bold(PROJECT_FILE)}`,
+ summary: `Operate on root of ${chalk.bold(prettyPath(projectFile))}`,
type: Boolean,
hint: chalk.dim('[multi-app]'),
groups: [OptionGroup.Advanced],
diff --git a/packages/ionic/src/commands/config/unset.ts b/packages/ionic/src/commands/config/unset.ts
index 36210f0319..24193d3e95 100644
--- a/packages/ionic/src/commands/config/unset.ts
+++ b/packages/ionic/src/commands/config/unset.ts
@@ -1,4 +1,5 @@
import { OptionGroup, validators } from '@ionic/cli-framework';
+import { prettyPath } from '@ionic/cli-framework/utils/format';
import chalk from 'chalk';
import { PROJECT_FILE } from '../../constants';
@@ -9,12 +10,14 @@ import { BaseConfigCommand, getConfigValue, unsetConfigValue } from './base';
export class ConfigUnsetCommand extends BaseConfigCommand {
async getMetadata(): Promise {
+ const projectFile = this.project ? prettyPath(this.project.filePath) : PROJECT_FILE;
+
return {
name: 'unset',
type: 'global',
summary: 'Delete config values',
description: `
-This command deletes configuration values from the project's ${chalk.bold(PROJECT_FILE)} file. It can also operate on the global CLI configuration (${chalk.bold('~/.ionic/config.json')}) using the ${chalk.green('--global')} option.
+This command deletes configuration values from the project's ${chalk.bold(prettyPath(projectFile))} file. It can also operate on the global CLI configuration (${chalk.bold('~/.ionic/config.json')}) using the ${chalk.green('--global')} option.
For nested properties, separate nest levels with dots. For example, the property name ${chalk.green('integrations.cordova')} will look in the ${chalk.bold('integrations')} object for the ${chalk.bold('cordova')} property.
@@ -36,7 +39,7 @@ For multi-app projects, this command is scoped to the current project by default
},
{
name: 'root',
- summary: `Operate on root of ${chalk.bold(PROJECT_FILE)}`,
+ summary: `Operate on root of ${chalk.bold(prettyPath(projectFile))}`,
type: Boolean,
hint: chalk.dim('[multi-app]'),
groups: [OptionGroup.Advanced],
diff --git a/packages/ionic/src/commands/cordova/build.ts b/packages/ionic/src/commands/cordova/build.ts
index aed0237382..a2683909f6 100644
--- a/packages/ionic/src/commands/cordova/build.ts
+++ b/packages/ionic/src/commands/cordova/build.ts
@@ -10,6 +10,7 @@ import { COMMON_CORDOVA_BUILD_COMMAND_OPTIONS, CORDOVA_BUILD_EXAMPLE_COMMANDS, C
export class BuildCommand extends CordovaCommand implements CommandPreRun {
async getMetadata(): Promise {
+ const exampleCommands = CORDOVA_BUILD_EXAMPLE_COMMANDS.sort();
const options: CommandMetadataOption[] = [
// Build Options
{
@@ -42,7 +43,7 @@ The Cordova CLI requires a separator for platform-specific arguments for Android
${chalk.cyan('[1]')}: ${chalk.bold('https://cordova.apache.org/docs/en/latest/guide/platforms/android/index.html#using-flags')}
${chalk.cyan('[2]')}: ${chalk.bold('https://cordova.apache.org/docs/en/latest/guide/platforms/ios/index.html#using-flags')}
`,
- exampleCommands: CORDOVA_BUILD_EXAMPLE_COMMANDS,
+ exampleCommands,
inputs: [
{
name: 'platform',
diff --git a/packages/ionic/src/commands/cordova/resources.ts b/packages/ionic/src/commands/cordova/resources.ts
index 64ca4965bb..4ef5f603a7 100644
--- a/packages/ionic/src/commands/cordova/resources.ts
+++ b/packages/ionic/src/commands/cordova/resources.ts
@@ -80,16 +80,30 @@ This command uses Ionic servers, so we require you to be logged into your free I
}
}
+ async getBuildPlatforms() {
+ const { getPlatforms } = await import('../../lib/integrations/cordova/project');
+ const { RESOURCES } = await import('../../lib/integrations/cordova/resources');
+
+ debug(`RESOURCES=${Object.keys(RESOURCES).length}`);
+
+ const installedPlatforms = await getPlatforms(this.integration.root);
+ debug(`installedPlatforms=${installedPlatforms.map(e => chalk.bold(e)).join(', ')}`);
+
+ const buildPlatforms = Object.keys(RESOURCES).filter(p => installedPlatforms.includes(p));
+ debug(`buildPlatforms=${buildPlatforms.map(v => chalk.bold(v)).join(', ')}`);
+
+ return buildPlatforms;
+ }
+
async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise