Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): Allow to use capacitor commands in custom platforms #3091

Merged
merged 19 commits into from
Jul 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions cli/src/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Config } from './config';
import { exec } from 'child_process';
import { exec, spawn } from 'child_process';
import { setTimeout } from 'timers';
import { basename, dirname, join, parse, resolve } from 'path';
import { copyAsync, existsAsync, readFileAsync, renameAsync, writeFileAsync } from './util/fs';
Expand Down Expand Up @@ -252,6 +252,21 @@ export function wait(time: number) {
return new Promise((resolve) => setTimeout(resolve, time));
}

export function runPlatformHook(command: string): Promise<string> {
return new Promise((resolve, reject) => {
const cmd = spawn(command, {
stdio: 'inherit',
shell: true
});
cmd.on('close', (code) => {
resolve('');
});
cmd.on('error', (err) => {
reject(err);
});
});
}

export function runCommand(command: string): Promise<string> {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
Expand Down Expand Up @@ -420,7 +435,26 @@ export async function checkPlatformVersions(config: Config, platform: string) {
}
}

export function resolveNode(config: Config, ...pathSegments: any[]): string | null {
export function resolvePlatform(config: Config, platform: string): string | null {
if (platform[0] !== '@') {
const core = resolveNode(config, `@capacitor/${platform}`);

if (core) {
return core;
}

const community = resolveNode(config, `@capacitor-community/${platform}`);

if (community) {
return community;
}
}

// third-party
return resolveNode(config, platform);
}

export function resolveNode(config: Config, ...pathSegments: string[]): string | null {
const id = pathSegments[0];
const path = pathSegments.slice(1);

Expand Down
73 changes: 41 additions & 32 deletions cli/src/tasks/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,59 @@ import { addElectron } from '../electron/add';
import { addIOS, addIOSChecks } from '../ios/add';
import { editProjectSettingsAndroid } from '../android/common';
import { editProjectSettingsIOS } from '../ios/common';
import { check, checkAppConfig, checkPackage, checkWebDir, log, logError, logFatal, logInfo, runTask, writePrettyJSON } from '../common';
import { check, checkAppConfig, checkPackage, checkWebDir, hasYarn, log, logError, logFatal, logInfo, resolvePlatform, runCommand, runPlatformHook, runTask, writePrettyJSON } from '../common';
import { sync } from './sync';

import chalk from 'chalk';
import { resolve } from 'path';

export async function addCommand(config: Config, selectedPlatformName: string) {
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
const platformFolder = resolvePlatform(config, selectedPlatformName);
if (platformFolder) {
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:add`);
log(result);
} else {
logError(`platform ${selectedPlatformName} not found`);
}
} else {
const platformName = await config.askPlatform(
selectedPlatformName,
`Please choose a platform to add:`
);

const platformName = await config.askPlatform(
selectedPlatformName,
`Please choose a platform to add:`
);

if (platformName === config.web.name) {
webWarning();
return;
}
if (platformName === config.web.name) {
webWarning();
return;
}

const existingPlatformDir = config.platformDirExists(platformName);
if (existingPlatformDir) {
logFatal(`"${platformName}" platform already exists.
To add a new "${platformName}" platform, please remove "${existingPlatformDir}" and run this command again.
WARNING! your native IDE project will be completely removed.`);
}
const existingPlatformDir = config.platformDirExists(platformName);
if (existingPlatformDir) {
logFatal(`"${platformName}" platform already exists.
To add a new "${platformName}" platform, please remove "${existingPlatformDir}" and run this command again.
WARNING! your native IDE project will be completely removed.`);
}

try {
await check(
config,
[checkPackage, checkAppConfig, ...addChecks(config, platformName)]
);
await generateCapacitorConfig(config);
await check(config, [checkWebDir]);
await doAdd(config, platformName);
await editPlatforms(config, platformName);
try {
await check(
config,
[checkPackage, checkAppConfig, ...addChecks(config, platformName)]
);
await generateCapacitorConfig(config);
await check(config, [checkWebDir]);
await doAdd(config, platformName);
await editPlatforms(config, platformName);

if (shouldSync(config, platformName)) {
await sync(config, platformName, false);
}
if (shouldSync(config, platformName)) {
await sync(config, platformName, false);
}

if (platformName === config.ios.name || platformName === config.android.name) {
log(chalk`\nNow you can run {green {bold npx cap open ${platformName}}} to launch ${platformName === config.ios.name ? 'Xcode' : 'Android Studio'}`);
if (platformName === config.ios.name || platformName === config.android.name) {
log(chalk`\nNow you can run {green {bold npx cap open ${platformName}}} to launch ${platformName === config.ios.name ? 'Xcode' : 'Android Studio'}`);
}
} catch (e) {
logFatal(e);
}
} catch (e) {
logFatal(e);
}
}

Expand Down
30 changes: 20 additions & 10 deletions cli/src/tasks/copy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Config } from '../config';
import { checkWebDir, logError, logFatal, logInfo, resolveNode, runTask } from '../common';
import { checkWebDir, hasYarn, log, logError, logFatal, logInfo, resolveNode, resolvePlatform, runCommand, runPlatformHook, runTask } from '../common';
import { existsAsync } from '../util/fs';
import { allSerial } from '../util/promise';
import { copyWeb } from '../web/copy';
Expand All @@ -10,15 +10,25 @@ import { getCordovaPlugins, handleCordovaPluginsJS, writeCordovaAndroidManifest
import chalk from 'chalk';

export async function copyCommand(config: Config, selectedPlatformName: string) {
const platforms = config.selectPlatforms(selectedPlatformName);
if (platforms.length === 0) {
logInfo(`There are no platforms to copy yet. Create one with \`capacitor create\`.`);
return;
}
try {
await allSerial(platforms.map(platformName => () => copy(config, platformName)));
} catch (e) {
logError(e);
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
const platformFolder = resolvePlatform(config, selectedPlatformName);
if (platformFolder) {
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:copy`);
log(result);
} else {
logError(`platform ${selectedPlatformName} not found`);
}
} else {
const platforms = config.selectPlatforms(selectedPlatformName);
if (platforms.length === 0) {
logInfo(`There are no platforms to copy yet. Create one with \`capacitor create\`.`);
return;
}
try {
await allSerial(platforms.map(platformName => () => copy(config, platformName)));
} catch (e) {
logError(e);
}
}
}

