UNPKG

@ionic/cli

Version:

A tool for creating and developing Ionic Framework mobile apps.

226 lines (225 loc) 9.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Integration = void 0; const tslib_1 = require("tslib"); const utils_fs_1 = require("@ionic/utils-fs"); const chalk_1 = tslib_1.__importDefault(require("chalk")); const debug_1 = require("debug"); const lodash = tslib_1.__importStar(require("lodash")); const os = tslib_1.__importStar(require("os")); const path = tslib_1.__importStar(require("path")); const __1 = require("../"); const color_1 = require("../../color"); const utils_1 = require("./utils"); const debug = (0, debug_1.debug)('ionic:lib:integrations:cordova'); class Integration extends __1.BaseIntegration { constructor() { super(...arguments); this.name = 'cordova'; this.summary = 'Target native iOS and Android with Apache Cordova'; this.archiveUrl = 'https://d2ql0qc7j8u4b2.cloudfront.net/integration-cordova.tar.gz'; } get config() { return new __1.IntegrationConfig(this.e.project.filePath, { pathPrefix: [...this.e.project.pathPrefix, 'integrations', this.name] }); } async add(details) { await (0, utils_1.checkForUnsupportedProject)(this.e.project.type); const handlers = { conflictHandler: async (f, stats) => { const isDirectory = stats.isDirectory(); const filename = `${path.basename(f)}${isDirectory ? '/' : ''}`; const type = isDirectory ? 'directory' : 'file'; const confirm = await this.e.prompt({ type: 'confirm', name: 'confirm', message: `The ${(0, color_1.ancillary)(filename)} ${type} exists in project. Overwrite?`, default: false, }); return confirm; }, onFileCreate: f => { if (!details.quiet) { this.e.log.msg(`${chalk_1.default.green('CREATE')} ${f}`); } }, }; const onFileCreate = handlers.onFileCreate ? handlers.onFileCreate : lodash.noop; const conflictHandler = handlers.conflictHandler ? handlers.conflictHandler : async () => false; const { createRequest, download } = await Promise.resolve().then(() => tslib_1.__importStar(require('../../utils/http'))); const { tar } = await Promise.resolve().then(() => tslib_1.__importStar(require('../../utils/archive'))); this.e.log.info(`Downloading integration ${(0, color_1.input)(this.name)}`); const tmpdir = path.resolve(os.tmpdir(), `ionic-integration-${this.name}`); // TODO: etag if (await (0, utils_fs_1.pathExists)(tmpdir)) { await (0, utils_fs_1.remove)(tmpdir); } await (0, utils_fs_1.mkdirp)(tmpdir); const ws = tar.extract({ cwd: tmpdir }); const { req } = await createRequest('GET', this.archiveUrl, this.e.config.getHTTPConfig()); await download(req, ws, {}); const contents = await (0, utils_fs_1.readdirSafe)(tmpdir); const blacklist = []; debug(`Integration files downloaded to ${(0, color_1.strong)(tmpdir)} (files: ${contents.map(f => (0, color_1.strong)(f)).join(', ')})`); for (const f of contents) { const projectf = path.resolve(this.e.project.directory, f); try { const stats = await (0, utils_fs_1.stat)(projectf); const overwrite = await conflictHandler(projectf, stats); if (!overwrite) { blacklist.push(f); } } catch (e) { if (e.code !== 'ENOENT') { throw e; } } } this.e.log.info(`Copying integrations files to project`); debug(`Blacklist: ${blacklist.map(f => (0, color_1.strong)(f)).join(', ')}`); await (0, utils_fs_1.mkdirp)(details.root); await (0, utils_fs_1.copy)(tmpdir, details.root, { filter: f => { if (f === tmpdir) { return true; } const projectf = f.substring(tmpdir.length + 1); for (const item of blacklist) { if (item.slice(-1) === '/' && `${projectf}/` === item) { return false; } if (projectf.startsWith(item)) { return false; } } onFileCreate(projectf); return true; }, }); await super.add(details); } async getCordovaConfig() { try { return await this.requireConfig(); } catch (e) { // ignore } } async requireConfig() { const { loadCordovaConfig } = await Promise.resolve().then(() => tslib_1.__importStar(require('./config'))); const integration = this.e.project.requireIntegration('cordova'); const conf = await loadCordovaConfig(integration); return conf; } async getInfo() { const { getAndroidSdkToolsVersion } = await Promise.resolve().then(() => tslib_1.__importStar(require('./android'))); const [cordovaVersion, cordovaPlatforms, cordovaPlugins, xcode, iosDeploy, iosSim, androidSdkToolsVersion,] = await (Promise.all([ this.getCordovaVersion(), this.getCordovaPlatformVersions(), this.getCordovaPluginVersions(), this.getXcodebuildVersion(), this.getIOSDeployVersion(), this.getIOSSimVersion(), getAndroidSdkToolsVersion(), ])); const info = [ { group: 'cordova', name: 'Cordova CLI', key: 'cordova_version', value: cordovaVersion || 'not installed' }, { group: 'cordova', name: 'Cordova Platforms', key: 'cordova_platforms', value: cordovaPlatforms }, { group: 'cordova', name: 'Cordova Plugins', value: cordovaPlugins }, ]; if (xcode) { info.push({ group: 'system', name: 'Xcode', key: 'xcode_version', value: xcode }); } if (iosDeploy) { info.push({ group: 'system', name: 'ios-deploy', value: iosDeploy }); } if (iosSim) { info.push({ group: 'system', name: 'ios-sim', value: iosSim }); } if (androidSdkToolsVersion) { info.push({ group: 'system', name: 'Android SDK Tools', key: 'android_sdk_version', value: androidSdkToolsVersion }); } const conf = await this.getCordovaConfig(); if (conf) { const bundleId = conf.getBundleId(); info.push({ group: 'cordova', name: 'Bundle ID', key: 'bundle_id', value: bundleId || 'unknown', hidden: true }); } return info; } async personalize({ name, packageId }) { const conf = await this.requireConfig(); conf.setName(name); if (packageId) { conf.setBundleId(packageId); } await conf.save(); } async getCordovaVersion() { try { const integration = this.e.project.requireIntegration('cordova'); return this.e.shell.cmdinfo('cordova', ['-v', '--no-telemetry', '--no-update-notifier'], { cwd: integration.root }); } catch (e) { debug('Error while getting Cordova version: %O', e); } } async getCordovaPlatformVersions() { try { const integration = this.e.project.requireIntegration('cordova'); const output = await this.e.shell.output('cordova', ['platform', 'ls', '--no-telemetry', '--no-update-notifier'], { cwd: integration.root, showCommand: false }); const platforms = output .replace('Installed platforms:', '') .replace(/Available platforms[\s\S]+/, '') .split('\n') .map(l => l.trim()) .filter(l => l && !l.startsWith('.')); if (platforms.length === 0) { return 'none'; } return platforms.join(', '); } catch (e) { debug('Error while getting Cordova platforms: %O', e); return 'not available'; } } async getCordovaPluginVersions() { const whitelist = [ /^cordova-plugin-ionic$/, /^cordova-plugin-ionic-.+/, ]; try { const integration = this.e.project.requireIntegration('cordova'); const output = await this.e.shell.output('cordova', ['plugin', 'ls', '--no-telemetry', '--no-update-notifier'], { cwd: integration.root, showCommand: false }); const pluginRe = /^([a-z-]+)\s+(\d\.\d\.\d).+$/; const plugins = output .split('\n') .map(l => l.trim().match(pluginRe)) .filter((l) => l !== null) .map(m => [m[1], m[2]]); const whitelistedPlugins = plugins .filter(([plugin, version]) => whitelist.some(re => re.test(plugin))) .map(([plugin, version]) => `${plugin} ${version}`); const count = plugins.length - whitelistedPlugins.length; if (whitelistedPlugins.length === 0) { return `no whitelisted plugins (${count} plugins total)`; } return `${whitelistedPlugins.join(', ')}${count > 0 ? `, (and ${count} other plugins)` : ''}`; } catch (e) { debug('Error while getting Cordova plugins: %O', e); return 'not available'; } } async getXcodebuildVersion() { return this.e.shell.cmdinfo('xcodebuild', ['-version']); } async getIOSDeployVersion() { return this.e.shell.cmdinfo('ios-deploy', ['--version']); } async getIOSSimVersion() { return this.e.shell.cmdinfo('ios-sim', ['--version']); } } exports.Integration = Integration;