Skip to content

Commit c2133c5

Browse files
jcesarmobileimhoffdIT-MikeS
committed
feat(cli): add hooks to capacitor commands for custom platforms (#3091)
Co-authored-by: Dan Imhoff <dwieeb@gmail.com> Co-authored-by: IT-MikeS <20338451+IT-MikeS@users.noreply.github.com>
1 parent 34730d5 commit c2133c5

File tree

6 files changed

+176
-95
lines changed

6 files changed

+176
-95
lines changed

cli/src/common.ts

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Config } from './config';
2-
import { exec } from 'child_process';
2+
import { exec, spawn } from 'child_process';
33
import { setTimeout } from 'timers';
44
import { basename, dirname, join, parse, resolve } from 'path';
55
import { copyAsync, existsAsync, readFileAsync, renameAsync, writeFileAsync } from './util/fs';
@@ -252,6 +252,21 @@ export function wait(time: number) {
252252
return new Promise((resolve) => setTimeout(resolve, time));
253253
}
254254

255+
export function runPlatformHook(command: string): Promise<string> {
256+
return new Promise((resolve, reject) => {
257+
const cmd = spawn(command, {
258+
stdio: 'inherit',
259+
shell: true
260+
});
261+
cmd.on('close', (code) => {
262+
resolve('');
263+
});
264+
cmd.on('error', (err) => {
265+
reject(err);
266+
});
267+
});
268+
}
269+
255270
export function runCommand(command: string): Promise<string> {
256271
return new Promise((resolve, reject) => {
257272
exec(command, (error, stdout, stderr) => {
@@ -420,7 +435,26 @@ export async function checkPlatformVersions(config: Config, platform: string) {
420435
}
421436
}
422437

423-
export function resolveNode(config: Config, ...pathSegments: any[]): string | null {
438+
export function resolvePlatform(config: Config, platform: string): string | null {
439+
if (platform[0] !== '@') {
440+
const core = resolveNode(config, `@capacitor/${platform}`);
441+
442+
if (core) {
443+
return core;
444+
}
445+
446+
const community = resolveNode(config, `@capacitor-community/${platform}`);
447+
448+
if (community) {
449+
return community;
450+
}
451+
}
452+
453+
// third-party
454+
return resolveNode(config, platform);
455+
}
456+
457+
export function resolveNode(config: Config, ...pathSegments: string[]): string | null {
424458
const id = pathSegments[0];
425459
const path = pathSegments.slice(1);
426460

cli/src/tasks/add.ts

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,50 +5,59 @@ import { addElectron } from '../electron/add';
55
import { addIOS, addIOSChecks } from '../ios/add';
66
import { editProjectSettingsAndroid } from '../android/common';
77
import { editProjectSettingsIOS } from '../ios/common';
8-
import { check, checkAppConfig, checkPackage, checkWebDir, log, logError, logFatal, logInfo, runTask, writePrettyJSON } from '../common';
8+
import { check, checkAppConfig, checkPackage, checkWebDir, hasYarn, log, logError, logFatal, logInfo, resolvePlatform, runCommand, runPlatformHook, runTask, writePrettyJSON } from '../common';
99
import { sync } from './sync';
1010

1111
import chalk from 'chalk';
1212
import { resolve } from 'path';
1313

1414
export async function addCommand(config: Config, selectedPlatformName: string) {
15+
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
16+
const platformFolder = resolvePlatform(config, selectedPlatformName);
17+
if (platformFolder) {
18+
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:add`);
19+
log(result);
20+
} else {
21+
logError(`platform ${selectedPlatformName} not found`);
22+
}
23+
} else {
24+
const platformName = await config.askPlatform(
25+
selectedPlatformName,
26+
`Please choose a platform to add:`
27+
);
1528

16-
const platformName = await config.askPlatform(
17-
selectedPlatformName,
18-
`Please choose a platform to add:`
19-
);
20-
21-
if (platformName === config.web.name) {
22-
webWarning();
23-
return;
24-
}
29+
if (platformName === config.web.name) {
30+
webWarning();
31+
return;
32+
}
2533

26-
const existingPlatformDir = config.platformDirExists(platformName);
27-
if (existingPlatformDir) {
28-
logFatal(`"${platformName}" platform already exists.
29-
To add a new "${platformName}" platform, please remove "${existingPlatformDir}" and run this command again.
30-
WARNING! your native IDE project will be completely removed.`);
31-
}
34+
const existingPlatformDir = config.platformDirExists(platformName);
35+
if (existingPlatformDir) {
36+
logFatal(`"${platformName}" platform already exists.
37+
To add a new "${platformName}" platform, please remove "${existingPlatformDir}" and run this command again.
38+
WARNING! your native IDE project will be completely removed.`);
39+
}
3240

33-
try {
34-
await check(
35-
config,
36-
[checkPackage, checkAppConfig, ...addChecks(config, platformName)]
37-
);
38-
await generateCapacitorConfig(config);
39-
await check(config, [checkWebDir]);
40-
await doAdd(config, platformName);
41-
await editPlatforms(config, platformName);
41+
try {
42+
await check(
43+
config,
44+
[checkPackage, checkAppConfig, ...addChecks(config, platformName)]
45+
);
46+
await generateCapacitorConfig(config);
47+
await check(config, [checkWebDir]);
48+
await doAdd(config, platformName);
49+
await editPlatforms(config, platformName);
4250

43-
if (shouldSync(config, platformName)) {
44-
await sync(config, platformName, false);
45-
}
51+
if (shouldSync(config, platformName)) {
52+
await sync(config, platformName, false);
53+
}
4654

47-
if (platformName === config.ios.name || platformName === config.android.name) {
48-
log(chalk`\nNow you can run {green {bold npx cap open ${platformName}}} to launch ${platformName === config.ios.name ? 'Xcode' : 'Android Studio'}`);
55+
if (platformName === config.ios.name || platformName === config.android.name) {
56+
log(chalk`\nNow you can run {green {bold npx cap open ${platformName}}} to launch ${platformName === config.ios.name ? 'Xcode' : 'Android Studio'}`);
57+
}
58+
} catch (e) {
59+
logFatal(e);
4960
}
50-
} catch (e) {
51-
logFatal(e);
5261
}
5362
}
5463

cli/src/tasks/copy.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Config } from '../config';
2-
import { checkWebDir, logError, logFatal, logInfo, resolveNode, runTask } from '../common';
2+
import { checkWebDir, hasYarn, log, logError, logFatal, logInfo, resolveNode, resolvePlatform, runCommand, runPlatformHook, runTask } from '../common';
33
import { existsAsync } from '../util/fs';
44
import { allSerial } from '../util/promise';
55
import { copyWeb } from '../web/copy';
@@ -10,15 +10,25 @@ import { getCordovaPlugins, handleCordovaPluginsJS, writeCordovaAndroidManifest
1010
import chalk from 'chalk';
1111

1212
export async function copyCommand(config: Config, selectedPlatformName: string) {
13-
const platforms = config.selectPlatforms(selectedPlatformName);
14-
if (platforms.length === 0) {
15-
logInfo(`There are no platforms to copy yet. Create one with \`capacitor create\`.`);
16-
return;
17-
}
18-
try {
19-
await allSerial(platforms.map(platformName => () => copy(config, platformName)));
20-
} catch (e) {
21-
logError(e);
13+
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
14+
const platformFolder = resolvePlatform(config, selectedPlatformName);
15+
if (platformFolder) {
16+
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:copy`);
17+
log(result);
18+
} else {
19+
logError(`platform ${selectedPlatformName} not found`);
20+
}
21+
} else {
22+
const platforms = config.selectPlatforms(selectedPlatformName);
23+
if (platforms.length === 0) {
24+
logInfo(`There are no platforms to copy yet. Create one with \`capacitor create\`.`);
25+
return;
26+
}
27+
try {
28+
await allSerial(platforms.map(platformName => () => copy(config, platformName)));
29+
} catch (e) {
30+
logError(e);
31+
}
2232
}
2333
}
2434

cli/src/tasks/open.ts

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
import { Config } from '../config';
2-
import { logFatal, logInfo, runTask } from '../common';
2+
import { hasYarn, log, logError, logFatal, logInfo, resolvePlatform, runPlatformHook, runTask } from '../common';
33
import { openAndroid } from '../android/open';
44
import { openElectron } from '../electron/open';
55
import { openIOS } from '../ios/open';
66

7-
export async function openCommand(config: Config, selectedPlatform: string) {
8-
const platforms = config.selectPlatforms(selectedPlatform);
9-
let platformName: string;
10-
if (platforms.length === 0) {
11-
logInfo(`There are no platforms to open yet. Create one with "capacitor add".`);
12-
return;
13-
} else if (platforms.length === 1) {
14-
platformName = platforms[0];
7+
export async function openCommand(config: Config, selectedPlatformName: string) {
8+
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
9+
const platformFolder = resolvePlatform(config, selectedPlatformName);
10+
if (platformFolder) {
11+
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:open`);
12+
log(result);
13+
} else {
14+
logError(`platform ${selectedPlatformName} not found`);
15+
}
1516
} else {
16-
platformName = await config.askPlatform('', `Please choose a platform to open:`);
17-
}
18-
19-
try {
20-
await open(config, platformName);
17+
const platforms = config.selectPlatforms(selectedPlatformName);
18+
let platformName: string;
19+
if (platforms.length === 0) {
20+
logInfo(`There are no platforms to open yet. Create one with "capacitor add".`);
21+
return;
22+
} else if (platforms.length === 1) {
23+
platformName = platforms[0];
24+
} else {
25+
platformName = await config.askPlatform('', `Please choose a platform to open:`);
26+
}
2127

22-
} catch (e) {
23-
logFatal(e);
28+
try {
29+
await open(config, platformName);
30+
} catch (e) {
31+
logFatal(e);
32+
}
2433
}
2534
}
2635

cli/src/tasks/sync.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,37 @@
11
import { Config } from '../config';
2-
import { copy } from './copy';
3-
import { update, updateChecks } from './update';
2+
import { copy, copyCommand } from './copy';
3+
import { update, updateChecks, updateCommand } from './update';
44
import { check, checkPackage, checkWebDir, log, logError, logFatal, logInfo } from '../common';
55

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

88
/**
99
* Sync is a copy and an update in one.
1010
*/
11-
export async function syncCommand(config: Config, selectedPlatform: string, deployment: boolean) {
12-
const then = +new Date;
13-
const platforms = config.selectPlatforms(selectedPlatform);
14-
if (platforms.length === 0) {
15-
logInfo(`There are no platforms to sync yet. Create one with "capacitor create".`);
16-
return;
17-
}
18-
try {
19-
await check(config, [checkPackage, checkWebDir, ...updateChecks(config, platforms)]);
20-
await allSerial(platforms.map(platformName => () => sync(config, platformName, deployment)));
21-
const now = +new Date;
22-
const diff = (now - then) / 1000;
23-
log(`Sync finished in ${diff}s`);
24-
} catch (e)  {
25-
logFatal(e);
11+
export async function syncCommand(config: Config, selectedPlatformName: string, deployment: boolean) {
12+
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
13+
try {
14+
await copyCommand(config, selectedPlatformName);
15+
} catch (e) {
16+
logError(e);
17+
}
18+
await updateCommand(config, selectedPlatformName, deployment);
19+
} else {
20+
const then = +new Date;
21+
const platforms = config.selectPlatforms(selectedPlatformName);
22+
if (platforms.length === 0) {
23+
logInfo(`There are no platforms to sync yet. Create one with "capacitor create".`);
24+
return;
25+
}
26+
try {
27+
await check(config, [checkPackage, checkWebDir, ...updateChecks(config, platforms)]);
28+
await allSerial(platforms.map(platformName => () => sync(config, platformName, deployment)));
29+
const now = +new Date;
30+
const diff = (now - then) / 1000;
31+
log(`Sync finished in ${diff}s`);
32+
} catch (e)  {
33+
logFatal(e);
34+
}
2635
}
2736
}
2837

cli/src/tasks/update.ts

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,39 @@ import { Config } from '../config';
22
import { updateAndroid } from '../android/update';
33
import { updateIOS, updateIOSChecks } from '../ios/update';
44
import { allSerial } from '../util/promise';
5-
import { CheckFunction, check, checkPackage, log, logError, logFatal, logInfo, runTask } from '../common';
5+
import { CheckFunction, check, checkPackage, hasYarn, log, logError, logFatal, logInfo, resolvePlatform, runCommand, runPlatformHook, runTask } from '../common';
66

77
import chalk from 'chalk';
88

99
export async function updateCommand(config: Config, selectedPlatformName: string, deployment: boolean) {
10-
const then = +new Date;
11-
const platforms = config.selectPlatforms(selectedPlatformName);
12-
if (platforms.length === 0) {
13-
logInfo(`There are no platforms to update yet. Create one with "capacitor create".`);
14-
return;
15-
}
16-
try {
17-
await check(
18-
config,
19-
[checkPackage, ...updateChecks(config, platforms)]
20-
);
10+
if (selectedPlatformName && !config.isValidPlatform(selectedPlatformName)) {
11+
const platformFolder = resolvePlatform(config, selectedPlatformName);
12+
if (platformFolder) {
13+
const result = await runPlatformHook(`cd "${platformFolder}" && ${await hasYarn(config) ? 'yarn' : 'npm'} run capacitor:update`);
14+
log(result);
15+
} else {
16+
logError(`platform ${selectedPlatformName} not found`);
17+
}
18+
} else {
19+
const then = +new Date;
20+
const platforms = config.selectPlatforms(selectedPlatformName);
21+
if (platforms.length === 0) {
22+
logInfo(`There are no platforms to update yet. Create one with "capacitor create".`);
23+
return;
24+
}
25+
try {
26+
await check(
27+
config,
28+
[checkPackage, ...updateChecks(config, platforms)]
29+
);
2130

22-
await allSerial(platforms.map(platformName => async () => await update(config, platformName, deployment)));
23-
const now = +new Date;
24-
const diff = (now - then) / 1000;
25-
log(`Update finished in ${diff}s`);
26-
} catch (e) {
27-
logFatal(e);
31+
await allSerial(platforms.map(platformName => async () => await update(config, platformName, deployment)));
32+
const now = +new Date;
33+
const diff = (now - then) / 1000;
34+
log(`Update finished in ${diff}s`);
35+
} catch (e) {
36+
logFatal(e);
37+
}
2838
}
2939
}
3040

0 commit comments

Comments
 (0)