Expand Down
41 changes: 25 additions & 16 deletions cli/src/tasks/open.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
import { Config } from '../config';
import { logFatal, logInfo, runTask } from '../common';
import { hasYarn, log, logError, logFatal, logInfo, resolvePlatform, runPlatformHook, runTask } from '../common';
import { openAndroid } from '../android/open';
import { openElectron } from '../electron/open';
import { openIOS } from '../ios/open';

export async function openCommand(config: Config, selectedPlatform: string) {
const platforms = config.selectPlatforms(selectedPlatform);
let platformName: string;
if (platforms.length === 0) {
logInfo(`There are no platforms to open yet. Create one with "capacitor add".`);
return;
} else if (platforms.length === 1) {
platformName = platforms[0];
export async function openCommand(config: Config, selectedPlatformName: string) {
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
const platformFolder = resolvePlatform(config, selectedPlatformName);
if (platformFolder) {
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:open`);
log(result);
} else {
logError(`platform ${selectedPlatformName} not found`);
}
} else {
platformName = await config.askPlatform('', `Please choose a platform to open:`);
}

try {
await open(config, platformName);
const platforms = config.selectPlatforms(selectedPlatformName);
let platformName: string;
if (platforms.length === 0) {
logInfo(`There are no platforms to open yet. Create one with "capacitor add".`);
return;
} else if (platforms.length === 1) {
platformName = platforms[0];
} else {
platformName = await config.askPlatform('', `Please choose a platform to open:`);
}

} catch (e) {
logFatal(e);
try {
await open(config, platformName);
} catch (e) {
logFatal(e);
}
}
}

Expand Down
43 changes: 26 additions & 17 deletions cli/src/tasks/sync.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
import { Config } from '../config';
import { copy } from './copy';
import { update, updateChecks } from './update';
import { copy, copyCommand } from './copy';
import { update, updateChecks, updateCommand } from './update';
import { check, checkPackage, checkWebDir, log, logError, logFatal, logInfo } from '../common';

import { allSerial } from '../util/promise';

/**
* Sync is a copy and an update in one.
*/
export async function syncCommand(config: Config, selectedPlatform: string, deployment: boolean) {
const then = +new Date;
const platforms = config.selectPlatforms(selectedPlatform);
if (platforms.length === 0) {
logInfo(`There are no platforms to sync yet. Create one with "capacitor create".`);
return;
}
try {
await check(config, [checkPackage, checkWebDir, ...updateChecks(config, platforms)]);
await allSerial(platforms.map(platformName => () => sync(config, platformName, deployment)));
const now = +new Date;
const diff = (now - then) / 1000;
log(`Sync finished in ${diff}s`);
} catch (e)  {
logFatal(e);
export async function syncCommand(config: Config, selectedPlatformName: string, deployment: boolean) {
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
try {
await copyCommand(config, selectedPlatformName);
} catch (e) {
logError(e);
}
await updateCommand(config, selectedPlatformName, deployment);
} else {
const then = +new Date;
const platforms = config.selectPlatforms(selectedPlatformName);
if (platforms.length === 0) {
logInfo(`There are no platforms to sync yet. Create one with "capacitor create".`);
return;
}
try {
await check(config, [checkPackage, checkWebDir, ...updateChecks(config, platforms)]);
await allSerial(platforms.map(platformName => () => sync(config, platformName, deployment)));
const now = +new Date;
const diff = (now - then) / 1000;
log(`Sync finished in ${diff}s`);
} catch (e)  {
logFatal(e);
}
}
}

Expand Down
46 changes: 28 additions & 18 deletions cli/src/tasks/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,39 @@ import { Config } from '../config';
import { updateAndroid } from '../android/update';
import { updateIOS, updateIOSChecks } from '../ios/update';
import { allSerial } from '../util/promise';
import { CheckFunction, check, checkPackage, log, logError, logFatal, logInfo, runTask } from '../common';
import { CheckFunction, check, checkPackage, hasYarn, log, logError, logFatal, logInfo, resolvePlatform, runCommand, runPlatformHook, runTask } from '../common';

import chalk from 'chalk';

export async function updateCommand(config: Config, selectedPlatformName: string, deployment: boolean) {
const then = +new Date;
const platforms = config.selectPlatforms(selectedPlatformName);
if (platforms.length === 0) {
logInfo(`There are no platforms to update yet. Create one with "capacitor create".`);
return;
}
try {
await check(
config,
[checkPackage, ...updateChecks(config, platforms)]
);
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
const platformFolder = resolvePlatform(config, selectedPlatformName);
if (platformFolder) {
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:update`);
log(result);
} else {
logError(`platform ${selectedPlatformName} not found`);
}
} else {
const then = +new Date;
const platforms = config.selectPlatforms(selectedPlatformName);
if (platforms.length === 0) {
logInfo(`There are no platforms to update yet. Create one with "capacitor create".`);
return;
}
try {
await check(
config,
[checkPackage, ...updateChecks(config, platforms)]
);

await allSerial(platforms.map(platformName => async () => await update(config, platformName, deployment)));
const now = +new Date;
const diff = (now - then) / 1000;
log(`Update finished in ${diff}s`);
} catch (e) {
logFatal(e);
await allSerial(platforms.map(platformName => async () => await update(config, platformName, deployment)));
const now = +new Date;
const diff = (now - then) / 1000;
log(`Update finished in ${diff}s`);
} catch (e) {
logFatal(e);
}
}
}

Expand Down