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): support capacitor portals plugin changes needed #5558

Merged
merged 14 commits into from
Apr 21, 2022
16 changes: 16 additions & 0 deletions cli/src/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ export interface CapacitorConfig {
includePlugins?: string[];
}

export interface Portal {
name: string;
webDir: string;
appId?: string;
}

export interface PluginsConfig {
/**
* Plugin configuration by class name.
Expand All @@ -485,4 +491,14 @@ export interface PluginsConfig {
[key: string]: any;
}
| undefined;

/**
* Capacitor Portals plugin configuration
*
* @since 3.5.0
*/
Portals?: {
shell: Portal;
apps: Portal[];
};
}
3 changes: 2 additions & 1 deletion cli/src/definitions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CapacitorConfig } from './declarations';
import type { CapacitorConfig, PluginsConfig } from './declarations';

type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> };

Expand Down Expand Up @@ -119,6 +119,7 @@ export interface Config {
readonly web: WebConfig;
readonly cli: CLIConfig;
readonly app: AppConfig;
readonly plugins?: PluginsConfig;
}

export interface FrameworkConfig {
Expand Down
81 changes: 75 additions & 6 deletions cli/src/tasks/copy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { copy as fsCopy, pathExists, remove, writeJSON } from '@ionic/utils-fs';
import { basename, join, relative } from 'path';
import { basename, join, relative, resolve } from 'path';

import c from '../colors';
import {
Expand All @@ -15,9 +15,11 @@ import {
handleCordovaPluginsJS,
writeCordovaAndroidManifest,
} from '../cordova';
import type { Portal } from '../declarations';
import type { Config } from '../definitions';
import { isFatal } from '../errors';
import { logger } from '../log';
import { getPlugins } from '../plugin';
import { allSerial } from '../util/promise';
import { copyWeb } from '../web/copy';

Expand Down Expand Up @@ -70,23 +72,56 @@ export async function copy(
'capacitor:copy:before',
);

const allPlugins = await getPlugins(config, platformName);
let usesCapacitorPortals = false;
if (
allPlugins.filter(
plugin => plugin.id === '@ionic-enterprise/capacitor-portals',
).length > 0
) {
usesCapacitorPortals = true;
}

if (platformName === config.ios.name) {
await copyWebDir(config, await config.ios.webDirAbs);
if (usesCapacitorPortals) {
await copyFederatedWebDirs(config, await config.ios.webDirAbs);
} else {
await copyWebDir(
config,
await config.ios.webDirAbs,
config.app.webDirAbs,
);
}
await copyCapacitorConfig(config, config.ios.nativeTargetDirAbs);
const cordovaPlugins = await getCordovaPlugins(config, platformName);
await handleCordovaPluginsJS(cordovaPlugins, config, platformName);
} else if (platformName === config.android.name) {
await copyWebDir(config, config.android.webDirAbs);
if (usesCapacitorPortals) {
await copyFederatedWebDirs(config, config.android.webDirAbs);
} else {
await copyWebDir(
config,
config.android.webDirAbs,
config.app.webDirAbs,
);
}
await copyCapacitorConfig(config, config.android.assetsDirAbs);
const cordovaPlugins = await getCordovaPlugins(config, platformName);
await handleCordovaPluginsJS(cordovaPlugins, config, platformName);
await writeCordovaAndroidManifest(cordovaPlugins, config, platformName);
} else if (platformName === config.web.name) {
await copyWeb(config);
if (usesCapacitorPortals) {
logger.info(
'Capacitor Portals Plugin installed, skipping web bundling...',
);
} else {
await copyWeb(config);
}
} else {
throw `Platform ${platformName} is not valid.`;
}
});

await runPlatformHook(
config,
platformName,
Expand All @@ -110,8 +145,11 @@ async function copyCapacitorConfig(config: Config, nativeAbsDir: string) {
);
}

async function copyWebDir(config: Config, nativeAbsDir: string) {
const webAbsDir = config.app.webDirAbs;
async function copyWebDir(
config: Config,
nativeAbsDir: string,
webAbsDir: string,
) {
const webRelDir = basename(webAbsDir);
const nativeRelDir = relative(config.app.rootDir, nativeAbsDir);

Expand All @@ -138,3 +176,34 @@ async function copyWebDir(config: Config, nativeAbsDir: string) {
},
);
}

async function copyFederatedWebDirs(config: Config, nativeAbsDir: string) {
logger.info('Capacitor Portals Plugin Loaded - Copying Web Assets');

if (!config.app.extConfig?.plugins?.Portals) {
throw `Capacitor Portals plugin is present but no valid config is defined.`;
}

const portalsConfig = config.app.extConfig.plugins.Portals;
if (!isPortal(portalsConfig.shell)) {
throw `Capacitor Portals plugin is present but no valid Shell application is defined in the config.`;
}

if (!portalsConfig.apps.every(isPortal)) {
throw `Capacitor Portals plugin is present but there is a problem with the apps defined in the config.`;
}

await Promise.all(
[...portalsConfig.apps, portalsConfig.shell].map(app => {
const appDir = resolve(config.app.rootDir, app.webDir);
return copyWebDir(config, resolve(nativeAbsDir, app.name), appDir);
}),
);
}

function isPortal(config: any): config is Portal {
return (
(config as Portal).webDir !== undefined &&
(config as Portal).name !== undefined
);
}