react-klasha
Version:
This is an reactJS library for implementing klasha payment gateway
526 lines (525 loc) • 24.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeCordovaAndroidManifest = exports.getCordovaPreferences = exports.getIncompatibleCordovaPlugins = exports.checkPluginDependencies = exports.logCordovaManualSteps = exports.getCordovaPlugins = exports.handleCordovaPluginsJS = exports.autoGenerateConfig = exports.removePluginFiles = exports.createEmptyCordovaJS = exports.copyCordovaJS = exports.copyPluginsJS = exports.generateCordovaPluginsJSFile = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const plist_1 = tslib_1.__importDefault(require("plist"));
const prompts_1 = tslib_1.__importDefault(require("prompts"));
const common_1 = require("./android/common");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const errors_1 = require("./errors");
const common_2 = require("./ios/common");
const log_1 = require("./log");
const plugin_1 = require("./plugin");
const node_1 = require("./util/node");
const term_1 = require("./util/term");
const xml_1 = require("./util/xml");
/**
* Build the root cordova_plugins.js file referencing each Plugin JS file.
*/
function generateCordovaPluginsJSFile(config, plugins, platform) {
const pluginModules = [];
const pluginExports = [];
plugins.map(p => {
const pluginId = p.xml.$.id;
const jsModules = plugin_1.getJSModules(p, platform);
jsModules.map((jsModule) => {
const clobbers = [];
const merges = [];
let clobbersModule = '';
let mergesModule = '';
let runsModule = '';
let clobberKey = '';
let mergeKey = '';
if (jsModule.clobbers) {
jsModule.clobbers.map((clobber) => {
clobbers.push(clobber.$.target);
clobberKey = clobber.$.target;
});
clobbersModule = `,
"clobbers": [
"${clobbers.join('",\n "')}"
]`;
}
if (jsModule.merges) {
jsModule.merges.map((merge) => {
merges.push(merge.$.target);
mergeKey = merge.$.target;
});
mergesModule = `,
"merges": [
"${merges.join('",\n "')}"
]`;
}
if (jsModule.runs) {
runsModule = ',\n "runs": true';
}
const pluginModule = {
clobber: clobberKey,
merge: mergeKey,
// mimics Cordova's module name logic if the name attr is missing
pluginContent: `{
"id": "${pluginId +
'.' +
(jsModule.$.name || jsModule.$.src.match(/([^/]+)\.js/)[1])}",
"file": "plugins/${pluginId}/${jsModule.$.src}",
"pluginId": "${pluginId}"${clobbersModule}${mergesModule}${runsModule}
}`,
};
pluginModules.push(pluginModule);
});
pluginExports.push(`"${pluginId}": "${p.xml.$.version}"`);
});
return `
cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
${pluginModules
.sort((a, b) => a.clobber && b.clobber // Clobbers in alpha order
? a.clobber.localeCompare(b.clobber)
: a.clobber || b.clobber // Clobbers before anything else
? b.clobber.localeCompare(a.clobber)
: a.merge.localeCompare(b.merge))
.map(e => e.pluginContent)
.join(',\n ')}
];
module.exports.metadata =
// TOP OF METADATA
{
${pluginExports.join(',\n ')}
};
// BOTTOM OF METADATA
});
`;
}
exports.generateCordovaPluginsJSFile = generateCordovaPluginsJSFile;
/**
* Build the plugins/* files for each Cordova plugin installed.
*/
async function copyPluginsJS(config, cordovaPlugins, platform) {
const webDir = await getWebDir(config, platform);
const pluginsDir = path_1.join(webDir, 'plugins');
const cordovaPluginsJSFile = path_1.join(webDir, 'cordova_plugins.js');
await removePluginFiles(config, platform);
await Promise.all(cordovaPlugins.map(async (p) => {
const pluginId = p.xml.$.id;
const pluginDir = path_1.join(pluginsDir, pluginId, 'www');
await utils_fs_1.ensureDir(pluginDir);
const jsModules = plugin_1.getJSModules(p, platform);
await Promise.all(jsModules.map(async (jsModule) => {
const filePath = path_1.join(webDir, 'plugins', pluginId, jsModule.$.src);
await utils_fs_1.copy(path_1.join(p.rootPath, jsModule.$.src), filePath);
let data = await utils_fs_1.readFile(filePath, { encoding: 'utf-8' });
data = data.trim();
// mimics Cordova's module name logic if the name attr is missing
const name = pluginId +
'.' +
(jsModule.$.name ||
path_1.basename(jsModule.$.src, path_1.extname(jsModule.$.src)));
data = `cordova.define("${name}", function(require, exports, module) { \n${data}\n});`;
data = data.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script\s*>/gi, '');
await utils_fs_1.writeFile(filePath, data, { encoding: 'utf-8' });
}));
const assets = plugin_1.getAssets(p, platform);
await Promise.all(assets.map(async (asset) => {
const filePath = path_1.join(webDir, asset.$.target);
await utils_fs_1.copy(path_1.join(p.rootPath, asset.$.src), filePath);
}));
}));
await utils_fs_1.writeFile(cordovaPluginsJSFile, generateCordovaPluginsJSFile(config, cordovaPlugins, platform));
}
exports.copyPluginsJS = copyPluginsJS;
async function copyCordovaJS(config, platform) {
const cordovaPath = node_1.resolveNode(config.app.rootDir, '@capacitor/core', 'cordova.js');
if (!cordovaPath) {
errors_1.fatal(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/core/cordova.js')}.\n` + `Are you sure ${colors_1.default.strong('@capacitor/core')} is installed?`);
}
return utils_fs_1.copy(cordovaPath, path_1.join(await getWebDir(config, platform), 'cordova.js'));
}
exports.copyCordovaJS = copyCordovaJS;
async function createEmptyCordovaJS(config, platform) {
const webDir = await getWebDir(config, platform);
await utils_fs_1.writeFile(path_1.join(webDir, 'cordova.js'), '');
await utils_fs_1.writeFile(path_1.join(webDir, 'cordova_plugins.js'), '');
}
exports.createEmptyCordovaJS = createEmptyCordovaJS;
async function removePluginFiles(config, platform) {
const webDir = await getWebDir(config, platform);
const pluginsDir = path_1.join(webDir, 'plugins');
const cordovaPluginsJSFile = path_1.join(webDir, 'cordova_plugins.js');
await utils_fs_1.remove(pluginsDir);
await utils_fs_1.remove(cordovaPluginsJSFile);
}
exports.removePluginFiles = removePluginFiles;
async function autoGenerateConfig(config, cordovaPlugins, platform) {
var _a, _b;
let xmlDir = path_1.join(config.android.resDirAbs, 'xml');
const fileName = 'config.xml';
if (platform === 'ios') {
xmlDir = config.ios.nativeTargetDirAbs;
}
await utils_fs_1.ensureDir(xmlDir);
const cordovaConfigXMLFile = path_1.join(xmlDir, fileName);
await utils_fs_1.remove(cordovaConfigXMLFile);
const pluginEntries = [];
cordovaPlugins.map(p => {
const currentPlatform = plugin_1.getPluginPlatform(p, platform);
if (currentPlatform) {
const configFiles = currentPlatform['config-file'];
if (configFiles) {
const configXMLEntries = configFiles.filter(function (item) {
var _a;
return (_a = item.$) === null || _a === void 0 ? void 0 : _a.target.includes(fileName);
});
configXMLEntries.map((entry) => {
if (entry.feature) {
const feature = { feature: entry.feature };
pluginEntries.push(feature);
}
});
}
}
});
const pluginEntriesString = await Promise.all(pluginEntries.map(async (item) => {
const xmlString = await xml_1.writeXML(item);
return xmlString;
}));
let pluginPreferencesString = [];
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.preferences) {
pluginPreferencesString = await Promise.all(Object.entries(config.app.extConfig.cordova.preferences).map(async ([key, value]) => {
return `
<preference name="${key}" value="${value}" />`;
}));
}
const content = `<?xml version='1.0' encoding='utf-8'?>
<widget version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<access origin="*" />
${pluginEntriesString.join('')}
${pluginPreferencesString.join('')}
</widget>`;
await utils_fs_1.writeFile(cordovaConfigXMLFile, content);
}
exports.autoGenerateConfig = autoGenerateConfig;
async function getWebDir(config, platform) {
if (platform === 'ios') {
return config.ios.webDirAbs;
}
if (platform === 'android') {
return config.android.webDirAbs;
}
return '';
}
async function handleCordovaPluginsJS(cordovaPlugins, config, platform) {
const webDir = await getWebDir(config, platform);
await utils_fs_1.mkdirp(webDir);
if (cordovaPlugins.length > 0) {
plugin_1.printPlugins(cordovaPlugins, platform, 'cordova');
await copyCordovaJS(config, platform);
await copyPluginsJS(config, cordovaPlugins, platform);
}
else {
await removePluginFiles(config, platform);
await createEmptyCordovaJS(config, platform);
}
await autoGenerateConfig(config, cordovaPlugins, platform);
}
exports.handleCordovaPluginsJS = handleCordovaPluginsJS;
async function getCordovaPlugins(config, platform) {
const allPlugins = await plugin_1.getPlugins(config, platform);
let plugins = [];
if (platform === config.ios.name) {
plugins = await common_2.getIOSPlugins(allPlugins);
}
else if (platform === config.android.name) {
plugins = await common_1.getAndroidPlugins(allPlugins);
}
return plugins.filter(p => plugin_1.getPluginType(p, platform) === 1 /* Cordova */);
}
exports.getCordovaPlugins = getCordovaPlugins;
async function logCordovaManualSteps(cordovaPlugins, config, platform) {
cordovaPlugins.map(p => {
const editConfig = plugin_1.getPlatformElement(p, platform, 'edit-config');
const configFile = plugin_1.getPlatformElement(p, platform, 'config-file');
editConfig.concat(configFile).map(async (configElement) => {
if (configElement.$ && !configElement.$.target.includes('config.xml')) {
if (platform === config.ios.name) {
if (configElement.$.target.includes('Info.plist')) {
logiOSPlist(configElement, config, p);
}
}
}
});
});
}
exports.logCordovaManualSteps = logCordovaManualSteps;
async function logiOSPlist(configElement, config, plugin) {
const plistPath = path_1.resolve(config.ios.nativeTargetDirAbs, 'Info.plist');
const xmlMeta = await xml_1.readXML(plistPath);
const data = await utils_fs_1.readFile(plistPath, { encoding: 'utf-8' });
const plistData = plist_1.default.parse(data);
const dict = xmlMeta.plist.dict.pop();
if (!dict.key.includes(configElement.$.parent)) {
let xml = buildConfigFileXml(configElement);
xml = `<key>${configElement.$.parent}</key>${getConfigFileTagContent(xml)}`;
log_1.logger.warn(`Configuration required for ${colors_1.default.strong(plugin.id)}.\n` +
`Add the following to Info.plist:\n` +
xml);
}
else if (configElement.array || configElement.dict) {
if (configElement.array &&
configElement.array.length > 0 &&
configElement.array[0].string) {
let xml = '';
configElement.array[0].string.map((element) => {
const d = plistData[configElement.$.parent];
if (Array.isArray(d) && !d.includes(element)) {
xml = xml.concat(`<string>${element}</string>\n`);
}
});
if (xml.length > 0) {
log_1.logger.warn(`Configuration required for ${colors_1.default.strong(plugin.id)}.\n` +
`Add the following in the existing ${colors_1.default.strong(configElement.$.parent)} array of your Info.plist:\n` +
xml);
}
}
else {
logPossibleMissingItem(configElement, plugin);
}
}
}
function logPossibleMissingItem(configElement, plugin) {
let xml = buildConfigFileXml(configElement);
xml = getConfigFileTagContent(xml);
xml = removeOuterTags(xml);
log_1.logger.warn(`Configuration might be missing for ${colors_1.default.strong(plugin.id)}.\n` +
`Add the following to the existing ${colors_1.default.strong(configElement.$.parent)} entry of Info.plist:\n` +
xml);
}
function buildConfigFileXml(configElement) {
return xml_1.buildXmlElement(configElement, 'config-file');
}
function getConfigFileTagContent(str) {
return str.replace(/<config-file.+">|<\/config-file>/g, '');
}
function removeOuterTags(str) {
const start = str.indexOf('>') + 1;
const end = str.lastIndexOf('<');
return str.substring(start, end);
}
async function checkPluginDependencies(plugins, platform) {
const pluginDeps = new Map();
const cordovaPlugins = plugins.filter(p => plugin_1.getPluginType(p, platform) === 1 /* Cordova */);
const incompatible = plugins.filter(p => plugin_1.getPluginType(p, platform) === 2 /* Incompatible */);
await Promise.all(cordovaPlugins.map(async (p) => {
let allDependencies = [];
allDependencies = allDependencies.concat(plugin_1.getPlatformElement(p, platform, 'dependency'));
if (p.xml['dependency']) {
allDependencies = allDependencies.concat(p.xml['dependency']);
}
allDependencies = allDependencies.filter((dep) => !getIncompatibleCordovaPlugins(platform).includes(dep.$.id) &&
incompatible.filter(p => p.id === dep.$.id || p.xml.$.id === dep.$.id)
.length === 0);
if (allDependencies) {
await Promise.all(allDependencies.map(async (dep) => {
var _a;
let plugin = dep.$.id;
let version = dep.$.version;
if (plugin.includes('@') && plugin.indexOf('@') !== 0) {
[plugin, version] = plugin.split('@');
}
if (cordovaPlugins.filter(p => p.id === plugin || p.xml.$.id === plugin).length === 0) {
if ((_a = dep.$.url) === null || _a === void 0 ? void 0 : _a.startsWith('http')) {
plugin = dep.$.url;
version = dep.$.commit;
}
const deps = pluginDeps.get(p.id) || [];
deps.push(`${plugin}${version ? colors_1.default.weak(` (${version})`) : ''}`);
pluginDeps.set(p.id, deps);
}
}));
}
}));
if (pluginDeps.size > 0) {
let msg = `${colors_1.default.failure(colors_1.default.strong('Plugins are missing dependencies.'))}\n` +
`Cordova plugin dependencies must be installed in your project (e.g. w/ ${colors_1.default.input('npm install')}).\n`;
for (const [plugin, deps] of pluginDeps.entries()) {
msg +=
`\n ${colors_1.default.strong(plugin)} is missing dependencies:\n` +
deps.map(d => ` - ${d}`).join('\n');
}
log_1.logger.warn(`${msg}\n`);
}
}
exports.checkPluginDependencies = checkPluginDependencies;
function getIncompatibleCordovaPlugins(platform) {
const pluginList = [
'cordova-plugin-splashscreen',
'cordova-plugin-ionic-webview',
'cordova-plugin-crosswalk-webview',
'cordova-plugin-wkwebview-engine',
'cordova-plugin-console',
'cordova-plugin-music-controls',
'cordova-plugin-add-swift-support',
'cordova-plugin-ionic-keyboard',
'cordova-plugin-braintree',
'@ionic-enterprise/filesystem',
'@ionic-enterprise/keyboard',
'@ionic-enterprise/splashscreen',
'cordova-support-google-services',
];
if (platform === 'ios') {
pluginList.push('cordova-plugin-statusbar', '@ionic-enterprise/statusbar');
}
if (platform === 'android') {
pluginList.push('cordova-plugin-compat');
}
return pluginList;
}
exports.getIncompatibleCordovaPlugins = getIncompatibleCordovaPlugins;
async function getCordovaPreferences(config) {
var _a, _b, _c, _d, _e;
const configXml = path_1.join(config.app.rootDir, 'config.xml');
let cordova = {};
if (await utils_fs_1.pathExists(configXml)) {
cordova.preferences = {};
const xmlMeta = await xml_1.readXML(configXml);
if (xmlMeta.widget.preference) {
xmlMeta.widget.preference.map((pref) => {
cordova.preferences[pref.$.name] = pref.$.value;
});
}
}
if (cordova.preferences && Object.keys(cordova.preferences).length > 0) {
if (term_1.isInteractive()) {
const answers = await log_1.logPrompt(`${colors_1.default.strong(`Cordovaaa preferences can be automatically ported to ${colors_1.default.strong(config.app.extConfigName)}.`)}\n` +
`Keep in mind: Not all values can be automatically migrated from ${colors_1.default.strong('config.xml')}. There may be more work to do.\n` +
`More info: ${colors_1.default.strong('https://capacitorjs.com/docs/cordova/migrating-from-cordova-to-capacitor')}`, {
type: 'confirm',
name: 'confirm',
message: `Migrate Cordova preferences from config.xml?`,
initial: true,
});
if (answers.confirm) {
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.preferences) {
const answers = await prompts_1.default([
{
type: 'confirm',
name: 'confirm',
message: `${config.app.extConfigName} already contains Cordova preferences. Overwrite?`,
},
], { onCancel: () => process.exit(1) });
if (!answers.confirm) {
cordova = (_c = config.app.extConfig) === null || _c === void 0 ? void 0 : _c.cordova;
}
}
}
else {
cordova = (_d = config.app.extConfig) === null || _d === void 0 ? void 0 : _d.cordova;
}
}
}
else {
cordova = (_e = config.app.extConfig) === null || _e === void 0 ? void 0 : _e.cordova;
}
return cordova;
}
exports.getCordovaPreferences = getCordovaPreferences;
async function writeCordovaAndroidManifest(cordovaPlugins, config, platform) {
var _a;
const manifestPath = path_1.join(config.android.cordovaPluginsDirAbs, 'src', 'main', 'AndroidManifest.xml');
const rootXMLEntries = [];
const applicationXMLEntries = [];
const applicationXMLAttributes = [];
let prefsArray = [];
cordovaPlugins.map(async (p) => {
const editConfig = plugin_1.getPlatformElement(p, platform, 'edit-config');
const configFile = plugin_1.getPlatformElement(p, platform, 'config-file');
prefsArray = prefsArray.concat(plugin_1.getAllElements(p, platform, 'preference'));
editConfig.concat(configFile).map(async (configElement) => {
var _a, _b;
if (configElement.$ &&
(((_a = configElement.$.target) === null || _a === void 0 ? void 0 : _a.includes('AndroidManifest.xml')) || ((_b = configElement.$.file) === null || _b === void 0 ? void 0 : _b.includes('AndroidManifest.xml')))) {
const keys = Object.keys(configElement).filter(k => k !== '$');
keys.map(k => {
configElement[k].map((e) => {
const xmlElement = xml_1.buildXmlElement(e, k);
const pathParts = getPathParts(configElement.$.parent || configElement.$.target);
if (pathParts.length > 1) {
if (pathParts.pop() === 'application') {
if (configElement.$.mode &&
configElement.$.mode === 'merge' &&
xmlElement.startsWith('<application')) {
Object.keys(e.$).map((ek) => {
applicationXMLAttributes.push(`${ek}="${e.$[ek]}"`);
});
}
else if (!applicationXMLEntries.includes(xmlElement) &&
!contains(applicationXMLEntries, xmlElement, k)) {
applicationXMLEntries.push(xmlElement);
}
}
else {
log_1.logger.warn(`Configuration required for ${colors_1.default.strong(p.id)}.\n` +
`Add the following to AndroidManifest.xml:\n` +
xmlElement);
}
}
else {
if (!rootXMLEntries.includes(xmlElement) &&
!contains(rootXMLEntries, xmlElement, k)) {
rootXMLEntries.push(xmlElement);
}
}
});
});
}
});
});
const cleartextString = 'android:usesCleartextTraffic="true"';
const cleartext = ((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.cleartext) &&
!applicationXMLAttributes.includes(cleartextString)
? cleartextString
: '';
let content = `<?xml version='1.0' encoding='utf-8'?>
<manifest package="capacitor.android.plugins"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:amazon="http://schemas.amazon.com/apk/res/android">
<application ${applicationXMLAttributes.join('\n')} ${cleartext}>
${applicationXMLEntries.join('\n')}
</application>
${rootXMLEntries.join('\n')}
</manifest>`;
content = content.replace(new RegExp('$PACKAGE_NAME'.replace('$', '\\$&'), 'g'), '${applicationId}');
for (const preference of prefsArray) {
content = content.replace(new RegExp(('$' + preference.$.name).replace('$', '\\$&'), 'g'), preference.$.default);
}
if (await utils_fs_1.pathExists(manifestPath)) {
await utils_fs_1.writeFile(manifestPath, content);
}
}
exports.writeCordovaAndroidManifest = writeCordovaAndroidManifest;
function getPathParts(path) {
const rootPath = 'manifest';
path = path.replace('/*', rootPath);
const parts = path.split('/').filter(part => part !== '');
if (parts.length > 1 || parts.includes(rootPath)) {
return parts;
}
return [rootPath, path];
}
function contains(entries, obj, k) {
const element = xml_1.parseXML(obj);
for (const entry of entries) {
const current = xml_1.parseXML(entry);
if (element &&
current &&
current[k] &&
element[k] &&
current[k].$ &&
element[k].$ &&
element[k].$['android:name'] === current[k].$['android:name']) {
return true;
}
}
return false;
}