Update capacitor version

This commit is contained in:
Pieter Vander Vennet 2025-07-06 20:20:48 +02:00
parent 91155bce0a
commit f3b3a86b32
610 changed files with 28718 additions and 7101 deletions

View file

@ -1,19 +1,19 @@
ext {
androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.8.0'
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.9.2'
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.2.0'
androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.12.0'
androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.6.2'
androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.9.0'
androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.15.0'
androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.8.4'
androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.12.1'
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
cordovaAndroidVersion = project.hasProperty('cordovaAndroidVersion') ? rootProject.ext.cordovaAndroidVersion : '10.1.1'
}
buildscript {
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.10'
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.25'
repositories {
google()
mavenCentral()
@ -22,7 +22,7 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:8.2.1'
classpath 'com.android.tools.build:gradle:8.7.2'
if (System.getenv("CAP_PUBLISH") == "true") {
classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
@ -42,10 +42,10 @@ if (System.getenv("CAP_PUBLISH") == "true") {
android {
namespace "com.getcapacitor.android"
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 34
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
defaultConfig {
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 34
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
versionCode 1
versionName "1.0"
consumerProguardFiles 'proguard-rules.pro'
@ -64,8 +64,8 @@ android {
lintConfig file('lint.xml')
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
publishing {
singleVariant("release")
@ -90,7 +90,7 @@ dependencies {
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
implementation "org.apache.cordova:framework:$cordovaAndroidVersion"
testImplementation 'org.json:json:20231013'
testImplementation 'org.mockito:mockito-inline:5.2.0'
testImplementation 'org.json:json:20240303'
testImplementation 'org.mockito:mockito-core:5.14.1'
}

View file

@ -142,9 +142,7 @@ var nativeBridge = (function (exports) {
const CAPACITOR_HTTP_INTERCEPTOR = '/_capacitor_http_interceptor_';
const CAPACITOR_HTTP_INTERCEPTOR_URL_PARAM = 'u';
// TODO: export as Cap function
const isRelativeOrProxyUrl = (url) => !url ||
!(url.startsWith('http:') || url.startsWith('https:')) ||
url.indexOf(CAPACITOR_HTTP_INTERCEPTOR) > -1;
const isRelativeOrProxyUrl = (url) => !url || !(url.startsWith('http:') || url.startsWith('https:')) || url.indexOf(CAPACITOR_HTTP_INTERCEPTOR) > -1;
// TODO: export as Cap function
const createProxyUrl = (url, win) => {
var _a, _b;
@ -174,11 +172,10 @@ var nativeBridge = (function (exports) {
return webviewServerUrl + '/_capacitor_file_' + filePath;
}
else if (filePath.startsWith('file://')) {
return (webviewServerUrl + filePath.replace('file://', '/_capacitor_file_'));
return webviewServerUrl + filePath.replace('file://', '/_capacitor_file_');
}
else if (filePath.startsWith('content://')) {
return (webviewServerUrl +
filePath.replace('content:/', '/_capacitor_content_'));
return webviewServerUrl + filePath.replace('content:/', '/_capacitor_content_');
}
}
return filePath;
@ -289,9 +286,6 @@ var nativeBridge = (function (exports) {
return docAddEventListener.apply(doc, args);
};
}
// deprecated in v3, remove from v4
cap.platform = cap.getPlatform();
cap.isNative = cap.isNativePlatform();
win.Capacitor = cap;
};
const initVendor = (win, cap) => {
@ -321,27 +315,14 @@ var nativeBridge = (function (exports) {
win.Ionic.WebView = IonicWebView;
};
const initLogger = (win, cap) => {
const BRIDGED_CONSOLE_METHODS = [
'debug',
'error',
'info',
'log',
'trace',
'warn',
];
const BRIDGED_CONSOLE_METHODS = ['debug', 'error', 'info', 'log', 'trace', 'warn'];
const createLogFromNative = (c) => (result) => {
if (isFullConsole(c)) {
const success = result.success === true;
const tagStyles = success
? 'font-style: italic; font-weight: lighter; color: gray'
: 'font-style: italic; font-weight: lighter; color: red';
c.groupCollapsed('%cresult %c' +
result.pluginId +
'.' +
result.methodName +
' (#' +
result.callbackId +
')', tagStyles, 'font-style: italic; font-weight: bold; color: #444');
c.groupCollapsed('%cresult %c' + result.pluginId + '.' + result.methodName + ' (#' + result.callbackId + ')', tagStyles, 'font-style: italic; font-weight: bold; color: #444');
if (result.success === false) {
c.error(result.error);
}
@ -361,13 +342,7 @@ var nativeBridge = (function (exports) {
};
const createLogToNative = (c) => (call) => {
if (isFullConsole(c)) {
c.groupCollapsed('%cnative %c' +
call.pluginId +
'.' +
call.methodName +
' (#' +
call.callbackId +
')', 'font-weight: lighter; color: gray', 'font-weight: bold; color: #000');
c.groupCollapsed('%cnative %c' + call.pluginId + '.' + call.methodName + ' (#' + call.callbackId + ')', 'font-weight: lighter; color: gray', 'font-weight: bold; color: #000');
c.dir(call);
c.groupEnd();
}
@ -379,9 +354,7 @@ var nativeBridge = (function (exports) {
if (!c) {
return false;
}
return (typeof c.groupCollapsed === 'function' ||
typeof c.groupEnd === 'function' ||
typeof c.dir === 'function');
return typeof c.groupCollapsed === 'function' || typeof c.groupEnd === 'function' || typeof c.dir === 'function';
};
const serializeConsoleMessage = (msg) => {
try {
@ -440,9 +413,7 @@ var nativeBridge = (function (exports) {
set: function (val) {
const cookiePairs = val.split(';');
const domainSection = val.toLowerCase().split('domain=')[1];
const domain = cookiePairs.length > 1 &&
domainSection != null &&
domainSection.length > 0
const domain = cookiePairs.length > 1 && domainSection != null && domainSection.length > 0
? domainSection.split(';')[0].trim()
: '';
if (platform === 'ios') {
@ -497,6 +468,15 @@ var nativeBridge = (function (exports) {
if (doPatchHttp) {
// fetch patch
window.fetch = async (resource, options) => {
const headers = new Headers(options === null || options === void 0 ? void 0 : options.headers);
const contentType = headers.get('Content-Type') || headers.get('content-type');
if ((options === null || options === void 0 ? void 0 : options.body) instanceof FormData &&
(contentType === null || contentType === void 0 ? void 0 : contentType.includes('multipart/form-data')) &&
!contentType.includes('boundary')) {
headers.delete('Content-Type');
headers.delete('content-type');
options.headers = headers;
}
const request = new Request(resource, options);
if (request.url.startsWith(`${cap.getServerUrl()}/`)) {
return win.CapacitorWebFetch(resource, options);
@ -506,6 +486,17 @@ var nativeBridge = (function (exports) {
method.toLocaleUpperCase() === 'HEAD' ||
method.toLocaleUpperCase() === 'OPTIONS' ||
method.toLocaleUpperCase() === 'TRACE') {
// a workaround for following android webview issue:
// https://issues.chromium.org/issues/40450316
// Sets the user-agent header to a custom value so that its not stripped
// on its way to the native layer
if (platform === 'android' && (options === null || options === void 0 ? void 0 : options.headers)) {
const userAgent = headers.get('User-Agent') || headers.get('user-agent');
if (userAgent !== null) {
headers.set('x-cap-user-agent', userAgent);
options.headers = headers;
}
}
if (typeof resource === 'string') {
return await win.CapacitorWebFetch(createProxyUrl(resource, win), options);
}
@ -519,16 +510,24 @@ var nativeBridge = (function (exports) {
try {
const { body } = request;
const optionHeaders = Object.fromEntries(request.headers.entries());
const { data: requestData, type, headers, } = await convertBody((options === null || options === void 0 ? void 0 : options.body) || body || undefined, optionHeaders['Content-Type'] || optionHeaders['content-type']);
const { data: requestData, type, headers: requestHeaders, } = await convertBody((options === null || options === void 0 ? void 0 : options.body) || body || undefined, optionHeaders['Content-Type'] || optionHeaders['content-type']);
const nativeHeaders = Object.assign(Object.assign({}, requestHeaders), optionHeaders);
if (platform === 'android') {
if (headers.has('User-Agent')) {
nativeHeaders['User-Agent'] = headers.get('User-Agent');
}
if (headers.has('user-agent')) {
nativeHeaders['user-agent'] = headers.get('user-agent');
}
}
const nativeResponse = await cap.nativePromise('CapacitorHttp', 'request', {
url: request.url,
method: method,
data: requestData,
dataType: type,
headers: Object.assign(Object.assign({}, headers), optionHeaders),
headers: nativeHeaders,
});
const contentType = nativeResponse.headers['Content-Type'] ||
nativeResponse.headers['content-type'];
const contentType = nativeResponse.headers['Content-Type'] || nativeResponse.headers['content-type'];
let data = (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('application/json'))
? JSON.stringify(nativeResponse.data)
: nativeResponse.data;
@ -570,8 +569,7 @@ var nativeBridge = (function (exports) {
},
});
const prototype = win.CapacitorWebXMLHttpRequest.prototype;
const isProgressEventAvailable = () => typeof ProgressEvent !== 'undefined' &&
ProgressEvent.prototype instanceof Event;
const isProgressEventAvailable = () => typeof ProgressEvent !== 'undefined' && ProgressEvent.prototype instanceof Event;
// XHR patch abort
prototype.abort = function () {
if (isRelativeOrProxyUrl(this._url)) {
@ -619,6 +617,13 @@ var nativeBridge = (function (exports) {
};
// XHR patch set request header
prototype.setRequestHeader = function (header, value) {
// a workaround for the following android web view issue:
// https://issues.chromium.org/issues/40450316
// Sets the user-agent header to a custom value so that its not stripped
// on its way to the native layer
if (platform === 'android' && (header === 'User-Agent' || header === 'user-agent')) {
header = 'x-cap-user-agent';
}
if (isRelativeOrProxyUrl(this._url)) {
return win.CapacitorWebXMLHttpRequest.setRequestHeader.call(this, header, value);
}
@ -652,9 +657,7 @@ var nativeBridge = (function (exports) {
},
});
convertBody(body).then(({ data, type, headers }) => {
const otherHeaders = this._headers != null && Object.keys(this._headers).length > 0
? this._headers
: undefined;
const otherHeaders = this._headers != null && Object.keys(this._headers).length > 0 ? this._headers : undefined;
// intercept request & pass to the bridge
cap
.nativePromise('CapacitorHttp', 'request', {
@ -678,8 +681,7 @@ var nativeBridge = (function (exports) {
}
this._headers = nativeResponse.headers;
this.status = nativeResponse.status;
if (this.responseType === '' ||
this.responseType === 'text') {
if (this.responseType === '' || this.responseType === 'text') {
this.response =
typeof nativeResponse.data !== 'string'
? JSON.stringify(nativeResponse.data)
@ -688,8 +690,7 @@ var nativeBridge = (function (exports) {
else {
this.response = nativeResponse.data;
}
this.responseText = ((_a = (nativeResponse.headers['Content-Type'] ||
nativeResponse.headers['content-type'])) === null || _a === void 0 ? void 0 : _a.startsWith('application/json'))
this.responseText = ((_a = (nativeResponse.headers['Content-Type'] || nativeResponse.headers['content-type'])) === null || _a === void 0 ? void 0 : _a.startsWith('application/json'))
? JSON.stringify(nativeResponse.data)
: nativeResponse.data;
this.responseURL = nativeResponse.url;
@ -805,7 +806,7 @@ var nativeBridge = (function (exports) {
};
cap.logToNative = createLogToNative(win.console);
cap.logFromNative = createLogFromNative(win.console);
cap.handleError = err => win.console.error(err);
cap.handleError = (err) => win.console.error(err);
win.Capacitor = cap;
};
function initNativeBridge(win) {
@ -814,7 +815,7 @@ var nativeBridge = (function (exports) {
const callbacks = new Map();
const webviewServerUrl = typeof win.WEBVIEW_SERVER_URL === 'string' ? win.WEBVIEW_SERVER_URL : '';
cap.getServerUrl = () => webviewServerUrl;
cap.convertFileSrc = filePath => convertFileSrcServerUrl(webviewServerUrl, filePath);
cap.convertFileSrc = (filePath) => convertFileSrcServerUrl(webviewServerUrl, filePath);
// Counter of callback ids, randomized to avoid
// any issues during reloads if a call comes back with
// an existing callback id from an old session
@ -823,12 +824,12 @@ var nativeBridge = (function (exports) {
const isNativePlatform = () => true;
const getPlatform = () => getPlatformId(win);
cap.getPlatform = getPlatform;
cap.isPluginAvailable = name => Object.prototype.hasOwnProperty.call(cap.Plugins, name);
cap.isPluginAvailable = (name) => Object.prototype.hasOwnProperty.call(cap.Plugins, name);
cap.isNativePlatform = isNativePlatform;
// create the postToNative() fn if needed
if (getPlatformId(win) === 'android') {
// android platform
postToNative = data => {
postToNative = (data) => {
var _a;
try {
win.androidBridge.postMessage(JSON.stringify(data));
@ -840,7 +841,7 @@ var nativeBridge = (function (exports) {
}
else if (getPlatformId(win) === 'ios') {
// ios platform
postToNative = data => {
postToNative = (data) => {
var _a;
try {
data.type = data.type ? data.type : 'message';
@ -885,8 +886,7 @@ var nativeBridge = (function (exports) {
if (typeof postToNative === 'function') {
let callbackId = '-1';
if (storedCallback &&
(typeof storedCallback.callback === 'function' ||
typeof storedCallback.resolve === 'function')) {
(typeof storedCallback.callback === 'function' || typeof storedCallback.resolve === 'function')) {
// store the call for later lookup
callbackId = String(++callbackIdCount);
callbacks.set(callbackId, storedCallback);
@ -921,7 +921,7 @@ var nativeBridge = (function (exports) {
/**
* Process a response from the native layer.
*/
cap.fromNative = result => {
cap.fromNative = (result) => {
returnResult(result);
};
const returnResult = (result) => {

View file

@ -15,7 +15,11 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.webkit.ServiceWorkerClient;
import android.webkit.ServiceWorkerController;
import android.webkit.ValueCallback;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import androidx.activity.result.ActivityResultCallback;
@ -75,7 +79,6 @@ import org.json.JSONException;
*/
public class Bridge {
private static final String PREFS_NAME = "CapacitorSettings";
private static final String PERMISSION_PREFS_NAME = "PluginPermStates";
private static final String BUNDLE_LAST_PLUGIN_ID_KEY = "capacitorLastActivityPluginId";
private static final String BUNDLE_LAST_PLUGIN_CALL_METHOD_NAME_KEY = "capacitorLastActivityPluginMethod";
@ -118,6 +121,8 @@ public class Bridge {
private HostMask appAllowNavigationMask;
private Set<String> allowedOriginRules = new HashSet<String>();
private ArrayList<String> authorities = new ArrayList<>();
private ArrayList<String> miscJSFileInjections = new ArrayList<String>();
private Boolean canInjectJS = true;
// A reference to the main WebView for the app
private final WebView webView;
public final MockCordovaInterfaceImpl cordovaInterface;
@ -275,9 +280,23 @@ public class Bridge {
webView.setWebChromeClient(new BridgeWebChromeClient(this));
webView.setWebViewClient(this.webViewClient);
if (Build.VERSION.SDK_INT >= 24 && config.isResolveServiceWorkerRequests()) {
ServiceWorkerController swController = ServiceWorkerController.getInstance();
swController.setServiceWorkerClient(
new ServiceWorkerClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) {
return getLocalServer().shouldInterceptRequest(request);
}
}
);
}
if (!isDeployDisabled() && !isNewBinary()) {
SharedPreferences prefs = getContext()
.getSharedPreferences(com.getcapacitor.plugin.WebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE);
SharedPreferences prefs = getContext().getSharedPreferences(
com.getcapacitor.plugin.WebView.WEBVIEW_PREFS_NAME,
Activity.MODE_PRIVATE
);
String path = prefs.getString(com.getcapacitor.plugin.WebView.CAP_SERVER_PATH, null);
if (path != null && !path.isEmpty() && new File(path).exists()) {
setServerBasePath(path);
@ -408,8 +427,10 @@ public class Bridge {
private boolean isNewBinary() {
String versionCode = "";
String versionName = "";
SharedPreferences prefs = getContext()
.getSharedPreferences(com.getcapacitor.plugin.WebView.WEBVIEW_PREFS_NAME, Activity.MODE_PRIVATE);
SharedPreferences prefs = getContext().getSharedPreferences(
com.getcapacitor.plugin.WebView.WEBVIEW_PREFS_NAME,
Activity.MODE_PRIVATE
);
String lastVersionCode = prefs.getString(LAST_BINARY_VERSION_CODE, null);
String lastVersionName = prefs.getString(LAST_BINARY_VERSION_NAME, null);
@ -552,6 +573,9 @@ public class Bridge {
public void reset() {
savedCalls = new HashMap<>();
for (PluginHandle handle : this.plugins.values()) {
handle.getInstance().removeAllListeners();
}
}
/**
@ -563,7 +587,6 @@ public class Bridge {
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setGeolocationEnabled(true);
settings.setDatabaseEnabled(true);
settings.setMediaPlaybackRequiresUserGesture(false);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
if (this.config.isMixedContentAllowed()) {
@ -859,11 +882,11 @@ public class Bridge {
}
public void triggerJSEvent(final String eventName, final String target) {
eval("window.Capacitor.triggerEvent(\"" + eventName + "\", \"" + target + "\")", s -> {});
eval("window.Capacitor.triggerEvent(\"" + eventName + "\", \"" + target + "\")", (s) -> {});
}
public void triggerJSEvent(final String eventName, final String target, final String data) {
eval("window.Capacitor.triggerEvent(\"" + eventName + "\", \"" + target + "\", " + data + ")", s -> {});
eval("window.Capacitor.triggerEvent(\"" + eventName + "\", \"" + target + "\", " + data + ")", (s) -> {});
}
public void triggerWindowJSEvent(final String eventName) {
@ -1003,14 +1026,28 @@ public class Bridge {
String cordovaPluginsJS = JSExport.getCordovaPluginJS(context);
String cordovaPluginsFileJS = JSExport.getCordovaPluginsFileJS(context);
String localUrlJS = "window.WEBVIEW_SERVER_URL = '" + localUrl + "';";
String miscJS = JSExport.getMiscFileJS(miscJSFileInjections, context);
return new JSInjector(globalJS, bridgeJS, pluginJS, cordovaJS, cordovaPluginsJS, cordovaPluginsFileJS, localUrlJS);
miscJSFileInjections = new ArrayList<>();
canInjectJS = false;
return new JSInjector(globalJS, bridgeJS, pluginJS, cordovaJS, cordovaPluginsJS, cordovaPluginsFileJS, localUrlJS, miscJS);
} catch (Exception ex) {
Logger.error("Unable to export Capacitor JS. App will not function!", ex);
}
return null;
}
/**
* Inject JavaScript from an external file before the WebView loads.
* @param path relative to public folder
*/
public void injectScriptBeforeLoad(String path) {
if (canInjectJS) {
miscJSFileInjections.add(path);
}
}
/**
* Restore any saved bundle state data
* @param savedInstanceState
@ -1026,8 +1063,13 @@ public class Bridge {
try {
JSObject options = new JSObject(lastOptionsJson);
pluginCallForLastActivity =
new PluginCall(msgHandler, lastPluginId, PluginCall.CALLBACK_ID_DANGLING, lastPluginCallMethod, options);
pluginCallForLastActivity = new PluginCall(
msgHandler,
lastPluginId,
PluginCall.CALLBACK_ID_DANGLING,
lastPluginCallMethod,
options
);
} catch (JSONException ex) {
Logger.error("Unable to restore plugin call, unable to parse persisted JSON object", ex);
}
@ -1570,9 +1612,9 @@ public class Bridge {
config
);
if (webView instanceof CapacitorWebView) {
CapacitorWebView capacitorWebView = (CapacitorWebView) webView;
if (webView instanceof CapacitorWebView capacitorWebView) {
capacitorWebView.setBridge(bridge);
capacitorWebView.edgeToEdgeHandler(bridge);
}
bridge.setCordovaWebView(mockWebView);

View file

@ -25,7 +25,7 @@ public class BridgeActivity extends AppCompatActivity {
getApplication().setTheme(R.style.AppTheme_NoActionBar);
setTheme(R.style.AppTheme_NoActionBar);
try {
setContentView(R.layout.bridge_layout_main);
setContentView(R.layout.capacitor_bridge_layout_main);
} catch (Exception ex) {
setContentView(R.layout.no_webview);
return;

View file

@ -1,134 +0,0 @@
package com.getcapacitor;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import com.getcapacitor.android.R;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {@link Fragment} subclass.
* Use the {@link BridgeFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class BridgeFragment extends Fragment {
private static final String ARG_START_DIR = "startDir";
protected Bridge bridge;
protected boolean keepRunning = true;
private final List<Class<? extends Plugin>> initialPlugins = new ArrayList<>();
private CapConfig config = null;
private final List<WebViewListener> webViewListeners = new ArrayList<>();
public BridgeFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param startDir the directory to serve content from
* @return A new instance of fragment BridgeFragment.
*/
public static BridgeFragment newInstance(String startDir) {
BridgeFragment fragment = new BridgeFragment();
Bundle args = new Bundle();
args.putString(ARG_START_DIR, startDir);
fragment.setArguments(args);
return fragment;
}
public void addPlugin(Class<? extends Plugin> plugin) {
this.initialPlugins.add(plugin);
}
public void setConfig(CapConfig config) {
this.config = config;
}
public Bridge getBridge() {
return bridge;
}
public void addWebViewListener(WebViewListener webViewListener) {
webViewListeners.add(webViewListener);
}
/**
* Load the WebView and create the Bridge
*/
protected void load(Bundle savedInstanceState) {
Logger.debug("Loading Bridge with BridgeFragment");
Bundle args = getArguments();
String startDir = null;
if (args != null) {
startDir = getArguments().getString(ARG_START_DIR);
}
bridge =
new Bridge.Builder(this)
.setInstanceState(savedInstanceState)
.setPlugins(initialPlugins)
.setConfig(config)
.addWebViewListeners(webViewListeners)
.create();
if (startDir != null) {
bridge.setServerAssetPath(startDir);
}
this.keepRunning = bridge.shouldKeepRunning();
}
@Override
public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
super.onInflate(context, attrs, savedInstanceState);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.bridge_fragment);
CharSequence c = a.getString(R.styleable.bridge_fragment_start_dir);
if (c != null) {
String startDir = c.toString();
Bundle args = new Bundle();
args.putString(ARG_START_DIR, startDir);
setArguments(args);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bridge, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.load(savedInstanceState);
}
@Override
public void onDestroy() {
super.onDestroy();
if (this.bridge != null) {
this.bridge.onDestroy();
}
}
}

View file

@ -67,15 +67,11 @@ public class BridgeWebChromeClient extends WebChromeClient {
};
permissionLauncher = bridge.registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), permissionCallback);
activityLauncher =
bridge.registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (activityListener != null) {
activityListener.onActivityResult(result);
}
}
);
activityLauncher = bridge.registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), (result) -> {
if (activityListener != null) {
activityListener.onActivityResult(result);
}
});
}
/**
@ -104,8 +100,6 @@ public class BridgeWebChromeClient extends WebChromeClient {
@Override
public void onPermissionRequest(final PermissionRequest request) {
boolean isRequestPermissionRequired = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M;
List<String> permissionList = new ArrayList<>();
if (Arrays.asList(request.getResources()).contains("android.webkit.resource.VIDEO_CAPTURE")) {
permissionList.add(Manifest.permission.CAMERA);
@ -114,16 +108,15 @@ public class BridgeWebChromeClient extends WebChromeClient {
permissionList.add(Manifest.permission.MODIFY_AUDIO_SETTINGS);
permissionList.add(Manifest.permission.RECORD_AUDIO);
}
if (!permissionList.isEmpty() && isRequestPermissionRequired) {
if (!permissionList.isEmpty()) {
String[] permissions = permissionList.toArray(new String[0]);
permissionListener =
isGranted -> {
if (isGranted) {
request.grant(request.getResources());
} else {
request.deny();
}
};
permissionListener = (isGranted) -> {
if (isGranted) {
request.grant(request.getResources());
} else {
request.deny();
}
};
permissionLauncher.launch(permissions);
} else {
request.grant(request.getResources());
@ -147,19 +140,14 @@ public class BridgeWebChromeClient extends WebChromeClient {
AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
builder
.setMessage(message)
.setPositiveButton(
"OK",
(dialog, buttonIndex) -> {
dialog.dismiss();
result.confirm();
}
)
.setOnCancelListener(
dialog -> {
dialog.dismiss();
result.cancel();
}
);
.setPositiveButton("OK", (dialog, buttonIndex) -> {
dialog.dismiss();
result.confirm();
})
.setOnCancelListener((dialog) -> {
dialog.dismiss();
result.cancel();
});
AlertDialog dialog = builder.create();
@ -186,26 +174,18 @@ public class BridgeWebChromeClient extends WebChromeClient {
builder
.setMessage(message)
.setPositiveButton(
"OK",
(dialog, buttonIndex) -> {
dialog.dismiss();
result.confirm();
}
)
.setNegativeButton(
"Cancel",
(dialog, buttonIndex) -> {
dialog.dismiss();
result.cancel();
}
)
.setOnCancelListener(
dialog -> {
dialog.dismiss();
result.cancel();
}
);
.setPositiveButton("OK", (dialog, buttonIndex) -> {
dialog.dismiss();
result.confirm();
})
.setNegativeButton("Cancel", (dialog, buttonIndex) -> {
dialog.dismiss();
result.cancel();
})
.setOnCancelListener((dialog) -> {
dialog.dismiss();
result.cancel();
});
AlertDialog dialog = builder.create();
@ -235,28 +215,20 @@ public class BridgeWebChromeClient extends WebChromeClient {
builder
.setMessage(message)
.setView(input)
.setPositiveButton(
"OK",
(dialog, buttonIndex) -> {
dialog.dismiss();
.setPositiveButton("OK", (dialog, buttonIndex) -> {
dialog.dismiss();
String inputText1 = input.getText().toString().trim();
result.confirm(inputText1);
}
)
.setNegativeButton(
"Cancel",
(dialog, buttonIndex) -> {
dialog.dismiss();
result.cancel();
}
)
.setOnCancelListener(
dialog -> {
dialog.dismiss();
result.cancel();
}
);
String inputText1 = input.getText().toString().trim();
result.confirm(inputText1);
})
.setNegativeButton("Cancel", (dialog, buttonIndex) -> {
dialog.dismiss();
result.cancel();
})
.setOnCancelListener((dialog) -> {
dialog.dismiss();
result.cancel();
});
AlertDialog dialog = builder.create();
@ -277,22 +249,21 @@ public class BridgeWebChromeClient extends WebChromeClient {
final String[] geoPermissions = { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION };
if (!PermissionHelper.hasPermissions(bridge.getContext(), geoPermissions)) {
permissionListener =
isGranted -> {
if (isGranted) {
permissionListener = (isGranted) -> {
if (isGranted) {
callback.invoke(origin, true, false);
} else {
final String[] coarsePermission = { Manifest.permission.ACCESS_COARSE_LOCATION };
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
PermissionHelper.hasPermissions(bridge.getContext(), coarsePermission)
) {
callback.invoke(origin, true, false);
} else {
final String[] coarsePermission = { Manifest.permission.ACCESS_COARSE_LOCATION };
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
PermissionHelper.hasPermissions(bridge.getContext(), coarsePermission)
) {
callback.invoke(origin, true, false);
} else {
callback.invoke(origin, false, false);
}
callback.invoke(origin, false, false);
}
};
}
};
permissionLauncher.launch(geoPermissions);
} else {
// permission is already granted
@ -315,15 +286,14 @@ public class BridgeWebChromeClient extends WebChromeClient {
if (isMediaCaptureSupported()) {
showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo);
} else {
permissionListener =
isGranted -> {
if (isGranted) {
showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo);
} else {
Logger.warn(Logger.tags("FileChooser"), "Camera permission not granted");
filePathCallback.onReceiveValue(null);
}
};
permissionListener = (isGranted) -> {
if (isGranted) {
showMediaCaptureOrFilePicker(filePathCallback, fileChooserParams, captureVideo);
} else {
Logger.warn(Logger.tags("FileChooser"), "Camera permission not granted");
filePathCallback.onReceiveValue(null);
}
};
final String[] camPermission = { Manifest.permission.CAMERA };
permissionLauncher.launch(camPermission);
}
@ -375,14 +345,13 @@ public class BridgeWebChromeClient extends WebChromeClient {
return false;
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
activityListener =
activityResult -> {
Uri[] result = null;
if (activityResult.getResultCode() == Activity.RESULT_OK) {
result = new Uri[] { imageFileUri };
}
filePathCallback.onReceiveValue(result);
};
activityListener = (activityResult) -> {
Uri[] result = null;
if (activityResult.getResultCode() == Activity.RESULT_OK) {
result = new Uri[] { imageFileUri };
}
filePathCallback.onReceiveValue(result);
};
activityLauncher.launch(takePictureIntent);
return true;
@ -395,14 +364,13 @@ public class BridgeWebChromeClient extends WebChromeClient {
return false;
}
activityListener =
activityResult -> {
Uri[] result = null;
if (activityResult.getResultCode() == Activity.RESULT_OK) {
result = new Uri[] { activityResult.getData().getData() };
}
filePathCallback.onReceiveValue(result);
};
activityListener = (activityResult) -> {
Uri[] result = null;
if (activityResult.getResultCode() == Activity.RESULT_OK) {
result = new Uri[] { activityResult.getData().getData() };
}
filePathCallback.onReceiveValue(result);
};
activityLauncher.launch(takeVideoIntent);
return true;
@ -421,21 +389,20 @@ public class BridgeWebChromeClient extends WebChromeClient {
}
}
try {
activityListener =
activityResult -> {
Uri[] result;
Intent resultIntent = activityResult.getData();
if (activityResult.getResultCode() == Activity.RESULT_OK && resultIntent.getClipData() != null) {
final int numFiles = resultIntent.getClipData().getItemCount();
result = new Uri[numFiles];
for (int i = 0; i < numFiles; i++) {
result[i] = resultIntent.getClipData().getItemAt(i).getUri();
}
} else {
result = WebChromeClient.FileChooserParams.parseResult(activityResult.getResultCode(), resultIntent);
activityListener = (activityResult) -> {
Uri[] result;
Intent resultIntent = activityResult.getData();
if (activityResult.getResultCode() == Activity.RESULT_OK && resultIntent.getClipData() != null) {
final int numFiles = resultIntent.getClipData().getItemCount();
result = new Uri[numFiles];
for (int i = 0; i < numFiles; i++) {
result[i] = resultIntent.getClipData().getItemAt(i).getUri();
}
filePathCallback.onReceiveValue(result);
};
} else {
result = WebChromeClient.FileChooserParams.parseResult(activityResult.getResultCode(), resultIntent);
}
filePathCallback.onReceiveValue(result);
};
activityLauncher.launch(intent);
} catch (ActivityNotFoundException e) {
filePathCallback.onReceiveValue(null);

View file

@ -53,6 +53,8 @@ public class CapConfig {
private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
private String errorPath;
private boolean zoomableWebView = false;
private boolean resolveServiceWorkerRequests = true;
private String adjustMarginsForEdgeToEdge = "disable";
// Embedded
private String startPath;
@ -179,6 +181,8 @@ public class CapConfig {
this.minHuaweiWebViewVersion = builder.minHuaweiWebViewVersion;
this.errorPath = builder.errorPath;
this.zoomableWebView = builder.zoomableWebView;
this.resolveServiceWorkerRequests = builder.resolveServiceWorkerRequests;
this.adjustMarginsForEdgeToEdge = builder.adjustMarginsForEdgeToEdge;
// Embedded
this.startPath = builder.startPath;
@ -247,6 +251,7 @@ public class CapConfig {
serverUrl = JSONUtils.getString(configJSON, "server.url", null);
hostname = JSONUtils.getString(configJSON, "server.hostname", hostname);
errorPath = JSONUtils.getString(configJSON, "server.errorPath", null);
startPath = JSONUtils.getString(configJSON, "server.appStartPath", null);
String configSchema = JSONUtils.getString(configJSON, "server.androidScheme", androidScheme);
if (this.validateScheme(configSchema)) {
@ -256,24 +261,34 @@ public class CapConfig {
allowNavigation = JSONUtils.getArray(configJSON, "server.allowNavigation", null);
// Android
overriddenUserAgentString =
JSONUtils.getString(configJSON, "android.overrideUserAgent", JSONUtils.getString(configJSON, "overrideUserAgent", null));
appendedUserAgentString =
JSONUtils.getString(configJSON, "android.appendUserAgent", JSONUtils.getString(configJSON, "appendUserAgent", null));
backgroundColor =
JSONUtils.getString(configJSON, "android.backgroundColor", JSONUtils.getString(configJSON, "backgroundColor", null));
allowMixedContent =
JSONUtils.getBoolean(
configJSON,
"android.allowMixedContent",
JSONUtils.getBoolean(configJSON, "allowMixedContent", allowMixedContent)
);
overriddenUserAgentString = JSONUtils.getString(
configJSON,
"android.overrideUserAgent",
JSONUtils.getString(configJSON, "overrideUserAgent", null)
);
appendedUserAgentString = JSONUtils.getString(
configJSON,
"android.appendUserAgent",
JSONUtils.getString(configJSON, "appendUserAgent", null)
);
backgroundColor = JSONUtils.getString(
configJSON,
"android.backgroundColor",
JSONUtils.getString(configJSON, "backgroundColor", null)
);
allowMixedContent = JSONUtils.getBoolean(
configJSON,
"android.allowMixedContent",
JSONUtils.getBoolean(configJSON, "allowMixedContent", allowMixedContent)
);
minWebViewVersion = JSONUtils.getInt(configJSON, "android.minWebViewVersion", DEFAULT_ANDROID_WEBVIEW_VERSION);
minHuaweiWebViewVersion = JSONUtils.getInt(configJSON, "android.minHuaweiWebViewVersion", DEFAULT_HUAWEI_WEBVIEW_VERSION);
captureInput = JSONUtils.getBoolean(configJSON, "android.captureInput", captureInput);
useLegacyBridge = JSONUtils.getBoolean(configJSON, "android.useLegacyBridge", useLegacyBridge);
webContentsDebuggingEnabled = JSONUtils.getBoolean(configJSON, "android.webContentsDebuggingEnabled", isDebug);
zoomableWebView = JSONUtils.getBoolean(configJSON, "android.zoomEnabled", JSONUtils.getBoolean(configJSON, "zoomEnabled", false));
resolveServiceWorkerRequests = JSONUtils.getBoolean(configJSON, "android.resolveServiceWorkerRequests", true);
adjustMarginsForEdgeToEdge = JSONUtils.getString(configJSON, "android.adjustMarginsForEdgeToEdge", "disable");
String logBehavior = JSONUtils.getString(
configJSON,
@ -291,7 +306,11 @@ public class CapConfig {
loggingEnabled = isDebug;
}
initialFocus = JSONUtils.getBoolean(configJSON, "android.initialFocus", initialFocus);
initialFocus = JSONUtils.getBoolean(
configJSON,
"android.initialFocus",
JSONUtils.getBoolean(configJSON, "initialFocus", initialFocus)
);
// Plugins
pluginsConfiguration = deserializePluginsConfig(JSONUtils.getObject(configJSON, "plugins"));
@ -362,6 +381,10 @@ public class CapConfig {
return captureInput;
}
public boolean isResolveServiceWorkerRequests() {
return resolveServiceWorkerRequests;
}
public boolean isWebContentsDebuggingEnabled() {
return webContentsDebuggingEnabled;
}
@ -382,6 +405,10 @@ public class CapConfig {
return useLegacyBridge;
}
public String adjustMarginsForEdgeToEdge() {
return adjustMarginsForEdgeToEdge;
}
public int getMinWebViewVersion() {
if (minWebViewVersion < MINIMUM_ANDROID_WEBVIEW_VERSION) {
Logger.warn("Specified minimum webview version is too low, defaulting to " + MINIMUM_ANDROID_WEBVIEW_VERSION);
@ -561,6 +588,8 @@ public class CapConfig {
private int minWebViewVersion = DEFAULT_ANDROID_WEBVIEW_VERSION;
private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
private boolean zoomableWebView = false;
private boolean resolveServiceWorkerRequests = true;
private String adjustMarginsForEdgeToEdge = "disable";
// Embedded
private String startPath = null;
@ -660,6 +689,11 @@ public class CapConfig {
return this;
}
public Builder setResolveServiceWorkerRequests(boolean resolveServiceWorkerRequests) {
this.resolveServiceWorkerRequests = resolveServiceWorkerRequests;
return this;
}
public Builder setWebContentsDebuggingEnabled(boolean webContentsDebuggingEnabled) {
this.webContentsDebuggingEnabled = webContentsDebuggingEnabled;
return this;

View file

@ -1,12 +1,17 @@
package com.getcapacitor;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.webkit.WebView;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class CapacitorWebView extends WebView {
@ -49,4 +54,36 @@ public class CapacitorWebView extends WebView {
}
return super.dispatchKeyEvent(event);
}
public void edgeToEdgeHandler(Bridge bridge) {
String configEdgeToEdge = bridge.getConfig().adjustMarginsForEdgeToEdge();
if (configEdgeToEdge.equals("disable")) return;
boolean autoMargins = false;
boolean forceMargins = configEdgeToEdge.equals("force");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && configEdgeToEdge.equals("auto")) {
TypedValue value = new TypedValue();
boolean foundOptOut = getContext().getTheme().resolveAttribute(android.R.attr.windowOptOutEdgeToEdgeEnforcement, value, true);
boolean optOutValue = value.data != 0; // value is set to -1 on true as of Android 15, so we have to do this.
autoMargins = !(foundOptOut && optOutValue);
}
if (forceMargins || autoMargins) {
ViewCompat.setOnApplyWindowInsetsListener(this, (v, windowInsets) -> {
Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
mlp.leftMargin = insets.left;
mlp.bottomMargin = insets.bottom;
mlp.rightMargin = insets.right;
mlp.topMargin = insets.top;
v.setLayoutParams(mlp);
// Don't pass window insets to children
return WindowInsetsCompat.CONSUMED;
});
}
}
}

View file

@ -219,7 +219,8 @@ public class FileUtils {
int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
cursor.moveToFirst();
String name = (cursor.getString(nameIndex));
File file = new File(context.getFilesDir(), name);
String fileName = sanitizeFilename(name);
File file = new File(context.getFilesDir(), fileName);
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(file);
@ -289,4 +290,14 @@ public class FileUtils {
}
return null;
}
private static String sanitizeFilename(String displayName) {
String[] badCharacters = new String[] { "..", "/" };
String[] segments = displayName.split("/");
String fileName = segments[segments.length - 1];
for (String suspString : badCharacters) {
fileName = fileName.replace(suspString, "_");
}
return fileName;
}
}

View file

@ -21,6 +21,21 @@ public class JSExport {
return "window.Capacitor = { DEBUG: " + isDebug + ", isLoggingEnabled: " + loggingEnabled + ", Plugins: {} };";
}
public static String getMiscFileJS(ArrayList<String> paths, Context context) {
List<String> lines = new ArrayList<>();
for (String path : paths) {
try {
String fileContent = readFileFromAssets(context.getAssets(), "public/" + path);
lines.add(fileContent);
} catch (IOException ex) {
Logger.error("Unable to read public/" + path);
}
}
return TextUtils.join("\n", lines);
}
public static String getCordovaJS(Context context) {
String fileContent = "";
try {

View file

@ -20,6 +20,7 @@ class JSInjector {
private String cordovaPluginsJS;
private String cordovaPluginsFileJS;
private String localUrlJS;
private String miscJS;
public JSInjector(
String globalJS,
@ -29,6 +30,19 @@ class JSInjector {
String cordovaPluginsJS,
String cordovaPluginsFileJS,
String localUrlJS
) {
this(globalJS, bridgeJS, pluginJS, cordovaJS, cordovaPluginsJS, cordovaPluginsFileJS, localUrlJS, null);
}
public JSInjector(
String globalJS,
String bridgeJS,
String pluginJS,
String cordovaJS,
String cordovaPluginsJS,
String cordovaPluginsFileJS,
String localUrlJS,
String miscJS
) {
this.globalJS = globalJS;
this.bridgeJS = bridgeJS;
@ -37,6 +51,7 @@ class JSInjector {
this.cordovaPluginsJS = cordovaPluginsJS;
this.cordovaPluginsFileJS = cordovaPluginsFileJS;
this.localUrlJS = localUrlJS;
this.miscJS = miscJS;
}
/**
@ -45,7 +60,7 @@ class JSInjector {
* @return
*/
public String getScriptString() {
return (
String scriptString =
globalJS +
"\n\n" +
localUrlJS +
@ -58,8 +73,13 @@ class JSInjector {
"\n\n" +
cordovaPluginsFileJS +
"\n\n" +
cordovaPluginsJS
);
cordovaPluginsJS;
if (miscJS != null) {
scriptString += "\n\n" + miscJS;
}
return scriptString;
}
/**

View file

@ -150,10 +150,8 @@ public class MessageHandler {
}
private void callCordovaPluginMethod(String callbackId, String service, String action, String actionArgs) {
bridge.execute(
() -> {
cordovaPluginManager.exec(service, action, callbackId, actionArgs);
}
);
bridge.execute(() -> {
cordovaPluginManager.exec(service, action, callbackId, actionArgs);
});
}
}

View file

@ -114,7 +114,7 @@ public class Plugin {
// register callbacks annotated with ActivityCallback for activity results
ActivityResultLauncher<Intent> launcher = bridge.registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> triggerActivityCallback(method, result)
(result) -> triggerActivityCallback(method, result)
);
activityLaunchers.put(method.getName(), launcher);
@ -122,7 +122,7 @@ public class Plugin {
// register callbacks annotated with PermissionCallback for permission results
ActivityResultLauncher<String[]> launcher = bridge.registerForActivityResult(
new ActivityResultContracts.RequestMultiplePermissions(),
permissions -> triggerPermissionCallback(method, permissions)
(permissions) -> triggerPermissionCallback(method, permissions)
);
permissionLaunchers.put(method.getName(), launcher);
@ -762,6 +762,10 @@ public class Plugin {
call.resolve();
}
public void removeAllListeners() {
eventListeners.clear();
}
/**
* Exported plugin call for checking the granted status for each permission
* declared on the plugin. This plugin call responds with a mapping of permissions to

View file

@ -50,25 +50,6 @@ public class PluginCall {
this.msgHandler.sendResponseMessage(this, successResult, null);
}
/**
* @deprecated
* Use {@link #resolve(JSObject data)}
*/
@Deprecated
public void success(JSObject data) {
PluginResult result = new PluginResult(data);
this.msgHandler.sendResponseMessage(this, result, null);
}
/**
* @deprecated
* Use {@link #resolve()}
*/
@Deprecated
public void success() {
this.resolve(new JSObject());
}
public void resolve(JSObject data) {
PluginResult result = new PluginResult(data);
this.msgHandler.sendResponseMessage(this, result, null);
@ -90,33 +71,6 @@ public class PluginCall {
this.msgHandler.sendResponseMessage(this, null, errorResult);
}
/**
* @deprecated
* Use {@link #reject(String msg, Exception ex)}
*/
@Deprecated
public void error(String msg, Exception ex) {
reject(msg, ex);
}
/**
* @deprecated
* Use {@link #reject(String msg, String code, Exception ex)}
*/
@Deprecated
public void error(String msg, String code, Exception ex) {
reject(msg, code, ex);
}
/**
* @deprecated
* Use {@link #reject(String msg)}
*/
@Deprecated
public void error(String msg) {
reject(msg);
}
public void reject(String msg, String code, Exception ex, JSObject data) {
PluginResult errorResult = new PluginResult();

View file

@ -77,7 +77,9 @@ public class UriMatcher {
UriMatcher node = this;
for (int i = -2; i < numTokens; i++) {
String token;
if (i == -2) token = scheme; else if (i == -1) token = authority; else token = tokens[i];
if (i == -2) token = scheme;
else if (i == -1) token = authority;
else token = tokens[i];
ArrayList<UriMatcher> children = node.mChildren;
int numChildren = children.size();
UriMatcher child;
@ -130,7 +132,9 @@ public class UriMatcher {
for (int i = -2; i < li; i++) {
String u;
if (i == -2) u = uri.getScheme(); else if (i == -1) u = uri.getAuthority(); else u = pathSegments.get(i);
if (i == -2) u = uri.getScheme();
else if (i == -1) u = uri.getAuthority();
else u = pathSegments.get(i);
ArrayList<UriMatcher> list = node.mChildren;
if (list == null) {
break;
@ -139,7 +143,7 @@ public class UriMatcher {
int lj = list.size();
for (int j = 0; j < lj; j++) {
UriMatcher n = list.get(j);
which_switch:switch (n.mWhich) {
which_switch: switch (n.mWhich) {
case MASK:
if (HostMask.Parser.parse(n.mText).matches(u)) {
node = n;

View file

@ -260,6 +260,15 @@ public class WebViewLocalServer {
headers.put(header.getKey(), header.getValue());
}
// a workaround for the following android web view issue:
// https://issues.chromium.org/issues/40450316
// x-cap-user-agent contains the user agent set in JavaScript
String userAgentValue = headers.getString("x-cap-user-agent");
if (userAgentValue != null) {
headers.put("User-Agent", userAgentValue);
}
headers.remove("x-cap-user-agent");
HttpRequestHandler.HttpURLConnectionBuilder connectionBuilder = new HttpRequestHandler.HttpURLConnectionBuilder()
.setUrl(url)
.setMethod(request.getMethod())

View file

@ -7,5 +7,4 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ActivityCallback {
}
public @interface ActivityCallback {}

View file

@ -7,5 +7,4 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PermissionCallback {
}
public @interface PermissionCallback {}

View file

@ -72,14 +72,12 @@ public class MockCordovaWebViewImpl implements CordovaWebView {
public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
cordova
.getActivity()
.runOnUiThread(
() -> {
String js = queue.popAndEncodeAsJs();
if (js != null) {
webView.evaluateJavascript(js, null);
}
.runOnUiThread(() -> {
String js = queue.popAndEncodeAsJs();
if (js != null) {
webView.evaluateJavascript(js, null);
}
);
});
}
}
@ -194,7 +192,7 @@ public class MockCordovaWebViewImpl implements CordovaWebView {
}
public void triggerDocumentEvent(final String eventName) {
eval("window.Capacitor.triggerEvent('" + eventName + "', 'document');", s -> {});
eval("window.Capacitor.triggerEvent('" + eventName + "', 'document');", (s) -> {});
}
@Override

View file

@ -46,34 +46,31 @@ public class CapacitorCookies extends Plugin {
@PluginMethod
public void getCookies(PluginCall call) {
this.bridge.eval(
"document.cookie",
value -> {
String cookies = value.substring(1, value.length() - 1);
String[] cookieArray = cookies.split(";");
this.bridge.eval("document.cookie", (value) -> {
String cookies = value.substring(1, value.length() - 1);
String[] cookieArray = cookies.split(";");
JSObject cookieMap = new JSObject();
JSObject cookieMap = new JSObject();
for (String cookie : cookieArray) {
if (cookie.length() > 0) {
String[] keyValue = cookie.split("=", 2);
for (String cookie : cookieArray) {
if (cookie.length() > 0) {
String[] keyValue = cookie.split("=", 2);
if (keyValue.length == 2) {
String key = keyValue[0].trim();
String val = keyValue[1].trim();
try {
key = URLDecoder.decode(keyValue[0].trim(), StandardCharsets.UTF_8.name());
val = URLDecoder.decode(keyValue[1].trim(), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException ignored) {}
if (keyValue.length == 2) {
String key = keyValue[0].trim();
String val = keyValue[1].trim();
try {
key = URLDecoder.decode(keyValue[0].trim(), StandardCharsets.UTF_8.name());
val = URLDecoder.decode(keyValue[1].trim(), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException ignored) {}
cookieMap.put(key, val);
}
cookieMap.put(key, val);
}
}
call.resolve(cookieMap);
}
);
call.resolve(cookieMap);
});
}
@PluginMethod

View file

@ -398,6 +398,19 @@ public class HttpRequestHandler {
boolean isHttpMutate = method.equals("DELETE") || method.equals("PATCH") || method.equals("POST") || method.equals("PUT");
// a workaround for the following android web view issue:
// https://issues.chromium.org/issues/40450316
// x-cap-user-agent contains the user agent set in JavaScript
String userAgentValue = headers.getString("x-cap-user-agent");
if (userAgentValue != null) {
headers.put("User-Agent", userAgentValue);
}
headers.remove("x-cap-user-agent");
if (!headers.has("User-Agent") && !headers.has("user-agent")) {
headers.put("User-Agent", bridge.getConfig().getOverriddenUserAgentString());
}
URL url = new URL(urlString);
HttpURLConnectionBuilder connectionBuilder = new HttpURLConnectionBuilder()
.setUrl(url)

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.getcapacitor.BridgeActivity"
>
<com.getcapacitor.CapacitorWebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,13 +0,0 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F0FF1414"
tools:context="com.getcapacitor.BridgeFragment">
<com.getcapacitor.CapacitorWebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="bridge_fragment">
<attr name="start_dir" format="string"/>
</declare-styleable>
</resources>

View file

@ -1,6 +1,6 @@
{
"name": "@capacitor/android",
"version": "6.1.2",
"version": "7.4.1",
"description": "Capacitor: Cross-platform apps with JavaScript and the web",
"homepage": "https://capacitorjs.com",
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
@ -23,7 +23,7 @@
"verify": "./gradlew clean lint build test -b capacitor/build.gradle"
},
"peerDependencies": {
"@capacitor/core": "^6.1.0"
"@capacitor/core": "^7.4.0"
},
"publishConfig": {
"access": "public"

View file

@ -1,15 +1,84 @@
# Capacitor CLI
The Capacitor command-line interface should be installed locally and executed through `npm` scripts.
The Capacitor command-line interface (CLI) is a tool for creating and managing Capacitor applications. While it can be installed globally, it's recommended to install it locally in your project and execute through `npm` scripts.
```
## Installation
### Project Installation (Recommended)
Install the CLI locally in your project:
```bash
npm install @capacitor/cli --save-dev
```
### Global Installation
While not recommended for project use, you can install the CLI globally:
```bash
npm install -g @capacitor/cli
```
## Using Capacitor CLI
Consult the Getting Started guide for information on using the CLI and Capacitor scripts.
The CLI can be used through the `capacitor` or `cap` command. When installed locally, use it through your project's `npm` scripts or `npx`.
Common commands:
- `cap init`: Initialize a new Capacitor project
- `cap add`: Add a native platform (ios, android)
- `cap sync`: Sync your web code to your native projects
For detailed information, consult the [Getting Started guide](https://capacitorjs.com/docs/getting-started).
## Local Development
If you're contributing to the Capacitor CLI or testing local changes:
1. Clone and setup:
```bash
git clone https://github.com/ionic-team/capacitor.git
cd cli
npm install
```
2. Build the CLI:
```bash
npm run build
```
3. Create a local link:
```bash
npm link
```
4. Development workflow:
- Run `npm run watch` to automatically rebuild on changes
- Use `capacitor` or `cap` commands to test your changes
- Run `npm test` to execute the test suite
## Debugging
### Using VS Code Launch Configurations
The CLI includes VS Code launch configurations for debugging. To debug a CLI command:
1. Open the project in VS Code
2. Right now we don't have debugging working in the ts files, so select one of the .js files inside of /dist/\*\*.js
3. Place a breakpoint
4. Press F5 or go to Run > Start Debugging
5. Select a launch config and run filling out the path you want to run the cli in, and the command that you want run.
You can add more configurations by copying and modifying the existing ones in `.vscode/launch.json`.
## Contributing
Contributions are welcome! Please read our [Contributing Guide](https://github.com/ionic-team/capacitor/blob/main/CONTRIBUTING.md) for details.
### License
* [MIT](https://github.com/ionic-team/capacitor/blob/HEAD/LICENSE)
- [MIT](https://github.com/ionic-team/capacitor/blob/HEAD/LICENSE)

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLocalProperties = exports.addAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const os_1 = require("os");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
@ -17,7 +17,7 @@ async function addAndroid(config) {
exports.addAndroid = addAndroid;
async function createLocalProperties(platformDir) {
const defaultAndroidPath = (0, path_1.join)((0, os_1.homedir)(), 'Library/Android/sdk');
if (await (0, utils_fs_1.pathExists)(defaultAndroidPath)) {
if (await (0, fs_extra_1.pathExists)(defaultAndroidPath)) {
const localSettings = `
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
@ -30,7 +30,7 @@ async function createLocalProperties(platformDir) {
# header note.
sdk.dir=${defaultAndroidPath}
`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(platformDir, 'local.properties'), localSettings, {
await (0, fs_extra_1.writeFile)((0, path_1.join)(platformDir, 'local.properties'), localSettings, {
encoding: 'utf-8',
});
// Only sync if we were able to create the local properties above, otherwise

View file

@ -12,9 +12,7 @@ async function buildAndroid(config, buildOptions) {
const releaseType = (_a = buildOptions.androidreleasetype) !== null && _a !== void 0 ? _a : 'AAB';
const releaseTypeIsAAB = releaseType === 'AAB';
const flavor = (_b = buildOptions.flavor) !== null && _b !== void 0 ? _b : '';
const arg = releaseTypeIsAAB
? `:app:bundle${flavor}Release`
: `assemble${flavor}Release`;
const arg = releaseTypeIsAAB ? `:app:bundle${flavor}Release` : `assemble${flavor}Release`;
const gradleArgs = [arg];
try {
await (0, common_1.runTask)('Running Gradle build', async () => (0, subprocess_1.runCommand)('./gradlew', gradleArgs, {

View file

@ -1,7 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.editProjectSettingsAndroid = exports.resolvePlugin = exports.getAndroidPlugins = exports.checkAndroidPackage = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const common_1 = require("../common");
const cordova_1 = require("../cordova");
@ -20,12 +20,10 @@ async function resolvePlugin(plugin) {
var _a;
const platform = 'android';
if ((_a = plugin.manifest) === null || _a === void 0 ? void 0 : _a.android) {
let pluginFilesPath = plugin.manifest.android.src
? plugin.manifest.android.src
: platform;
let pluginFilesPath = plugin.manifest.android.src ? plugin.manifest.android.src : platform;
const absolutePath = (0, path_1.join)(plugin.rootPath, pluginFilesPath, plugin.id);
// Android folder shouldn't have subfolders, but they used to, so search for them for compatibility reasons
if (await (0, utils_fs_1.pathExists)(absolutePath)) {
if (await (0, fs_extra_1.pathExists)(absolutePath)) {
pluginFilesPath = (0, path_1.join)(platform, plugin.id);
}
plugin.android = {
@ -38,8 +36,7 @@ async function resolvePlugin(plugin) {
type: 1 /* PluginType.Cordova */,
path: 'src/' + platform,
};
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) ||
!(0, plugin_1.getPluginPlatform)(plugin, platform)) {
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) || !(0, plugin_1.getPluginPlatform)(plugin, platform)) {
plugin.android.type = 2 /* PluginType.Incompatible */;
}
}
@ -65,33 +62,33 @@ async function editProjectSettingsAndroid(config) {
const domainPath = appId.split('.').join('/');
// Make the package source path to the new plugin Java file
const newJavaPath = (0, path_1.resolve)(config.android.srcMainDirAbs, `java/${domainPath}`);
if (!(await (0, utils_fs_1.pathExists)(newJavaPath))) {
await (0, utils_fs_1.mkdirp)(newJavaPath);
if (!(await (0, fs_extra_1.pathExists)(newJavaPath))) {
await (0, fs_extra_1.mkdirp)(newJavaPath);
}
await (0, utils_fs_1.copy)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor/myapp/MainActivity.java'), (0, path_1.resolve)(newJavaPath, 'MainActivity.java'));
await (0, fs_extra_1.copy)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor/myapp/MainActivity.java'), (0, path_1.resolve)(newJavaPath, 'MainActivity.java'));
if (appId.split('.')[1] !== 'getcapacitor') {
await (0, utils_fs_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor'));
await (0, fs_extra_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor'));
}
// Remove our template 'com' folder if their ID doesn't have it
if (appId.split('.')[0] !== 'com') {
await (0, utils_fs_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/'));
await (0, fs_extra_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/'));
}
// Update the package in the MainActivity java file
const activityPath = (0, path_1.resolve)(newJavaPath, 'MainActivity.java');
let activityContent = await (0, utils_fs_1.readFile)(activityPath, { encoding: 'utf-8' });
let activityContent = await (0, fs_extra_1.readFile)(activityPath, { encoding: 'utf-8' });
activityContent = activityContent.replace(/package ([^;]*)/, `package ${appId}`);
await (0, utils_fs_1.writeFile)(activityPath, activityContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(activityPath, activityContent, { encoding: 'utf-8' });
// Update the applicationId in build.gradle
let gradleContent = await (0, utils_fs_1.readFile)(buildGradlePath, { encoding: 'utf-8' });
let gradleContent = await (0, fs_extra_1.readFile)(buildGradlePath, { encoding: 'utf-8' });
gradleContent = gradleContent.replace(/applicationId "[^"]+"/, `applicationId "${appId}"`);
// Update the namespace in build.gradle
gradleContent = gradleContent.replace(/namespace "[^"]+"/, `namespace "${appId}"`);
await (0, utils_fs_1.writeFile)(buildGradlePath, gradleContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(buildGradlePath, gradleContent, { encoding: 'utf-8' });
// Update the settings in res/values/strings.xml
const stringsPath = (0, path_1.resolve)(config.android.resDirAbs, 'values/strings.xml');
let stringsContent = await (0, utils_fs_1.readFile)(stringsPath, { encoding: 'utf-8' });
let stringsContent = await (0, fs_extra_1.readFile)(stringsPath, { encoding: 'utf-8' });
stringsContent = stringsContent.replace(/com.getcapacitor.myapp/g, appId);
stringsContent = stringsContent.replace(/My App/g, appName);
await (0, utils_fs_1.writeFile)(stringsPath, stringsContent);
await (0, fs_extra_1.writeFile)(stringsPath, stringsContent);
}
exports.editProjectSettingsAndroid = editProjectSettingsAndroid;

View file

@ -2,21 +2,18 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.doctorAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const errors_1 = require("../errors");
const log_1 = require("../log");
const fs_1 = require("../util/fs");
const xml_1 = require("../util/xml");
async function doctorAndroid(config) {
var _a;
try {
await (0, common_1.check)([
checkAndroidInstalled,
() => checkGradlew(config),
() => checkAppSrcDirs(config),
]);
await (0, common_1.check)([checkAndroidInstalled, () => checkGradlew(config), () => checkAppSrcDirs(config)]);
(0, log_1.logSuccess)('Android looking great! 👌');
}
catch (e) {
@ -28,20 +25,20 @@ async function doctorAndroid(config) {
}
exports.doctorAndroid = doctorAndroid;
async function checkAppSrcDirs(config) {
if (!(await (0, utils_fs_1.pathExists)(config.android.appDirAbs))) {
if (!(await (0, fs_extra_1.pathExists)(config.android.appDirAbs))) {
return `${colors_1.default.strong(config.android.appDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
if (!(await (0, utils_fs_1.pathExists)(config.android.srcMainDirAbs))) {
if (!(await (0, fs_extra_1.pathExists)(config.android.srcMainDirAbs))) {
return `${colors_1.default.strong(config.android.srcMainDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
if (!(await (0, utils_fs_1.pathExists)(config.android.assetsDirAbs))) {
if (!(await (0, fs_extra_1.pathExists)(config.android.assetsDirAbs))) {
return `${colors_1.default.strong(config.android.assetsDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
if (!(await (0, utils_fs_1.pathExists)(config.android.webDirAbs))) {
if (!(await (0, fs_extra_1.pathExists)(config.android.webDirAbs))) {
return `${colors_1.default.strong(config.android.webDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
const appSrcMainAssetsWwwIndexHtmlDir = (0, path_1.join)(config.android.webDirAbs, 'index.html');
if (!(await (0, utils_fs_1.pathExists)(appSrcMainAssetsWwwIndexHtmlDir))) {
if (!(await (0, fs_extra_1.pathExists)(appSrcMainAssetsWwwIndexHtmlDir))) {
return `${colors_1.default.strong('index.html')} file is missing in ${colors_1.default.strong(config.android.webDirAbs)}`;
}
return checkAndroidManifestFile(config);
@ -49,7 +46,7 @@ async function checkAppSrcDirs(config) {
async function checkAndroidManifestFile(config) {
const manifestFileName = 'AndroidManifest.xml';
const manifestFilePath = (0, path_1.join)(config.android.srcMainDirAbs, manifestFileName);
if (!(await (0, utils_fs_1.pathExists)(manifestFilePath))) {
if (!(await (0, fs_extra_1.pathExists)(manifestFilePath))) {
return `${colors_1.default.strong(manifestFileName)} is missing in ${colors_1.default.strong(config.android.srcMainDir)}`;
}
try {
@ -70,22 +67,22 @@ async function checkAndroidManifestData(config, xmlData) {
return `Missing ${colors_1.default.input('<application>')} XML node as a child node of ${colors_1.default.input('<manifest>')} in ${colors_1.default.strong(config.android.srcMainDir)}`;
}
let mainActivityClassPath = '';
const mainApplicationNode = applicationChildNodes.find(applicationChildNode => {
const mainApplicationNode = applicationChildNodes.find((applicationChildNode) => {
const activityChildNodes = applicationChildNode.activity;
if (!Array.isArray(activityChildNodes)) {
return false;
}
const mainActivityNode = activityChildNodes.find(activityChildNode => {
const mainActivityNode = activityChildNodes.find((activityChildNode) => {
const intentFilterChildNodes = activityChildNode['intent-filter'];
if (!Array.isArray(intentFilterChildNodes)) {
return false;
}
return intentFilterChildNodes.find(intentFilterChildNode => {
return intentFilterChildNodes.find((intentFilterChildNode) => {
const actionChildNodes = intentFilterChildNode.action;
if (!Array.isArray(actionChildNodes)) {
return false;
}
const mainActionChildNode = actionChildNodes.find(actionChildNode => {
const mainActionChildNode = actionChildNodes.find((actionChildNode) => {
const androidName = actionChildNode.$['android:name'];
return androidName === 'android.intent.action.MAIN';
});
@ -96,7 +93,7 @@ async function checkAndroidManifestData(config, xmlData) {
if (!Array.isArray(categoryChildNodes)) {
return false;
}
return categoryChildNodes.find(categoryChildNode => {
return categoryChildNodes.find((categoryChildNode) => {
const androidName = categoryChildNode.$['android:name'];
return androidName === 'android.intent.category.LAUNCHER';
});
@ -117,12 +114,12 @@ async function checkAndroidManifestData(config, xmlData) {
}
async function checkPackage(config, mainActivityClassPath) {
const appSrcMainJavaDir = (0, path_1.join)(config.android.srcMainDirAbs, 'java');
if (!(await (0, utils_fs_1.pathExists)(appSrcMainJavaDir))) {
if (!(await (0, fs_extra_1.pathExists)(appSrcMainJavaDir))) {
return `${colors_1.default.strong('java')} directory is missing in ${colors_1.default.strong(appSrcMainJavaDir)}`;
}
const mainActivityClassName = mainActivityClassPath.split('.').pop();
const srcFiles = await (0, utils_fs_1.readdirp)(appSrcMainJavaDir, {
filter: entry => !entry.stats.isDirectory() &&
const srcFiles = await (0, fs_1.readdirp)(appSrcMainJavaDir, {
filter: (entry) => !entry.stats.isDirectory() &&
['.java', '.kt'].includes((0, path_1.extname)(entry.path)) &&
mainActivityClassName === (0, path_1.parse)(entry.path).name,
});
@ -134,10 +131,10 @@ async function checkPackage(config, mainActivityClassPath) {
async function checkBuildGradle(config) {
const fileName = 'build.gradle';
const filePath = (0, path_1.join)(config.android.appDirAbs, fileName);
if (!(await (0, utils_fs_1.pathExists)(filePath))) {
if (!(await (0, fs_extra_1.pathExists)(filePath))) {
return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.appDir)}`;
}
let fileContent = await (0, utils_fs_1.readFile)(filePath, { encoding: 'utf-8' });
let fileContent = await (0, fs_extra_1.readFile)(filePath, { encoding: 'utf-8' });
fileContent = fileContent.replace(/'|"/g, '').replace(/\s+/g, ' ');
const searchFor = `applicationId`;
if (fileContent.indexOf(searchFor) === -1) {
@ -148,7 +145,7 @@ async function checkBuildGradle(config) {
async function checkGradlew(config) {
const fileName = 'gradlew';
const filePath = (0, path_1.join)(config.android.platformDirAbs, fileName);
if (!(await (0, utils_fs_1.pathExists)(filePath))) {
if (!(await (0, fs_extra_1.pathExists)(filePath))) {
return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.platformDir)}`;
}
return null;

View file

@ -2,8 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.openAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const fs_extra_1 = require("fs-extra");
const open_1 = tslib_1.__importDefault(require("open"));
const colors_1 = tslib_1.__importDefault(require("../colors"));
const log_1 = require("../log");
@ -12,7 +12,7 @@ async function openAndroid(config) {
const androidStudioPath = await config.android.studioPath;
const dir = config.android.platformDirAbs;
try {
if (!(await (0, utils_fs_1.pathExists)(androidStudioPath))) {
if (!(await (0, fs_extra_1.pathExists)(androidStudioPath))) {
throw new Error(`Android Studio does not exist at: ${androidStudioPath}`);
}
await (0, open_1.default)(dir, { app: { name: androidStudioPath }, wait: false });

View file

@ -9,7 +9,7 @@ const common_1 = require("../common");
const native_run_1 = require("../util/native-run");
const subprocess_1 = require("../util/subprocess");
const debug = (0, debug_1.default)('capacitor:android:run');
async function runAndroid(config, { target: selectedTarget, flavor: selectedFlavor, forwardPorts: selectedPorts, }) {
async function runAndroid(config, { target: selectedTarget, flavor: selectedFlavor, forwardPorts: selectedPorts }) {
var _a;
const target = await (0, common_1.promptForPlatformTarget)(await (0, native_run_1.getPlatformTargets)('android'), selectedTarget);
const runFlavor = selectedFlavor || ((_a = config.android) === null || _a === void 0 ? void 0 : _a.flavor) || '';

View file

@ -2,8 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleCordovaPluginsGradle = exports.installGradlePlugins = exports.updateAndroid = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
@ -19,25 +19,26 @@ const common_2 = require("./common");
const platform = 'android';
const debug = (0, debug_1.default)('capacitor:android:update');
async function updateAndroid(config) {
var _a;
const plugins = await getPluginsTask(config);
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
const capacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
(0, plugin_1.printPlugins)(capacitorPlugins, 'android');
await writePluginsJson(config, capacitorPlugins);
await removePluginsNativeFiles(config);
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
await (0, migrate_1.patchOldCapacitorPlugins)(config);
if (cordovaPlugins.length > 0) {
await copyPluginsNativeFiles(config, cordovaPlugins);
}
if (!(await (0, utils_fs_1.pathExists)(config.android.webDirAbs))) {
if (!(await (0, fs_extra_1.pathExists)(config.android.webDirAbs))) {
await (0, copy_1.copy)(config, platform);
}
await (0, cordova_1.handleCordovaPluginsJS)(cordovaPlugins, config, platform);
await (0, cordova_1.checkPluginDependencies)(plugins, platform);
await (0, cordova_1.checkPluginDependencies)(plugins, platform, (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.failOnUninstalledPlugins);
await installGradlePlugins(config, capacitorPlugins, cordovaPlugins);
await handleCordovaPluginsGradle(config, cordovaPlugins);
await (0, cordova_1.writeCordovaAndroidManifest)(cordovaPlugins, config, platform);
const incompatibleCordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
const incompatibleCordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
await (0, common_1.checkPlatformVersions)(config, platform);
}
@ -48,7 +49,7 @@ function getGradlePackageName(id) {
async function writePluginsJson(config, plugins) {
const classes = await findAndroidPluginClasses(plugins);
const pluginsJsonPath = (0, path_1.resolve)(config.android.assetsDirAbs, 'capacitor.plugins.json');
await (0, utils_fs_1.writeJSON)(pluginsJsonPath, classes, { spaces: '\t' });
await (0, fs_extra_1.writeJSON)(pluginsJsonPath, classes, { spaces: '\t' });
}
async function findAndroidPluginClasses(plugins) {
const entries = [];
@ -62,15 +63,14 @@ async function findAndroidPluginClassesInPlugin(plugin) {
return [];
}
const srcPath = (0, path_1.resolve)(plugin.rootPath, plugin.android.path, 'src/main');
const srcFiles = await (0, utils_fs_1.readdirp)(srcPath, {
filter: entry => !entry.stats.isDirectory() &&
['.java', '.kt'].includes((0, path_1.extname)(entry.path)),
const srcFiles = await (0, fs_1.readdirp)(srcPath, {
filter: (entry) => !entry.stats.isDirectory() && ['.java', '.kt'].includes((0, path_1.extname)(entry.path)),
});
const classRegex = /^@(?:CapacitorPlugin|NativePlugin)[\s\S]+?class ([\w]+)/gm;
const packageRegex = /^package ([\w.]+);?$/gm;
debug('Searching %O source files in %O by %O regex', srcFiles.length, srcPath, classRegex);
const entries = await Promise.all(srcFiles.map(async (srcFile) => {
const srcFileContents = await (0, utils_fs_1.readFile)(srcFile, { encoding: 'utf-8' });
const srcFileContents = await (0, fs_extra_1.readFile)(srcFile, { encoding: 'utf-8' });
classRegex.lastIndex = 0;
const classMatch = classRegex.exec(srcFileContents);
if (classMatch) {
@ -79,8 +79,7 @@ async function findAndroidPluginClassesInPlugin(plugin) {
packageRegex.lastIndex = 0;
const packageMatch = packageRegex.exec(srcFileContents.substring(0, classMatch.index));
if (!packageMatch) {
(0, errors_1.fatal)(`Package could not be parsed from Android plugin.\n` +
`Location: ${colors_1.default.strong(srcFile)}`);
(0, errors_1.fatal)(`Package could not be parsed from Android plugin.\n` + `Location: ${colors_1.default.strong(srcFile)}`);
}
const packageName = packageMatch[1];
const classpath = `${packageName}.${className}`;
@ -107,7 +106,7 @@ async function installGradlePlugins(config, capacitorPlugins, cordovaPlugins) {
include ':capacitor-android'
project(':capacitor-android').projectDir = new File('${relativeCapcitorAndroidPath}')
${capacitorPlugins
.map(p => {
.map((p) => {
if (!p.android) {
return '';
}
@ -121,7 +120,7 @@ project(':${getGradlePackageName(p.id)}').projectDir = new File('${relativePlugi
const applyArray = [];
const frameworksArray = [];
let prefsArray = [];
cordovaPlugins.map(p => {
cordovaPlugins.map((p) => {
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(dependencyPath, p.rootPath));
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
frameworks.map((framework) => {
@ -148,15 +147,15 @@ project(':${getGradlePackageName(p.id)}').projectDir = new File('${relativePlugi
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
sourceCompatibility JavaVersion.VERSION_21
targetCompatibility JavaVersion.VERSION_21
}
}
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
dependencies {
${capacitorPlugins
.map(p => {
.map((p) => {
return ` implementation project(':${getGradlePackageName(p.id)}')`;
})
.join('\n')}
@ -168,20 +167,20 @@ if (hasProperty('postBuildExtras')) {
postBuildExtras()
}
`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(settingsPath, 'capacitor.settings.gradle'), settingsLines);
await (0, utils_fs_1.writeFile)((0, path_1.join)(dependencyPath, 'capacitor.build.gradle'), dependencyLines);
await (0, fs_extra_1.writeFile)((0, path_1.join)(settingsPath, 'capacitor.settings.gradle'), settingsLines);
await (0, fs_extra_1.writeFile)((0, path_1.join)(dependencyPath, 'capacitor.build.gradle'), dependencyLines);
}
exports.installGradlePlugins = installGradlePlugins;
async function handleCordovaPluginsGradle(config, cordovaPlugins) {
var _a, _b, _c;
const pluginsGradlePath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'build.gradle');
const kotlinNeeded = await kotlinNeededCheck(config, cordovaPlugins);
const kotlinVersionString = (_c = (_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinVersion) !== null && _c !== void 0 ? _c : '1.8.20';
const kotlinVersionString = (_c = (_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinVersion) !== null && _c !== void 0 ? _c : '1.9.25';
const frameworksArray = [];
let prefsArray = [];
const applyArray = [];
applyArray.push(`apply from: "cordova.variables.gradle"`);
cordovaPlugins.map(p => {
cordovaPlugins.map((p) => {
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(config.android.cordovaPluginsDirAbs, p.rootPath));
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
frameworks.map((framework) => {
@ -198,7 +197,7 @@ async function handleCordovaPluginsGradle(config, cordovaPlugins) {
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(p, platform, 'preference'));
});
let frameworkString = frameworksArray
.map(f => {
.map((f) => {
if (f.startsWith('platform(')) {
return ` implementation ${f}`;
}
@ -213,7 +212,7 @@ async function handleCordovaPluginsGradle(config, cordovaPlugins) {
frameworkString += `\n implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"`;
}
const applyString = applyArray.join('\n');
let buildGradle = await (0, utils_fs_1.readFile)(pluginsGradlePath, { encoding: 'utf-8' });
let buildGradle = await (0, fs_extra_1.readFile)(pluginsGradlePath, { encoding: 'utf-8' });
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + frameworkString.concat('\n') + ' $2');
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + applyString.concat('\n') + '$2');
if (kotlinNeeded) {
@ -223,7 +222,7 @@ async function handleCordovaPluginsGradle(config, cordovaPlugins) {
buildGradle = buildGradle.replace(/(apply\splugin:\s'com\.android\.library')/, `$1\napply plugin: 'kotlin-android'`);
buildGradle = buildGradle.replace(/(compileOptions\s{\n((\t{2}|\s{8}).+\n)+(\t|\s{4})})\n(})/, `$1\n sourceSets {\n main.java.srcDirs += 'src/main/kotlin'\n }\n$5`);
}
await (0, utils_fs_1.writeFile)(pluginsGradlePath, buildGradle);
await (0, fs_extra_1.writeFile)(pluginsGradlePath, buildGradle);
const cordovaVariables = `// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
ext {
cdvMinSdkVersion = project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : ${config.android.minVersion}
@ -231,13 +230,12 @@ ext {
cdvPluginPostBuildExtras = []
cordovaConfig = [:]
}`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(config.android.cordovaPluginsDirAbs, 'cordova.variables.gradle'), cordovaVariables);
await (0, fs_extra_1.writeFile)((0, path_1.join)(config.android.cordovaPluginsDirAbs, 'cordova.variables.gradle'), cordovaVariables);
}
exports.handleCordovaPluginsGradle = handleCordovaPluginsGradle;
async function kotlinNeededCheck(config, cordovaPlugins) {
var _a, _b;
if (((_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinEnabled) !==
'true') {
if (((_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinEnabled) !== 'true') {
for (const plugin of cordovaPlugins) {
const androidPlatform = (0, plugin_1.getPluginPlatform)(plugin, platform);
const sourceFiles = androidPlatform['source-file'];
@ -268,10 +266,8 @@ async function copyPluginsNativeFiles(config, cordovaPlugins) {
if (fileName.split('.').pop() === 'aidl') {
baseFolder = 'aidl/';
}
const target = sourceFile.$['target-dir']
.replace('app/src/main/', '')
.replace('src/', baseFolder);
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, sourceFile.$.src), (0, path_1.join)(pluginsPath, target, fileName));
const target = sourceFile.$['target-dir'].replace('app/src/main/', '').replace('src/', baseFolder);
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, sourceFile.$.src), (0, path_1.join)(pluginsPath, target, fileName));
}
}
const resourceFiles = androidPlatform['resource-file'];
@ -279,22 +275,22 @@ async function copyPluginsNativeFiles(config, cordovaPlugins) {
for (const resourceFile of resourceFiles) {
const target = resourceFile.$['target'];
if (resourceFile.$.src.split('.').pop() === 'aar') {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, 'libs', target.split('/').pop()));
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, 'libs', target.split('/').pop()));
}
else if (target !== '.') {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, target));
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, target));
}
}
}
const libFiles = (0, plugin_1.getPlatformElement)(p, platform, 'lib-file');
for (const libFile of libFiles) {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, libFile.$.src), (0, path_1.join)(pluginsPath, 'libs', libFile.$.src.split('/').pop()));
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, libFile.$.src), (0, path_1.join)(pluginsPath, 'libs', libFile.$.src.split('/').pop()));
}
}
}
}
async function removePluginsNativeFiles(config) {
await (0, utils_fs_1.remove)(config.android.cordovaPluginsDirAbs);
await (0, fs_extra_1.remove)(config.android.cordovaPluginsDirAbs);
await (0, template_1.extractTemplate)(config.cli.assets.android.cordovaPluginsTemplateArchiveAbs, config.android.cordovaPluginsDirAbs);
}
async function getPluginsTask(config) {
@ -307,8 +303,8 @@ async function getPluginsTask(config) {
async function getVariablesGradleFile(config) {
const variablesFile = (0, path_1.resolve)(config.android.platformDirAbs, 'variables.gradle');
let variablesGradle = '';
if (await (0, utils_fs_1.pathExists)(variablesFile)) {
variablesGradle = await (0, utils_fs_1.readFile)(variablesFile, { encoding: 'utf-8' });
if (await (0, fs_extra_1.pathExists)(variablesFile)) {
variablesGradle = await (0, fs_extra_1.readFile)(variablesFile, { encoding: 'utf-8' });
}
return variablesGradle;
}

View file

@ -2,8 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseApkNameFromFlavor = exports.checkJDKMajorVersion = exports.resolvePlatform = exports.checkPlatformVersions = exports.getAddedPlatforms = exports.getPlatformTargetName = exports.promptForPlatformTarget = exports.promptForPlatform = exports.isValidEnterprisePlatform = exports.getKnownEnterprisePlatforms = exports.isValidCommunityPlatform = exports.getKnownCommunityPlatforms = exports.isValidPlatform = exports.getKnownPlatforms = exports.selectPlatforms = exports.getProjectPlatformDirectory = exports.getCLIVersion = exports.getCoreVersion = exports.getCapacitorPackageVersion = exports.requireCapacitorPackage = exports.getCapacitorPackage = exports.runTask = exports.runPlatformHook = exports.runHooks = exports.wait = exports.checkAppName = exports.checkAppId = exports.checkAppDir = exports.checkAppConfig = exports.checkCapacitorPlatform = exports.checkPackage = exports.checkWebDir = exports.check = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const utils_terminal_1 = require("@ionic/utils-terminal");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const errors_1 = require("./errors");
@ -13,8 +13,8 @@ const monorepotools_1 = require("./util/monorepotools");
const node_1 = require("./util/node");
const subprocess_1 = require("./util/subprocess");
async function check(checks) {
const results = await Promise.all(checks.map(f => f()));
const errors = results.filter(r => r != null);
const results = await Promise.all(checks.map((f) => f()));
const errors = results.filter((r) => r != null);
if (errors.length > 0) {
throw errors.join('\n');
}
@ -30,11 +30,11 @@ async function checkWebDir(config) {
if (invalidFolders.includes(config.app.webDir)) {
return `"${config.app.webDir}" is not a valid value for webDir`;
}
if (!(await (0, utils_fs_1.pathExists)(config.app.webDirAbs))) {
if (!(await (0, fs_extra_1.pathExists)(config.app.webDirAbs))) {
return (`Could not find the web assets directory: ${colors_1.default.strong((0, utils_terminal_1.prettyPath)(config.app.webDirAbs))}.\n` +
`Please create it and make sure it has an ${colors_1.default.strong('index.html')} file. You can change the path of this directory in ${colors_1.default.strong(config.app.extConfigName)} (${colors_1.default.input('webDir')} option). You may need to compile the web assets for your app (typically ${colors_1.default.input('npm run build')}). More info: ${colors_1.default.strong('https://capacitorjs.com/docs/basics/workflow#sync-your-project')}`);
}
if (!(await (0, utils_fs_1.pathExists)((0, path_1.join)(config.app.webDirAbs, 'index.html')))) {
if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(config.app.webDirAbs, 'index.html')))) {
return (`The web assets directory (${colors_1.default.strong((0, utils_terminal_1.prettyPath)(config.app.webDirAbs))}) must contain an ${colors_1.default.strong('index.html')} file.\n` +
`It will be the entry point for the web portion of the Capacitor app.`);
}
@ -42,8 +42,8 @@ async function checkWebDir(config) {
}
exports.checkWebDir = checkWebDir;
async function checkPackage() {
if (!(await (0, utils_fs_1.pathExists)('package.json'))) {
if (await (0, utils_fs_1.pathExists)('project.json')) {
if (!(await (0, fs_extra_1.pathExists)('package.json'))) {
if (await (0, fs_extra_1.pathExists)('project.json')) {
return null;
}
else {
@ -93,12 +93,20 @@ async function checkAppDir(config, dir) {
exports.checkAppDir = checkAppDir;
async function checkAppId(config, id) {
if (!id) {
return `Invalid App ID. Must be in Java package form with no dashes (ex: com.example.app)`;
return `Invalid App ID. App ID is required and cannot be blank.`;
}
if (/^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+$/.test(id.toLowerCase())) {
if (/^[a-zA-Z][\w]*(?:\.[a-zA-Z][\w]*)+$/.test(id.toLowerCase())) {
return null;
}
return `Invalid App ID "${id}". Must be in Java package form with no dashes (ex: com.example.app)`;
return `
Invalid App ID "${id}". Your App ID must meet the following requirements to be valid on both iOS and Android:
- Must be in Java package form with no dashes (ex: com.example.app)
- It must have at least two segments (one or more dots).
- Each segment must start with a letter.
- All characters must be alphanumeric or an underscore [a-zA-Z][a-zA-Z0-9]+.
If you would like to skip validation, run "cap init" with the "--skip-appid-validation" flag.
`;
}
exports.checkAppId = checkAppId;
async function checkAppName(config, name) {
@ -110,15 +118,15 @@ async function checkAppName(config, name) {
}
exports.checkAppName = checkAppName;
async function wait(time) {
return new Promise(resolve => setTimeout(resolve, time));
return new Promise((resolve) => setTimeout(resolve, time));
}
exports.wait = wait;
async function runHooks(config, platformName, dir, hook) {
await runPlatformHook(config, platformName, dir, hook);
const allPlugins = await (0, plugin_1.getPlugins)(config, platformName);
allPlugins.forEach(async (p) => {
for (const p of allPlugins) {
await runPlatformHook(config, platformName, p.rootPath, hook);
});
}
}
exports.runHooks = runHooks;
async function runPlatformHook(config, platformName, platformDir, hook) {
@ -126,10 +134,10 @@ async function runPlatformHook(config, platformName, platformDir, hook) {
const { spawn } = await Promise.resolve().then(() => tslib_1.__importStar(require('child_process')));
let pkg;
if ((0, monorepotools_1.isNXMonorepo)(platformDir)) {
pkg = await (0, utils_fs_1.readJSON)((0, path_1.join)((0, monorepotools_1.findNXMonorepoRoot)(platformDir), 'package.json'));
pkg = await (0, fs_extra_1.readJSON)((0, path_1.join)((0, monorepotools_1.findNXMonorepoRoot)(platformDir), 'package.json'));
}
else {
pkg = await (0, utils_fs_1.readJSON)((0, path_1.join)(platformDir, 'package.json'));
pkg = await (0, fs_extra_1.readJSON)((0, path_1.join)(platformDir, 'package.json'));
}
const cmd = (_a = pkg.scripts) === null || _a === void 0 ? void 0 : _a[hook];
if (!cmd) {
@ -149,10 +157,15 @@ async function runPlatformHook(config, platformName, platformDir, hook) {
...process.env,
},
});
p.on('close', () => {
resolve();
p.on('close', (code) => {
if (code === 0) {
resolve();
}
else {
reject(new Error(`${hook} hook on ${platformName} failed with error code: ${code} while running command: ${cmd}`));
}
});
p.on('error', err => {
p.on('error', (err) => {
reject(err);
});
});
@ -177,7 +190,7 @@ async function getCapacitorPackage(config, name) {
if (!packagePath) {
return null;
}
return (0, utils_fs_1.readJSON)(packagePath);
return (0, fs_extra_1.readJSON)(packagePath);
}
exports.getCapacitorPackage = getCapacitorPackage;
async function requireCapacitorPackage(config, name) {
@ -214,7 +227,7 @@ function getPlatformDirectory(config, platform) {
}
async function getProjectPlatformDirectory(config, platform) {
const platformPath = getPlatformDirectory(config, platform);
if (platformPath && (await (0, utils_fs_1.pathExists)(platformPath))) {
if (platformPath && (await (0, fs_extra_1.pathExists)(platformPath))) {
return platformPath;
}
return null;
@ -229,8 +242,7 @@ async function selectPlatforms(config, selectedPlatformName) {
}
else if (!(await getProjectPlatformDirectory(config, platformName))) {
if (platformName === 'web') {
(0, errors_1.fatal)(`Could not find the web platform directory.\n` +
`Make sure ${colors_1.default.strong(config.app.webDir)} exists.`);
(0, errors_1.fatal)(`Could not find the web platform directory.\n` + `Make sure ${colors_1.default.strong(config.app.webDir)} exists.`);
}
(0, errors_1.fatal)(`${colors_1.default.strong(platformName)} platform has not been added yet.\n` +
`See the docs for adding the ${colors_1.default.strong(platformName)} platform: ${colors_1.default.strong(`https://capacitorjs.com/docs/${platformName}#adding-the-${platformName}-platform`)}`);
@ -275,7 +287,7 @@ async function promptForPlatform(platforms, promptMessage, selectedPlatformName)
type: 'select',
name: 'mode',
message: promptMessage,
choices: platforms.map(p => ({ title: p, value: p })),
choices: platforms.map((p) => ({ title: p, value: p })),
},
], { onCancel: () => process.exit(1) });
return answers.mode.toLowerCase().trim();
@ -283,15 +295,14 @@ async function promptForPlatform(platforms, promptMessage, selectedPlatformName)
const platformName = selectedPlatformName.toLowerCase().trim();
if (!(await isValidPlatform(platformName))) {
const knownPlatforms = await getKnownPlatforms();
(0, errors_1.fatal)(`Invalid platform: ${colors_1.default.input(platformName)}.\n` +
`Valid platforms include: ${knownPlatforms.join(', ')}`);
(0, errors_1.fatal)(`Invalid platform: ${colors_1.default.input(platformName)}.\n` + `Valid platforms include: ${knownPlatforms.join(', ')}`);
}
return platformName;
}
exports.promptForPlatform = promptForPlatform;
async function promptForPlatformTarget(targets, selectedTarget) {
const { prompt } = await Promise.resolve().then(() => tslib_1.__importStar(require('prompts')));
const validTargets = targets.filter(t => t.id !== undefined);
const validTargets = targets.filter((t) => t.id !== undefined);
if (!selectedTarget) {
if (validTargets.length === 1) {
return validTargets[0];
@ -302,7 +313,7 @@ async function promptForPlatformTarget(targets, selectedTarget) {
type: 'select',
name: 'target',
message: 'Please choose a target device:',
choices: validTargets.map(t => ({
choices: validTargets.map((t) => ({
title: `${getPlatformTargetName(t)} (${t.id})`,
value: t,
})),
@ -312,19 +323,16 @@ async function promptForPlatformTarget(targets, selectedTarget) {
}
}
const targetID = selectedTarget.trim();
const target = targets.find(t => t.id === targetID);
const target = targets.find((t) => t.id === targetID);
if (!target) {
(0, errors_1.fatal)(`Invalid target ID: ${colors_1.default.input(targetID)}.\n` +
`Valid targets are: ${targets.map(t => t.id).join(', ')}`);
(0, errors_1.fatal)(`Invalid target ID: ${colors_1.default.input(targetID)}.\n` + `Valid targets are: ${targets.map((t) => t.id).join(', ')}`);
}
return target;
}
exports.promptForPlatformTarget = promptForPlatformTarget;
function getPlatformTargetName(target) {
var _a, _b, _c;
return `${(_c = (_b = (_a = target.name) !== null && _a !== void 0 ? _a : target.model) !== null && _b !== void 0 ? _b : target.id) !== null && _c !== void 0 ? _c : '?'}${target.virtual
? ` (${target.platform === 'ios' ? 'simulator' : 'emulator'})`
: ''}`;
return `${(_c = (_b = (_a = target.name) !== null && _a !== void 0 ? _a : target.model) !== null && _b !== void 0 ? _b : target.id) !== null && _c !== void 0 ? _c : '?'}${target.virtual ? ` (${target.platform === 'ios' ? 'simulator' : 'emulator'})` : ''}`;
}
exports.getPlatformTargetName = getPlatformTargetName;
async function getAddedPlatforms(config) {
@ -343,8 +351,7 @@ async function checkPlatformVersions(config, platform) {
const semver = await Promise.resolve().then(() => tslib_1.__importStar(require('semver')));
const coreVersion = await getCoreVersion(config);
const platformVersion = await getCapacitorPackageVersion(config, platform);
if (semver.diff(coreVersion, platformVersion) === 'minor' ||
semver.diff(coreVersion, platformVersion) === 'major') {
if (semver.diff(coreVersion, platformVersion) === 'minor' || semver.diff(coreVersion, platformVersion) === 'major') {
log_1.logger.warn(`${colors_1.default.strong('@capacitor/core')}${colors_1.default.weak(`@${coreVersion}`)} version doesn't match ${colors_1.default.strong(`@capacitor/${platform}`)}${colors_1.default.weak(`@${platformVersion}`)} version.\n` +
`Consider updating to a matching version, e.g. w/ ${colors_1.default.input(`npm install @capacitor/core@${platformVersion}`)}`);
}
@ -386,9 +393,7 @@ async function checkJDKMajorVersion() {
if (typeof firstVersionNumber === 'number' && firstVersionNumber != 1) {
return firstVersionNumber;
}
else if (typeof secondVersionNumber === 'number' &&
firstVersionNumber == 1 &&
secondVersionNumber < 9) {
else if (typeof secondVersionNumber === 'number' && firstVersionNumber == 1 && secondVersionNumber < 9) {
return secondVersionNumber;
}
else {

View file

@ -1,9 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkExternalConfig = exports.writeConfig = exports.loadConfig = exports.CONFIG_FILE_NAME_JSON = exports.CONFIG_FILE_NAME_JS = exports.CONFIG_FILE_NAME_TS = void 0;
exports.writeConfig = exports.loadConfig = exports.CONFIG_FILE_NAME_JSON = exports.CONFIG_FILE_NAME_JS = exports.CONFIG_FILE_NAME_TS = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const common_1 = require("./common");
@ -28,7 +28,7 @@ async function loadConfig() {
var _a, _b;
if ((0, monorepotools_1.isNXMonorepo)(appRootDir)) {
const rootOfNXMonorepo = (0, monorepotools_1.findNXMonorepoRoot)(appRootDir);
const pkgJSONOfMonorepoRoot = await (0, fn_1.tryFn)(utils_fs_1.readJSON, (0, path_1.resolve)(rootOfNXMonorepo, 'package.json'));
const pkgJSONOfMonorepoRoot = await (0, fn_1.tryFn)(fs_extra_1.readJSON, (0, path_1.resolve)(rootOfNXMonorepo, 'package.json'));
const devDependencies = (_a = pkgJSONOfMonorepoRoot === null || pkgJSONOfMonorepoRoot === void 0 ? void 0 : pkgJSONOfMonorepoRoot.devDependencies) !== null && _a !== void 0 ? _a : {};
const dependencies = (_b = pkgJSONOfMonorepoRoot === null || pkgJSONOfMonorepoRoot === void 0 ? void 0 : pkgJSONOfMonorepoRoot.dependencies) !== null && _b !== void 0 ? _b : {};
return {
@ -53,7 +53,7 @@ async function loadConfig() {
appName,
webDir,
webDirAbs: (0, path_1.resolve)(appRootDir, webDir),
package: (_d = (await (0, fn_1.tryFn)(utils_fs_1.readJSON, (0, path_1.resolve)(appRootDir, 'package.json')))) !== null && _d !== void 0 ? _d : {
package: (_d = (await (0, fn_1.tryFn)(fs_extra_1.readJSON, (0, path_1.resolve)(appRootDir, 'package.json')))) !== null && _d !== void 0 ? _d : {
name: appName,
version: '1.0.0',
...depsForNx,
@ -68,11 +68,11 @@ exports.loadConfig = loadConfig;
async function writeConfig(extConfig, extConfigFilePath) {
switch ((0, path_1.extname)(extConfigFilePath)) {
case '.json': {
await (0, utils_fs_1.writeJSON)(extConfigFilePath, extConfig, { spaces: 2 });
await (0, fs_extra_1.writeJSON)(extConfigFilePath, extConfig, { spaces: 2 });
break;
}
case '.ts': {
await (0, utils_fs_1.writeFile)(extConfigFilePath, formatConfigTS(extConfig));
await (0, fs_extra_1.writeFile)(extConfigFilePath, formatConfigTS(extConfig));
break;
}
}
@ -88,9 +88,7 @@ async function loadExtConfigTS(rootDir, extConfigName, extConfigFilePath) {
}
const ts = require(tsPath); // eslint-disable-line @typescript-eslint/no-var-requires
const extConfigObject = (0, node_1.requireTS)(ts, extConfigFilePath);
const extConfig = extConfigObject.default
? await extConfigObject.default
: extConfigObject;
const extConfig = extConfigObject.default ? await extConfigObject.default : extConfigObject;
return {
extConfigType: 'ts',
extConfigName,
@ -122,11 +120,11 @@ async function loadExtConfigJS(rootDir, extConfigName, extConfigFilePath) {
async function loadExtConfig(rootDir) {
var _a;
const extConfigFilePathTS = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_TS);
if (await (0, utils_fs_1.pathExists)(extConfigFilePathTS)) {
if (await (0, fs_extra_1.pathExists)(extConfigFilePathTS)) {
return loadExtConfigTS(rootDir, exports.CONFIG_FILE_NAME_TS, extConfigFilePathTS);
}
const extConfigFilePathJS = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_JS);
if (await (0, utils_fs_1.pathExists)(extConfigFilePathJS)) {
if (await (0, fs_extra_1.pathExists)(extConfigFilePathJS)) {
return loadExtConfigJS(rootDir, exports.CONFIG_FILE_NAME_JS, extConfigFilePathJS);
}
const extConfigFilePath = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_JSON);
@ -134,7 +132,7 @@ async function loadExtConfig(rootDir) {
extConfigType: 'json',
extConfigName: exports.CONFIG_FILE_NAME_JSON,
extConfigFilePath: extConfigFilePath,
extConfig: (_a = (await (0, fn_1.tryFn)(utils_fs_1.readJSON, extConfigFilePath))) !== null && _a !== void 0 ? _a : {},
extConfig: (_a = (await (0, fn_1.tryFn)(fs_extra_1.readJSON, extConfigFilePath))) !== null && _a !== void 0 ? _a : {},
};
}
async function loadCLIConfig(rootDir) {
@ -162,7 +160,7 @@ async function loadCLIConfig(rootDir) {
cordovaPluginsTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, androidCordovaPluginsTemplateArchive),
},
},
package: await (0, utils_fs_1.readJSON)((0, path_1.resolve)(rootDir, 'package.json')),
package: await (0, fs_extra_1.readJSON)((0, path_1.resolve)(rootDir, 'package.json')),
os: determineOS(process.platform),
};
}
@ -196,7 +194,7 @@ async function loadAndroidConfig(rootDir, extConfig, cliConfig) {
};
return {
name,
minVersion: '22',
minVersion: '23',
studioPath,
platformDir,
platformDirAbs,
@ -222,7 +220,7 @@ async function loadAndroidConfig(rootDir, extConfig, cliConfig) {
};
}
async function loadIOSConfig(rootDir, extConfig) {
var _a, _b, _c, _d;
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
const name = 'ios';
const platformDir = (_b = (_a = extConfig.ios) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : 'ios';
const platformDirAbs = (0, path_1.resolve)(rootDir, platformDir);
@ -237,9 +235,15 @@ async function loadIOSConfig(rootDir, extConfig) {
const podPath = (0, promise_1.lazy)(() => determineGemfileOrCocoapodPath(rootDir, platformDirAbs, nativeProjectDirAbs));
const webDirAbs = (0, promise_1.lazy)(() => determineIOSWebDirAbs(nativeProjectDirAbs, nativeTargetDirAbs, nativeXcodeProjDirAbs));
const cordovaPluginsDir = 'capacitor-cordova-ios-plugins';
const buildOptions = {
exportMethod: (_f = (_e = extConfig.ios) === null || _e === void 0 ? void 0 : _e.buildOptions) === null || _f === void 0 ? void 0 : _f.exportMethod,
xcodeSigningStyle: (_h = (_g = extConfig.ios) === null || _g === void 0 ? void 0 : _g.buildOptions) === null || _h === void 0 ? void 0 : _h.signingStyle,
signingCertificate: (_k = (_j = extConfig.ios) === null || _j === void 0 ? void 0 : _j.buildOptions) === null || _k === void 0 ? void 0 : _k.signingCertificate,
provisioningProfile: (_m = (_l = extConfig.ios) === null || _l === void 0 ? void 0 : _l.buildOptions) === null || _m === void 0 ? void 0 : _m.provisioningProfile,
};
return {
name,
minVersion: '13.0',
minVersion: '14.0',
platformDir,
platformDirAbs,
scheme,
@ -256,6 +260,7 @@ async function loadIOSConfig(rootDir, extConfig) {
webDir: (0, promise_1.lazy)(async () => (0, path_1.relative)(platformDirAbs, await webDirAbs)),
webDirAbs,
podPath,
buildOptions,
};
}
async function loadWebConfig(rootDir, webDir) {
@ -285,7 +290,7 @@ async function determineIOSWebDirAbs(nativeProjectDirAbs, nativeTargetDirAbs, na
const re = /path\s=\spublic[\s\S]+?sourceTree\s=\s([^;]+)/;
const pbxprojPath = (0, path_1.resolve)(nativeXcodeProjDirAbs, 'project.pbxproj');
try {
const pbxproj = await (0, utils_fs_1.readFile)(pbxprojPath, { encoding: 'utf8' });
const pbxproj = await (0, fs_extra_1.readFile)(pbxprojPath, { encoding: 'utf8' });
const m = pbxproj.match(re);
if (m && m[1] === 'SOURCE_ROOT') {
log_1.logger.warn(`Using the iOS project root for the ${colors_1.default.strong('public')} directory is deprecated.\n` +
@ -309,7 +314,7 @@ async function determineAndroidStudioPath(os) {
const { runCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./util/subprocess')));
let p = 'C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe';
try {
if (!(await (0, utils_fs_1.pathExists)(p))) {
if (!(await (0, fs_extra_1.pathExists)(p))) {
let commandResult = await runCommand('REG', [
'QUERY',
'HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio',
@ -339,13 +344,13 @@ async function determineGemfileOrCocoapodPath(rootDir, platformDir, nativeProjec
return process.env.CAPACITOR_COCOAPODS_PATH;
}
let gemfilePath = '';
if (await (0, utils_fs_1.pathExists)((0, path_1.resolve)(rootDir, 'Gemfile'))) {
if (await (0, fs_extra_1.pathExists)((0, path_1.resolve)(rootDir, 'Gemfile'))) {
gemfilePath = (0, path_1.resolve)(rootDir, 'Gemfile');
}
else if (await (0, utils_fs_1.pathExists)((0, path_1.resolve)(platformDir, 'Gemfile'))) {
else if (await (0, fs_extra_1.pathExists)((0, path_1.resolve)(platformDir, 'Gemfile'))) {
gemfilePath = (0, path_1.resolve)(platformDir, 'Gemfile');
}
else if (await (0, utils_fs_1.pathExists)((0, path_1.resolve)(nativeProjectDirAbs, 'Gemfile'))) {
else if (await (0, fs_extra_1.pathExists)((0, path_1.resolve)(nativeProjectDirAbs, 'Gemfile'))) {
gemfilePath = (0, path_1.resolve)(nativeProjectDirAbs, 'Gemfile');
}
const appSpecificGemfileExists = gemfilePath != '';
@ -362,7 +367,7 @@ async function determineGemfileOrCocoapodPath(rootDir, platformDir, nativeProjec
}
}
try {
const gemfileText = (await (0, utils_fs_1.readFile)(gemfilePath)).toString();
const gemfileText = (await (0, fs_extra_1.readFile)(gemfilePath)).toString();
if (!gemfileText) {
return 'pod';
}
@ -386,13 +391,3 @@ const config: CapacitorConfig = ${(0, js_1.formatJSObject)(extConfig)};
export default config;\n`;
}
function checkExternalConfig(config) {
if (typeof config.extConfig.bundledWebRuntime !== 'undefined') {
let actionMessage = `Can be safely deleted.`;
if (config.extConfig.bundledWebRuntime === true) {
actionMessage = `Please, use a bundler to bundle Capacitor and its plugins.`;
}
log_1.logger.warn(`The ${colors_1.default.strong('bundledWebRuntime')} configuration option has been deprecated. ${actionMessage}`);
}
}
exports.checkExternalConfig = checkExternalConfig;

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeCordovaAndroidManifest = exports.getCordovaPreferences = exports.needsStaticPod = 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 fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const plist_1 = tslib_1.__importDefault(require("plist"));
const prompts_1 = tslib_1.__importDefault(require("prompts"));
@ -21,7 +21,7 @@ const xml_1 = require("./util/xml");
function generateCordovaPluginsJSFile(config, plugins, platform) {
const pluginModules = [];
const pluginExports = [];
plugins.map(p => {
plugins.map((p) => {
const pluginId = p.xml.$.id;
const jsModules = (0, plugin_1.getJSModules)(p, platform);
jsModules.map((jsModule) => {
@ -60,9 +60,7 @@ function generateCordovaPluginsJSFile(config, plugins, platform) {
merge: mergeKey,
// mimics Cordova's module name logic if the name attr is missing
pluginContent: `{
"id": "${pluginId +
'.' +
(jsModule.$.name || jsModule.$.src.match(/([^/]+)\.js/)[1])}",
"id": "${pluginId + '.' + (jsModule.$.name || jsModule.$.src.match(/([^/]+)\.js/)[1])}",
"file": "plugins/${pluginId}/${jsModule.$.src}",
"pluginId": "${pluginId}"${clobbersModule}${mergesModule}${runsModule}
}`,
@ -80,7 +78,7 @@ function generateCordovaPluginsJSFile(config, plugins, platform) {
: a.clobber || b.clobber // Clobbers before anything else
? b.clobber.localeCompare(a.clobber)
: a.merge.localeCompare(b.merge))
.map(e => e.pluginContent)
.map((e) => e.pluginContent)
.join(',\n ')}
];
module.exports.metadata =
@ -104,51 +102,49 @@ async function copyPluginsJS(config, cordovaPlugins, platform) {
await Promise.all(cordovaPlugins.map(async (p) => {
const pluginId = p.xml.$.id;
const pluginDir = (0, path_1.join)(pluginsDir, pluginId, 'www');
await (0, utils_fs_1.ensureDir)(pluginDir);
await (0, fs_extra_1.ensureDir)(pluginDir);
const jsModules = (0, plugin_1.getJSModules)(p, platform);
await Promise.all(jsModules.map(async (jsModule) => {
const filePath = (0, path_1.join)(webDir, 'plugins', pluginId, jsModule.$.src);
await (0, utils_fs_1.copy)((0, path_1.join)(p.rootPath, jsModule.$.src), filePath);
let data = await (0, utils_fs_1.readFile)(filePath, { encoding: 'utf-8' });
await (0, fs_extra_1.copy)((0, path_1.join)(p.rootPath, jsModule.$.src), filePath);
let data = await (0, fs_extra_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 ||
(0, path_1.basename)(jsModule.$.src, (0, path_1.extname)(jsModule.$.src)));
const name = pluginId + '.' + (jsModule.$.name || (0, path_1.basename)(jsModule.$.src, (0, 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 (0, utils_fs_1.writeFile)(filePath, data, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(filePath, data, { encoding: 'utf-8' });
}));
const assets = (0, plugin_1.getAssets)(p, platform);
await Promise.all(assets.map(async (asset) => {
const filePath = (0, path_1.join)(webDir, asset.$.target);
await (0, utils_fs_1.copy)((0, path_1.join)(p.rootPath, asset.$.src), filePath);
await (0, fs_extra_1.copy)((0, path_1.join)(p.rootPath, asset.$.src), filePath);
}));
}));
await (0, utils_fs_1.writeFile)(cordovaPluginsJSFile, generateCordovaPluginsJSFile(config, cordovaPlugins, platform));
await (0, fs_extra_1.writeFile)(cordovaPluginsJSFile, generateCordovaPluginsJSFile(config, cordovaPlugins, platform));
}
exports.copyPluginsJS = copyPluginsJS;
async function copyCordovaJS(config, platform) {
const cordovaPath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/core', 'cordova.js');
if (!cordovaPath) {
(0, 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?`);
(0, 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 (0, utils_fs_1.copy)(cordovaPath, (0, path_1.join)(await getWebDir(config, platform), 'cordova.js'));
return (0, fs_extra_1.copy)(cordovaPath, (0, path_1.join)(await getWebDir(config, platform), 'cordova.js'));
}
exports.copyCordovaJS = copyCordovaJS;
async function createEmptyCordovaJS(config, platform) {
const webDir = await getWebDir(config, platform);
await (0, utils_fs_1.writeFile)((0, path_1.join)(webDir, 'cordova.js'), '');
await (0, utils_fs_1.writeFile)((0, path_1.join)(webDir, 'cordova_plugins.js'), '');
await (0, fs_extra_1.writeFile)((0, path_1.join)(webDir, 'cordova.js'), '');
await (0, fs_extra_1.writeFile)((0, path_1.join)(webDir, 'cordova_plugins.js'), '');
}
exports.createEmptyCordovaJS = createEmptyCordovaJS;
async function removePluginFiles(config, platform) {
const webDir = await getWebDir(config, platform);
const pluginsDir = (0, path_1.join)(webDir, 'plugins');
const cordovaPluginsJSFile = (0, path_1.join)(webDir, 'cordova_plugins.js');
await (0, utils_fs_1.remove)(pluginsDir);
await (0, utils_fs_1.remove)(cordovaPluginsJSFile);
await (0, fs_extra_1.remove)(pluginsDir);
await (0, fs_extra_1.remove)(cordovaPluginsJSFile);
}
exports.removePluginFiles = removePluginFiles;
async function autoGenerateConfig(config, cordovaPlugins, platform) {
@ -158,11 +154,11 @@ async function autoGenerateConfig(config, cordovaPlugins, platform) {
if (platform === 'ios') {
xmlDir = config.ios.nativeTargetDirAbs;
}
await (0, utils_fs_1.ensureDir)(xmlDir);
await (0, fs_extra_1.ensureDir)(xmlDir);
const cordovaConfigXMLFile = (0, path_1.join)(xmlDir, fileName);
await (0, utils_fs_1.remove)(cordovaConfigXMLFile);
await (0, fs_extra_1.remove)(cordovaConfigXMLFile);
const pluginEntries = [];
cordovaPlugins.map(p => {
cordovaPlugins.map((p) => {
const currentPlatform = (0, plugin_1.getPluginPlatform)(p, platform);
if (currentPlatform) {
const configFiles = currentPlatform['config-file'];
@ -207,7 +203,7 @@ async function autoGenerateConfig(config, cordovaPlugins, platform) {
${pluginEntriesString.join('')}
${pluginPreferencesString.join('')}
</widget>`;
await (0, utils_fs_1.writeFile)(cordovaConfigXMLFile, content);
await (0, fs_extra_1.writeFile)(cordovaConfigXMLFile, content);
}
exports.autoGenerateConfig = autoGenerateConfig;
async function getWebDir(config, platform) {
@ -221,7 +217,7 @@ async function getWebDir(config, platform) {
}
async function handleCordovaPluginsJS(cordovaPlugins, config, platform) {
const webDir = await getWebDir(config, platform);
await (0, utils_fs_1.mkdirp)(webDir);
await (0, fs_extra_1.mkdirp)(webDir);
if (cordovaPlugins.length > 0) {
(0, plugin_1.printPlugins)(cordovaPlugins, platform, 'cordova');
await copyCordovaJS(config, platform);
@ -243,11 +239,11 @@ async function getCordovaPlugins(config, platform) {
else if (platform === config.android.name) {
plugins = await (0, common_1.getAndroidPlugins)(allPlugins);
}
return plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
return plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
}
exports.getCordovaPlugins = getCordovaPlugins;
async function logCordovaManualSteps(cordovaPlugins, config, platform) {
cordovaPlugins.map(p => {
cordovaPlugins.map((p) => {
const editConfig = (0, plugin_1.getPlatformElement)(p, platform, 'edit-config');
const configFile = (0, plugin_1.getPlatformElement)(p, platform, 'config-file');
editConfig.concat(configFile).map(async (configElement) => {
@ -268,26 +264,22 @@ async function logiOSPlist(configElement, config, plugin) {
if ((_a = config.app.extConfig.ios) === null || _a === void 0 ? void 0 : _a.scheme) {
plistPath = (0, path_1.resolve)(config.ios.nativeProjectDirAbs, `${(_b = config.app.extConfig.ios) === null || _b === void 0 ? void 0 : _b.scheme}-Info.plist`);
}
if (!(await (0, utils_fs_1.pathExists)(plistPath))) {
if (!(await (0, fs_extra_1.pathExists)(plistPath))) {
plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Base.lproj', 'Info.plist');
}
if (await (0, utils_fs_1.pathExists)(plistPath)) {
if (await (0, fs_extra_1.pathExists)(plistPath)) {
const xmlMeta = await (0, xml_1.readXML)(plistPath);
const data = await (0, utils_fs_1.readFile)(plistPath, { encoding: 'utf-8' });
const data = await (0, fs_extra_1.readFile)(plistPath, { encoding: 'utf-8' });
const trimmedPlistData = data.replace(/(\t|\r|\n)/g, '');
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);
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) {
if (configElement.array && configElement.array.length > 0 && configElement.array[0].string) {
let xml = '';
configElement.array[0].string.map((element) => {
const d = plistData[configElement.$.parent];
@ -356,8 +348,7 @@ async function logiOSPlist(configElement, config, plugin) {
parsedRequiredElements.push(rootOfRequiredElementsToAdd);
const doesContainElements = (requiredElementsArray, existingElementsArray) => {
for (const requiredElement of requiredElementsArray) {
if (requiredElement.name === 'key' ||
requiredElement.name === 'string') {
if (requiredElement.name === 'key' || requiredElement.name === 'string') {
let foundMatch = false;
for (const existingElement of existingElementsArray) {
if (existingElement.name === requiredElement.name &&
@ -375,8 +366,7 @@ async function logiOSPlist(configElement, config, plugin) {
let foundMatch = false;
for (const existingElement of existingElementsArray) {
if (existingElement.name === requiredElement.name) {
if ((requiredElement.children !== undefined) ===
(existingElement.children !== undefined)) {
if ((requiredElement.children !== undefined) === (existingElement.children !== undefined)) {
if (doesContainElements(requiredElement.children, existingElement.children)) {
foundMatch = true;
break;
@ -420,10 +410,10 @@ function removeOuterTags(str) {
const end = str.lastIndexOf('<');
return str.substring(start, end);
}
async function checkPluginDependencies(plugins, platform) {
async function checkPluginDependencies(plugins, platform, failOnMissingDeps = false) {
const pluginDeps = new Map();
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
const incompatible = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
const incompatible = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
await Promise.all(cordovaPlugins.map(async (p) => {
let allDependencies = [];
allDependencies = allDependencies.concat((0, plugin_1.getPlatformElement)(p, platform, 'dependency'));
@ -431,8 +421,7 @@ async function checkPluginDependencies(plugins, platform) {
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);
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;
@ -441,7 +430,7 @@ async function checkPluginDependencies(plugins, platform) {
if (plugin.includes('@') && plugin.indexOf('@') !== 0) {
[plugin, version] = plugin.split('@');
}
if (cordovaPlugins.filter(p => p.id === plugin || p.xml.$.id === plugin).length === 0) {
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;
@ -457,9 +446,10 @@ async function checkPluginDependencies(plugins, platform) {
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');
msg += `\n ${colors_1.default.strong(plugin)} is missing dependencies:\n` + deps.map((d) => ` - ${d}`).join('\n');
}
if (failOnMissingDeps) {
(0, errors_1.fatal)(`${msg}\n`);
}
log_1.logger.warn(`${msg}\n`);
}
@ -490,18 +480,8 @@ function getIncompatibleCordovaPlugins(platform) {
return pluginList;
}
exports.getIncompatibleCordovaPlugins = getIncompatibleCordovaPlugins;
function needsStaticPod(plugin, config) {
var _a, _b, _c, _d;
let pluginList = [
'phonegap-plugin-push',
'@batch.com/cordova-plugin',
'onesignal-cordova-plugin',
];
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.staticPlugins) {
log_1.logger.warn('cordova.staticPlugins is deprecated, make sure you are using latest version of the plugin');
pluginList = pluginList.concat((_d = (_c = config.app.extConfig) === null || _c === void 0 ? void 0 : _c.cordova) === null || _d === void 0 ? void 0 : _d.staticPlugins);
}
return pluginList.includes(plugin.id) || useFrameworks(plugin);
function needsStaticPod(plugin) {
return useFrameworks(plugin);
}
exports.needsStaticPod = needsStaticPod;
function useFrameworks(plugin) {
@ -513,7 +493,7 @@ async function getCordovaPreferences(config) {
var _a, _b, _c, _d, _e;
const configXml = (0, path_1.join)(config.app.rootDir, 'config.xml');
let cordova = {};
if (await (0, utils_fs_1.pathExists)(configXml)) {
if (await (0, fs_extra_1.pathExists)(configXml)) {
cordova.preferences = {};
const xmlMeta = await (0, xml_1.readXML)(configXml);
if (xmlMeta.widget.preference) {
@ -573,16 +553,14 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
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 => {
const keys = Object.keys(configElement).filter((k) => k !== '$');
keys.map((k) => {
configElement[k].map(async (e) => {
const xmlElement = (0, 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')) {
if (configElement.$.mode && configElement.$.mode === 'merge' && xmlElement.startsWith('<application')) {
Object.keys(e.$).map((ek) => {
applicationXMLAttributes.push(`${ek}="${e.$[ek]}"`);
});
@ -594,7 +572,7 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
}
else {
const manifestPathOfCapApp = (0, path_1.join)(config.android.appDirAbs, 'src', 'main', 'AndroidManifest.xml');
const manifestContentTrimmed = (await (0, utils_fs_1.readFile)(manifestPathOfCapApp))
const manifestContentTrimmed = (await (0, fs_extra_1.readFile)(manifestPathOfCapApp))
.toString()
.trim()
.replace(/\n|\t|\r/g, '')
@ -657,8 +635,7 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
if (requiredElement.name !== existingElement.name) {
return false;
}
if ((requiredElement.attrs !== undefined) !==
(existingElement.attrs !== undefined)) {
if ((requiredElement.attrs !== undefined) !== (existingElement.attrs !== undefined)) {
return false;
}
else {
@ -666,16 +643,14 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
const requiredELementAttrKeys = Object.keys(requiredElement.attrs);
for (const key of requiredELementAttrKeys) {
if (!/^[$].{1,}$/.test(requiredElement.attrs[key].trim())) {
if (requiredElement.attrs[key] !==
existingElement.attrs[key]) {
if (requiredElement.attrs[key] !== existingElement.attrs[key]) {
return false;
}
}
}
}
}
if ((requiredElement.children !== undefined) !==
(existingElement.children !== undefined) &&
if ((requiredElement.children !== undefined) !== (existingElement.children !== undefined) &&
((_a = requiredElement.children) === null || _a === void 0 ? void 0 : _a.length) !== 0) {
return false;
}
@ -697,8 +672,7 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
}
}
else {
if (requiredElement.children === undefined &&
existingElement.children === undefined) {
if (requiredElement.children === undefined && existingElement.children === undefined) {
return true;
}
else {
@ -736,8 +710,7 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
...requiredElements[rootKeyOfRequiredElements]['$'],
};
}
if (requiredElements[rootKeyOfRequiredElements]['$$'] !==
undefined) {
if (requiredElements[rootKeyOfRequiredElements]['$$'] !== undefined) {
parseXmlToSearchable(requiredElements[rootKeyOfRequiredElements]['$$'], rootOfRequiredElementsToAdd['children']);
}
parsedRequiredElements.push(rootOfRequiredElementsToAdd);
@ -771,8 +744,7 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
}
}
else {
if (!rootXMLEntries.includes(xmlElement) &&
!contains(rootXMLEntries, xmlElement, k)) {
if (!rootXMLEntries.includes(xmlElement) && !contains(rootXMLEntries, xmlElement, k)) {
rootXMLEntries.push(xmlElement);
}
}
@ -782,8 +754,7 @@ async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cle
});
});
const cleartextString = 'android:usesCleartextTraffic="true"';
const cleartextValue = (cleartext || ((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.cleartext)) &&
!applicationXMLAttributes.includes(cleartextString)
const cleartextValue = (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'?>
@ -798,15 +769,15 @@ ${rootXMLEntries.join('\n')}
for (const preference of prefsArray) {
content = content.replace(new RegExp(('$' + preference.$.name).replace('$', '\\$&'), 'g'), preference.$.default);
}
if (await (0, utils_fs_1.pathExists)(manifestPath)) {
await (0, utils_fs_1.writeFile)(manifestPath, content);
if (await (0, fs_extra_1.pathExists)(manifestPath)) {
await (0, fs_extra_1.writeFile)(manifestPath, content);
}
}
exports.writeCordovaAndroidManifest = writeCordovaAndroidManifest;
function getPathParts(path) {
const rootPath = 'manifest';
path = path.replace('/*', rootPath);
const parts = path.split('/').filter(part => part !== '');
const parts = path.split('/').filter((part) => part !== '');
if (parts.length > 1 || parts.includes(rootPath)) {
return parts;
}

View file

@ -26,20 +26,6 @@ export interface CapacitorConfig {
* @since 1.0.0
*/
webDir?: string;
/**
* Whether to copy the Capacitor runtime bundle or not.
*
* If your app is not using a bundler, set this to `true`, then Capacitor
* will create a `capacitor.js` file that you'll need to add as a script in
* your `index.html` file.
*
* It's deprecated and will be removed in Capacitor 6
*
* @since 1.0.0
* @deprecated 5.0.0
* @default false
*/
bundledWebRuntime?: boolean;
/**
* The build configuration (as defined by the native app) under which Capacitor
* will send statements to the log system. This applies to log statements in
@ -83,6 +69,13 @@ export interface CapacitorConfig {
* @since 6.0.0
*/
zoomEnabled?: boolean;
/**
* Whether to give the webview initial focus.
*
* @since 7.0.0
* @default true
*/
initialFocus?: boolean;
android?: {
/**
* Specify a custom path to the native Android project.
@ -186,6 +179,8 @@ export interface CapacitorConfig {
/**
* Whether to give the webview initial focus.
*
* Overrides global `initialFocus` option.
*
* @since 3.5.1
* @default true
*/
@ -264,6 +259,24 @@ export interface CapacitorConfig {
* @default false
*/
useLegacyBridge?: boolean;
/**
* Make service worker requests go through Capacitor bridge.
* Set it to false to use your own handling.
*
* @since 7.0.0
* @default true
*/
resolveServiceWorkerRequests?: boolean;
/**
* If set to "force", margins will be adjusted for edge to edge regardless of any other settings.
* If set to "auto", or is missing, will check for Android 15 and the setting of [windowOptOutEdgeToEdgeEnforcement](https://developer.android.com/reference/android/R.attr#windowOptOutEdgeToEdgeEnforcement) and will adjust margins if on Android 15 and windowOptOutEdgeToEdgeEnforcement is false/missing.
* If set to "disable", will not adjust margins at all.
* In Capacitor 8, this default will be changed to 'auto'
*
* @since 7.1.0
* @default disable
*/
adjustMarginsForEdgeToEdge?: 'auto' | 'force' | 'disable';
};
ios?: {
/**
@ -419,6 +432,43 @@ export interface CapacitorConfig {
* @default false
*/
webContentsDebuggingEnabled?: boolean;
/**
* Whether to give the webview initial focus.
*
* Overrides global `initialFocus` option.
*
* @since 7.0.0
* @default true
*/
initialFocus?: boolean;
buildOptions?: {
/**
* The signing style to use when building the app for distribution.
*
* @since 7.1.0
* @default 'automatic'
*/
signingStyle?: 'automatic' | 'manual';
/**
* The method used by xcodebuild to export the archive
*
* @since 7.1.0
* @default 'app-store-connect'
*/
exportMethod?: string;
/**
* A certificate name, SHA-1 hash, or automatic selector to use for signing for iOS builds.
*
* @since 7.1.0
*/
signingCertificate?: string;
/**
* A provisioning profile name or UUID for iOS builds.
*
* @since 7.1.0
*/
provisioningProfile?: string;
};
};
server?: {
/**
@ -504,6 +554,14 @@ export interface CapacitorConfig {
* @default null
*/
errorPath?: string;
/**
* Append a path to the app URL.
*
* Allows loading from other paths than the default `/index.html`.
* @since 7.3.0
* @default null
*/
appStartPath?: string;
};
cordova?: {
/**
@ -524,15 +582,13 @@ export interface CapacitorConfig {
[key: string]: string | undefined;
};
/**
* List of Cordova plugins that need to be static but are not
* already in the static plugin list.
* Fail on cap update/sync if the CLI detects that a cordova plugin
* has uninstalled dependencies.
*
* It's deprecated and will be removed in Capacitor 7
*
* @since 3.3.0
* @deprecated 6.1.1
* @default false
* @since 7.4.0
*/
staticPlugins?: string[];
failOnUninstalledPlugins?: boolean;
};
/**
* Configure plugins.

View file

@ -1,2 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XcodeExportMethod = void 0;
var XcodeExportMethod;
(function (XcodeExportMethod) {
XcodeExportMethod["AppStoreConnect"] = "app-store-connect";
XcodeExportMethod["ReleaseTesting"] = "release-testing";
XcodeExportMethod["Enterprise"] = "enterprise";
XcodeExportMethod["Debugging"] = "debugging";
XcodeExportMethod["DeveloperID"] = "developer-id";
XcodeExportMethod["MacApplication"] = "mac-application";
XcodeExportMethod["Validation"] = "validation";
})(XcodeExportMethod = exports.XcodeExportMethod || (exports.XcodeExportMethod = {}));

View file

@ -4,85 +4,85 @@ exports.detectFramework = void 0;
const FRAMEWORK_CONFIGS = [
{
name: 'Angular',
isMatch: config => hasDependency(config, '@angular/cli'),
isMatch: (config) => hasDependency(config, '@angular/cli'),
webDir: 'dist',
priority: 3,
},
{
name: 'Create React App',
isMatch: config => hasDependency(config, 'react-scripts'),
isMatch: (config) => hasDependency(config, 'react-scripts'),
webDir: 'build',
priority: 3,
},
{
name: 'Ember',
isMatch: config => hasDependency(config, 'ember-cli'),
isMatch: (config) => hasDependency(config, 'ember-cli'),
webDir: 'dist',
priority: 3,
},
{
name: 'Gatsby',
isMatch: config => hasDependency(config, 'gatsby'),
isMatch: (config) => hasDependency(config, 'gatsby'),
webDir: 'public',
priority: 2,
},
{
name: 'Ionic Angular',
isMatch: config => hasDependency(config, '@ionic/angular'),
isMatch: (config) => hasDependency(config, '@ionic/angular'),
webDir: 'www',
priority: 1,
},
{
name: 'Ionic React',
isMatch: config => hasDependency(config, '@ionic/react'),
isMatch: (config) => hasDependency(config, '@ionic/react'),
webDir: 'build',
priority: 1,
},
{
name: 'Ionic Vue',
isMatch: config => hasDependency(config, '@ionic/vue'),
isMatch: (config) => hasDependency(config, '@ionic/vue'),
webDir: 'public',
priority: 1,
},
{
name: 'Next',
isMatch: config => hasDependency(config, 'next'),
isMatch: (config) => hasDependency(config, 'next'),
webDir: 'public',
priority: 2,
},
{
name: 'Preact',
isMatch: config => hasDependency(config, 'preact-cli'),
isMatch: (config) => hasDependency(config, 'preact-cli'),
webDir: 'build',
priority: 3,
},
{
name: 'Stencil',
isMatch: config => hasDependency(config, '@stencil/core'),
isMatch: (config) => hasDependency(config, '@stencil/core'),
webDir: 'www',
priority: 3,
},
{
name: 'Svelte',
isMatch: config => hasDependency(config, 'svelte') && hasDependency(config, 'sirv-cli'),
isMatch: (config) => hasDependency(config, 'svelte') && hasDependency(config, 'sirv-cli'),
webDir: 'public',
priority: 3,
},
{
name: 'Vite',
isMatch: config => hasDependency(config, 'vite'),
isMatch: (config) => hasDependency(config, 'vite'),
webDir: 'dist',
priority: 2,
},
{
name: 'Vue',
isMatch: config => hasDependency(config, '@vue/cli-service'),
isMatch: (config) => hasDependency(config, '@vue/cli-service'),
webDir: 'dist',
priority: 3,
},
];
function detectFramework(config) {
const frameworks = FRAMEWORK_CONFIGS.filter(f => f.isMatch(config)).sort((a, b) => {
const frameworks = FRAMEWORK_CONFIGS.filter((f) => f.isMatch(config)).sort((a, b) => {
if (a.priority < b.priority)
return -1;
if (a.priority > b.priority)

View file

@ -12,7 +12,7 @@ const log_1 = require("./log");
const telemetry_1 = require("./telemetry");
const cli_1 = require("./util/cli");
const emoji_1 = require("./util/emoji");
process.on('unhandledRejection', error => {
process.on('unhandledRejection', (error) => {
console.error(colors_1.default.failure('[fatal]'), error);
});
process.on('message', ipc_1.receive);
@ -48,9 +48,10 @@ function runProgram(config) {
.command('init [appName] [appId]')
.description(`Initialize Capacitor configuration`)
.option('--web-dir <value>', 'Optional: Directory of your projects built web assets')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (appName, appId, { webDir }) => {
.option('--skip-appid-validation', 'Optional: Skip validating the app ID for iOS and Android compatibility')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (appName, appId, { webDir, skipAppidValidation }) => {
const { initCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/init')));
await initCommand(config, appName, appId, webDir);
await initCommand(config, appName, appId, webDir, skipAppidValidation);
})));
commander_1.program
.command('serve', { hidden: true })
@ -65,7 +66,6 @@ function runProgram(config) {
.option('--deployment', 'Optional: if provided, pod install will use --deployment option')
.option('--inline', 'Optional: if true, all source maps will be inlined for easier debugging on mobile devices', false)
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { deployment, inline }) => {
(0, config_1.checkExternalConfig)(config.app);
const { syncCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/sync')));
await syncCommand(config, platform, deployment, inline);
})));
@ -74,7 +74,6 @@ function runProgram(config) {
.description(`updates the native plugins and dependencies based on ${colors_1.default.strong('package.json')}`)
.option('--deployment', 'Optional: if provided, pod install will use --deployment option')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { deployment }) => {
(0, config_1.checkExternalConfig)(config.app);
const { updateCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/update')));
await updateCommand(config, platform, deployment);
})));
@ -83,7 +82,6 @@ function runProgram(config) {
.description('copies the web app build into the native app')
.option('--inline', 'Optional: if true, all source maps will be inlined for easier debugging on mobile devices', false)
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { inline }) => {
(0, config_1.checkExternalConfig)(config.app);
const { copyCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/copy')));
await copyCommand(config, platform, inline);
})));
@ -97,9 +95,28 @@ function runProgram(config) {
.option('--keystorealias <keystoreAlias>', 'Key Alias in the keystore')
.option('--configuration <name>', 'Configuration name of the iOS Scheme')
.option('--keystorealiaspass <keystoreAliasPass>', 'Password for the Key Alias')
.addOption(new commander_1.Option('--androidreleasetype <androidreleasetype>', 'Android release type; APK or AAB').choices(['AAB', 'APK']))
.addOption(new commander_1.Option('--signing-type <signingtype>', 'Program used to sign apps (default: jarsigner)').choices(['apksigner', 'jarsigner']))
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, keystorepath, keystorepass, keystorealias, keystorealiaspass, androidreleasetype, signingType, configuration, }) => {
.addOption(new commander_1.Option('--androidreleasetype <androidreleasetype>', 'Android release type; APK or AAB').choices([
'AAB',
'APK',
]))
.addOption(new commander_1.Option('--signing-type <signingtype>', 'Program used to sign apps (default: jarsigner)').choices([
'apksigner',
'jarsigner',
]))
.addOption(new commander_1.Option('--xcode-team-id <xcodeTeamID>', 'The Developer team to use for building and exporting the archive'))
.addOption(new commander_1.Option('--xcode-export-method <xcodeExportMethod>', 'Describes how xcodebuild should export the archive (default: app-store-connect)').choices([
'app-store-connect',
'release-testing',
'enterprise',
'debugging',
'developer-id',
'mac-application',
'validation',
]))
.addOption(new commander_1.Option('--xcode-signing-style <xcodeSigningStyle>', 'The iOS signing style to use when building the app for distribution (default: automatic)').choices(['automatic', 'manual']))
.addOption(new commander_1.Option('--xcode-signing-certificate <xcodeSigningCertificate>', 'A certificate name, SHA-1 hash, or automatic selector to use for signing for iOS builds'))
.addOption(new commander_1.Option('--xcode-provisioning-profile <xcodeProvisioningProfile>', 'A provisioning profile name or UUID for iOS builds'))
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, keystorepath, keystorepass, keystorealias, keystorealiaspass, androidreleasetype, signingType, configuration, xcodeTeamId, xcodeExportMethod, xcodeSigningStyle, xcodeSigningCertificate, xcodeProvisioningProfile, }) => {
const { buildCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/build')));
await buildCommand(config, platform, {
scheme,
@ -111,6 +128,11 @@ function runProgram(config) {
androidreleasetype,
signingtype: signingType,
configuration,
xcodeTeamId,
xcodeExportMethod,
xcodeSigningType: xcodeSigningStyle,
xcodeSigningCertificate,
xcodeProvisioningProfile,
});
})));
commander_1.program
@ -119,8 +141,7 @@ function runProgram(config) {
.option('--scheme <schemeName>', 'set the scheme of the iOS project')
.option('--flavor <flavorName>', 'set the flavor of the Android project (flavor dimensions not yet supported)')
.option('--list', 'list targets, then quit')
// TODO: remove once --json is a hidden option (https://github.com/tj/commander.js/issues/1106)
.allowUnknownOption(true)
.addOption(new commander_1.Option('--json').hideHelp())
.option('--target <id>', 'use a specific target')
.option('--no-sync', `do not run ${colors_1.default.input('sync')}`)
.option('--forwardPorts <port:port>', 'Automatically run "adb reverse" for better live-reloading support')
@ -128,12 +149,13 @@ function runProgram(config) {
.option('--host <host>', 'Host used for live reload')
.option('--port <port>', 'Port used for live reload')
.option('--configuration <name>', 'Configuration name of the iOS Scheme')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, list, target, sync, forwardPorts, liveReload, host, port, configuration, }) => {
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, list, json, target, sync, forwardPorts, liveReload, host, port, configuration }) => {
const { runCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/run')));
await runCommand(config, platform, {
scheme,
flavor,
list,
json,
target,
sync,
forwardPorts,
@ -153,14 +175,12 @@ function runProgram(config) {
commander_1.program
.command('add [platform]')
.description('add a native platform project')
.option('--packagemanager <packageManager>', 'The package manager to use for dependency installs (Cocoapods, SPM **experimental**)')
.option('--packagemanager <packageManager>', 'The package manager to use for dependency installs (CocoaPods or SPM)')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { packagemanager }) => {
(0, config_1.checkExternalConfig)(config.app);
const { addCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/add')));
const configWritable = config;
if (packagemanager === 'SPM') {
configWritable.cli.assets.ios.platformTemplateArchive =
'ios-spm-template.tar.gz';
configWritable.cli.assets.ios.platformTemplateArchive = 'ios-spm-template.tar.gz';
configWritable.cli.assets.ios.platformTemplateArchiveAbs = (0, path_1.resolve)(configWritable.cli.assetsDirAbs, configWritable.cli.assets.ios.platformTemplateArchive);
}
await addCommand(configWritable, platform);
@ -169,7 +189,6 @@ function runProgram(config) {
.command('ls [platform]')
.description('list installed Cordova and Capacitor plugins')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
(0, config_1.checkExternalConfig)(config.app);
const { listCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/list')));
await listCommand(config, platform);
})));
@ -177,7 +196,6 @@ function runProgram(config) {
.command('doctor [platform]')
.description('checks the current setup for common errors')
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
(0, config_1.checkExternalConfig)(config.app);
const { doctorCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/doctor')));
await doctorCommand(config, platform);
})));
@ -210,6 +228,13 @@ function runProgram(config) {
const { migrateCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/migrate')));
await migrateCommand(config, noprompt, packagemanager);
}));
commander_1.program
.command('spm-migration-assistant')
.description('Remove Cocoapods from project and switch to Swift Package Manager')
.action((0, cli_1.wrapAction)(async () => {
const { migrateToSPM } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/migrate-spm')));
await migrateToSPM(config);
}));
commander_1.program.arguments('[command]').action((0, cli_1.wrapAction)(async (cmd) => {
if (typeof cmd === 'undefined') {
log_1.output.write(`\n ${(0, emoji_1.emoji)('⚡️', '--')} ${colors_1.default.strong('Capacitor - Cross-Platform apps with JavaScript and the Web')} ${(0, emoji_1.emoji)('⚡️', '--')}\n\n`);

View file

@ -1,16 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildiOS = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const rimraf_1 = require("rimraf");
const common_1 = require("../common");
const definitions_1 = require("../definitions");
const log_1 = require("../log");
const spm_1 = require("../util/spm");
const subprocess_1 = require("../util/subprocess");
async function buildiOS(config, buildOptions) {
var _a;
var _a, _b, _c, _d;
const theScheme = (_a = buildOptions.scheme) !== null && _a !== void 0 ? _a : 'App';
const packageManager = await (0, spm_1.checkPackageManager)(config);
let typeOfBuild;
@ -23,7 +23,11 @@ async function buildiOS(config, buildOptions) {
typeOfBuild = '-project';
projectName = (0, path_1.basename)(await config.ios.nativeXcodeProjDirAbs);
}
await (0, common_1.runTask)('Building xArchive', async () => (0, subprocess_1.runCommand)('xcodebuild', [
if (buildOptions.xcodeSigningType == 'manual' &&
(!buildOptions.xcodeSigningCertificate || !buildOptions.xcodeProvisioningProfile)) {
throw 'Manually signed Xcode builds require a signing certificate and provisioning profile.';
}
const buildArgs = [
typeOfBuild,
projectName,
'-scheme',
@ -33,20 +37,39 @@ async function buildiOS(config, buildOptions) {
'-archivePath',
`${theScheme}.xcarchive`,
'archive',
], {
'-configuration',
buildOptions.configuration,
];
if (buildOptions.xcodeTeamId) {
buildArgs.push(`DEVELOPMENT_TEAM=${buildOptions.xcodeTeamId}`);
}
if (buildOptions.xcodeSigningType == 'manual') {
buildArgs.push(`PROVISIONING_PROFILE_SPECIFIER=${buildOptions.xcodeProvisioningProfile}`);
}
await (0, common_1.runTask)('Building xArchive', async () => (0, subprocess_1.runCommand)('xcodebuild', buildArgs, {
cwd: config.ios.nativeProjectDirAbs,
}));
const manualSigningContents = `<key>provisioningProfiles</key>
<dict>
<key>${config.app.appId}</key>
<string>${(_b = buildOptions.xcodeProvisioningProfile) !== null && _b !== void 0 ? _b : ''}</string>
</dict>
<key>signingCertificate</key>
<string>${(_c = buildOptions.xcodeSigningCertificate) !== null && _c !== void 0 ? _c : ''}</string>`;
const archivePlistContents = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
<string>${(_d = buildOptions.xcodeExportMethod) !== null && _d !== void 0 ? _d : definitions_1.XcodeExportMethod.AppStoreConnect}</string>
<key>signingStyle</key>
<string>${buildOptions.xcodeSigningType}</string>
${buildOptions.xcodeSigningType == 'manual' ? manualSigningContents : ''}
</dict>
</plist>`;
const archivePlistPath = (0, path_1.join)(`${config.ios.nativeProjectDirAbs}`, 'archive.plist');
(0, utils_fs_1.writeFileSync)(archivePlistPath, archivePlistContents);
await (0, common_1.runTask)('Building IPA', async () => (0, subprocess_1.runCommand)('xcodebuild', [
(0, fs_extra_1.writeFileSync)(archivePlistPath, archivePlistContents);
const archiveArgs = [
'archive',
'-archivePath',
`${theScheme}.xcarchive`,
@ -55,15 +78,18 @@ async function buildiOS(config, buildOptions) {
'archive.plist',
'-exportPath',
'output',
'-allowProvisioningUpdates',
'-configuration',
buildOptions.configuration,
], {
];
if (buildOptions.xcodeSigningType == 'automatic') {
archiveArgs.push('-allowProvisioningUpdates');
}
await (0, common_1.runTask)('Building IPA', async () => (0, subprocess_1.runCommand)('xcodebuild', archiveArgs, {
cwd: config.ios.nativeProjectDirAbs,
}));
await (0, common_1.runTask)('Cleaning up', async () => {
(0, utils_fs_1.unlinkSync)(archivePlistPath);
rimraf_1.default.sync((0, path_1.join)(config.ios.nativeProjectDirAbs, `${theScheme}.xcarchive`));
(0, fs_extra_1.unlinkSync)(archivePlistPath);
rimraf_1.rimraf.sync((0, path_1.join)(config.ios.nativeProjectDirAbs, `${theScheme}.xcarchive`));
});
(0, log_1.logSuccess)(`Successfully generated an IPA at: ${(0, path_1.join)(config.ios.nativeProjectDirAbs, 'output')}`);
}

View file

@ -1,9 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.editProjectSettingsIOS = exports.resolvePlugin = exports.getIOSPlugins = exports.checkCocoaPods = exports.checkBundler = exports.checkIOSPackage = void 0;
exports.getMajoriOSVersion = exports.editProjectSettingsIOS = exports.resolvePlugin = exports.getIOSPlugins = exports.checkCocoaPods = exports.checkBundler = exports.checkIOSPackage = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const child_process_1 = require("child_process");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
@ -42,8 +42,7 @@ async function checkBundler(config) {
}
exports.checkBundler = checkBundler;
async function checkCocoaPods(config) {
if (!(await (0, subprocess_1.isInstalled)(await config.ios.podPath)) &&
config.cli.os === "mac" /* OS.Mac */) {
if (!(await (0, subprocess_1.isInstalled)(await config.ios.podPath)) && config.cli.os === "mac" /* OS.Mac */) {
return (`CocoaPods is not installed.\n` +
`See this install guide: ${colors_1.default.strong('https://capacitorjs.com/docs/getting-started/environment-setup#homebrew')}`);
}
@ -71,8 +70,7 @@ async function resolvePlugin(plugin) {
type: 1 /* PluginType.Cordova */,
path: 'src/' + platform,
};
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) ||
!(0, plugin_1.getPluginPlatform)(plugin, platform)) {
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) || !(0, plugin_1.getPluginPlatform)(plugin, platform)) {
plugin.ios.type = 2 /* PluginType.Incompatible */;
}
}
@ -87,17 +85,21 @@ exports.resolvePlugin = resolvePlugin;
*/
async function editProjectSettingsIOS(config) {
const appId = config.app.appId;
const appName = config.app.appName
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
const appName = config.app.appName.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
const pbxPath = `${config.ios.nativeXcodeProjDirAbs}/project.pbxproj`;
const plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
let plistContent = await (0, utils_fs_1.readFile)(plistPath, { encoding: 'utf-8' });
let plistContent = await (0, fs_extra_1.readFile)(plistPath, { encoding: 'utf-8' });
plistContent = plistContent.replace(/<key>CFBundleDisplayName<\/key>[\s\S]?\s+<string>([^<]*)<\/string>/, `<key>CFBundleDisplayName</key>\n <string>${appName}</string>`);
let pbxContent = await (0, utils_fs_1.readFile)(pbxPath, { encoding: 'utf-8' });
let pbxContent = await (0, fs_extra_1.readFile)(pbxPath, { encoding: 'utf-8' });
pbxContent = pbxContent.replace(/PRODUCT_BUNDLE_IDENTIFIER = ([^;]+)/g, `PRODUCT_BUNDLE_IDENTIFIER = ${appId}`);
await (0, utils_fs_1.writeFile)(plistPath, plistContent, { encoding: 'utf-8' });
await (0, utils_fs_1.writeFile)(pbxPath, pbxContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(plistPath, plistContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(pbxPath, pbxContent, { encoding: 'utf-8' });
}
exports.editProjectSettingsIOS = editProjectSettingsIOS;
function getMajoriOSVersion(config) {
const pbx = (0, fs_extra_1.readFileSync)((0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj'), 'utf-8');
const searchString = 'IPHONEOS_DEPLOYMENT_TARGET = ';
const iosVersion = pbx.substring(pbx.indexOf(searchString) + searchString.length, pbx.indexOf(searchString) + searchString.length + 2);
return iosVersion;
}
exports.getMajoriOSVersion = getMajoriOSVersion;

View file

@ -20,11 +20,7 @@ async function doctorIOS(config) {
// check online datebase of common errors
// check if www folder is empty (index.html does not exist)
try {
await (0, common_1.check)([
() => (0, common_2.checkBundler)(config) || (0, common_2.checkCocoaPods)(config),
() => (0, common_1.checkWebDir)(config),
checkXcode,
]);
await (0, common_1.check)([() => (0, common_2.checkBundler)(config) || (0, common_2.checkCocoaPods)(config), () => (0, common_1.checkWebDir)(config), checkXcode]);
(0, log_1.logSuccess)('iOS looking great! 👌');
}
catch (e) {

View file

@ -10,7 +10,7 @@ const native_run_1 = require("../util/native-run");
const spm_1 = require("../util/spm");
const subprocess_1 = require("../util/subprocess");
const debug = (0, debug_1.default)('capacitor:ios:run');
async function runIOS(config, { target: selectedTarget, scheme: selectedScheme, configuration: selectedConfiguration, }) {
async function runIOS(config, { target: selectedTarget, scheme: selectedScheme, configuration: selectedConfiguration }) {
const target = await (0, common_1.promptForPlatformTarget)(await (0, native_run_1.getPlatformTargets)('ios'), selectedTarget);
const runScheme = selectedScheme || config.ios.scheme;
const configuration = selectedConfiguration || 'Debug';
@ -43,9 +43,7 @@ async function runIOS(config, { target: selectedTarget, scheme: selectedScheme,
cwd: config.ios.nativeProjectDirAbs,
}));
const appName = `${runScheme}.app`;
const appPath = (0, path_1.resolve)(derivedDataPath, 'Build/Products', target.virtual
? `${configuration}-iphonesimulator`
: `${configuration}-iphoneos`, appName);
const appPath = (0, path_1.resolve)(derivedDataPath, 'Build/Products', target.virtual ? `${configuration}-iphonesimulator` : `${configuration}-iphoneos`, appName);
const nativeRunArgs = ['ios', '--app', appPath, '--target', target.id];
debug('Invoking native-run with args: %O', nativeRunArgs);
await (0, common_1.runTask)(`Deploying ${colors_1.default.strong(appName)} to ${colors_1.default.input(target.id)}`, async () => (0, native_run_1.runNativeRun)(nativeRunArgs));

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.installCocoaPodsPlugins = exports.updateIOS = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
@ -21,34 +21,79 @@ const common_2 = require("./common");
const platform = 'ios';
async function updateIOS(config, deployment) {
const plugins = await getPluginsTask(config);
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
if ((await (0, spm_1.checkPackageManager)(config)) === 'SPM') {
await (0, spm_1.generatePackageFile)(config, capacitorPlugins);
}
else {
await updateIOSCocoaPods(config, plugins, deployment);
}
const capacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
await updatePluginFiles(config, plugins, deployment);
await (0, common_1.checkPlatformVersions)(config, platform);
(0, iosplugin_1.generateIOSPackageJSON)(config, plugins);
(0, plugin_1.printPlugins)(capacitorPlugins, 'ios');
}
exports.updateIOS = updateIOS;
async function updateIOSCocoaPods(config, plugins, deployment) {
async function updatePluginFiles(config, plugins, deployment) {
var _a;
await removePluginsNativeFiles(config);
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
if (cordovaPlugins.length > 0) {
await copyPluginsNativeFiles(config, cordovaPlugins);
}
if (!(await (0, utils_fs_1.pathExists)(await config.ios.webDirAbs))) {
if (!(await (0, fs_extra_1.pathExists)(await config.ios.webDirAbs))) {
await (0, copy_1.copy)(config, platform);
}
await (0, cordova_1.handleCordovaPluginsJS)(cordovaPlugins, config, platform);
await (0, cordova_1.checkPluginDependencies)(plugins, platform);
await generateCordovaPodspecs(cordovaPlugins, config);
await installCocoaPodsPlugins(config, plugins, deployment);
await (0, cordova_1.checkPluginDependencies)(plugins, platform, (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.failOnUninstalledPlugins);
if ((await (0, spm_1.checkPackageManager)(config)) === 'SPM') {
await generateCordovaPackageFiles(cordovaPlugins, config);
const validSPMPackages = await (0, spm_1.checkPluginsForPackageSwift)(config, plugins);
await (0, spm_1.generatePackageFile)(config, validSPMPackages);
}
else {
await generateCordovaPodspecs(cordovaPlugins, config);
await installCocoaPodsPlugins(config, plugins, deployment);
}
await (0, cordova_1.logCordovaManualSteps)(cordovaPlugins, config, platform);
const incompatibleCordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
const incompatibleCordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
await (0, common_1.checkPlatformVersions)(config, platform);
}
async function generateCordovaPackageFiles(cordovaPlugins, config) {
cordovaPlugins.map((plugin) => {
generateCordovaPackageFile(plugin, config);
});
}
async function generateCordovaPackageFile(p, config) {
const iosPlatformVersion = await (0, common_1.getCapacitorPackageVersion)(config, config.ios.name);
const iosVersion = (0, common_2.getMajoriOSVersion)(config);
const headerFiles = (0, plugin_1.getPlatformElement)(p, platform, 'header-file');
let headersText = '';
if (headerFiles.length > 0) {
headersText = `,
publicHeadersPath: "."`;
}
const content = `// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "${p.name}",
platforms: [.iOS(.v${iosVersion})],
products: [
.library(
name: "${p.name}",
targets: ["${p.name}"]
)
],
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "${iosPlatformVersion}")
],
targets: [
.target(
name: "${p.name}",
dependencies: [
.product(name: "Cordova", package: "capacitor-swift-pm")
],
path: "."${headersText}
)
]
)`;
await (0, fs_extra_1.writeFile)((0, path_1.join)(config.ios.cordovaPluginsDirAbs, 'sources', p.name, 'Package.swift'), content);
}
async function installCocoaPodsPlugins(config, plugins, deployment) {
await (0, common_1.runTask)(`Updating iOS native dependencies with ${colors_1.default.input(`${await config.ios.podPath} install`)}`, () => {
@ -60,31 +105,23 @@ async function updatePodfile(config, plugins, deployment) {
const dependenciesContent = await generatePodFile(config, plugins);
const relativeCapacitoriOSPath = await getRelativeCapacitoriOSPath(config);
const podfilePath = (0, path_1.join)(config.ios.nativeProjectDirAbs, 'Podfile');
let podfileContent = await (0, utils_fs_1.readFile)(podfilePath, { encoding: 'utf-8' });
let podfileContent = await (0, fs_extra_1.readFile)(podfilePath, { encoding: 'utf-8' });
podfileContent = podfileContent.replace(/(def capacitor_pods)[\s\S]+?(\nend)/, `$1${dependenciesContent}$2`);
podfileContent = podfileContent.replace(/(require_relative)[\s\S]+?(@capacitor\/ios\/scripts\/pods_helpers')/, `require_relative '${relativeCapacitoriOSPath}/scripts/pods_helpers'`);
podfileContent = podfileContent.replace(`def assertDeploymentTarget(installer)
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# ensure IPHONEOS_DEPLOYMENT_TARGET is at least 13.0
deployment_target = config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f
should_upgrade = deployment_target < 13.0 && deployment_target != 0.0
if should_upgrade
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
end
end`, `require_relative '${relativeCapacitoriOSPath}/scripts/pods_helpers'`);
await (0, utils_fs_1.writeFile)(podfilePath, podfileContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(podfilePath, podfileContent, { encoding: 'utf-8' });
const podPath = await config.ios.podPath;
const useBundler = podPath.startsWith('bundle');
const useBundler = podPath.startsWith('bundle') && (await (0, subprocess_1.isInstalled)('bundle'));
const podCommandExists = await (0, subprocess_1.isInstalled)('pod');
if (useBundler || podCommandExists) {
if (useBundler) {
await (0, subprocess_1.runCommand)('bundle', ['exec', 'pod', 'install', ...(deployment ? ['--deployment'] : [])], { cwd: config.ios.nativeProjectDirAbs });
await (0, subprocess_1.runCommand)('bundle', ['exec', 'pod', 'install', ...(deployment ? ['--deployment'] : [])], {
cwd: config.ios.nativeProjectDirAbs,
});
}
else {
await (0, subprocess_1.runCommand)(podPath, ['install', ...(deployment ? ['--deployment'] : [])], { cwd: config.ios.nativeProjectDirAbs });
await (0, subprocess_1.runCommand)(podPath, ['install', ...(deployment ? ['--deployment'] : [])], {
cwd: config.ios.nativeProjectDirAbs,
});
}
}
else {
@ -106,18 +143,18 @@ async function getRelativeCapacitoriOSPath(config) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/ios')}.\n` +
`Are you sure ${colors_1.default.strong('@capacitor/ios')} is installed?`);
}
return (0, fs_1.convertToUnixPath)((0, path_1.relative)(config.ios.nativeProjectDirAbs, await (0, utils_fs_1.realpath)((0, path_1.dirname)(capacitoriOSPath))));
return (0, fs_1.convertToUnixPath)((0, path_1.relative)(config.ios.nativeProjectDirAbs, await (0, fs_extra_1.realpath)((0, path_1.dirname)(capacitoriOSPath))));
}
async function generatePodFile(config, plugins) {
const relativeCapacitoriOSPath = await getRelativeCapacitoriOSPath(config);
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
const capacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
const pods = await Promise.all(capacitorPlugins.map(async (p) => {
if (!p.ios) {
return '';
}
return ` pod '${p.ios.name}', :path => '${(0, fs_1.convertToUnixPath)((0, path_1.relative)(config.ios.nativeProjectDirAbs, await (0, utils_fs_1.realpath)(p.rootPath)))}'\n`;
return ` pod '${p.ios.name}', :path => '${(0, fs_1.convertToUnixPath)((0, path_1.relative)(config.ios.nativeProjectDirAbs, await (0, fs_extra_1.realpath)(p.rootPath)))}'\n`;
}));
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
cordovaPlugins.map(async (p) => {
const podspecs = (0, plugin_1.getPlatformElement)(p, platform, 'podspec');
podspecs.map((podspec) => {
@ -140,8 +177,8 @@ async function generatePodFile(config, plugins) {
});
});
});
const staticPlugins = cordovaPlugins.filter(p => (0, cordova_1.needsStaticPod)(p, config));
const noStaticPlugins = cordovaPlugins.filter(el => !staticPlugins.includes(el));
const staticPlugins = cordovaPlugins.filter((p) => (0, cordova_1.needsStaticPod)(p));
const noStaticPlugins = cordovaPlugins.filter((el) => !staticPlugins.includes(el));
if (noStaticPlugins.length > 0) {
pods.push(` pod 'CordovaPlugins', :path => '../capacitor-cordova-ios-plugins'\n`);
}
@ -164,16 +201,14 @@ function getFrameworkName(framework) {
}
return framework.$.src.substr(0, framework.$.src.indexOf('.'));
}
return framework.$.src
.substr(0, framework.$.src.indexOf('.'))
.replace('lib', '');
return framework.$.src.substr(0, framework.$.src.indexOf('.')).replace('lib', '');
}
function isFramework(framework) {
return framework.$.src.split('.').pop().includes('framework');
}
async function generateCordovaPodspecs(cordovaPlugins, config) {
const staticPlugins = cordovaPlugins.filter(p => (0, cordova_1.needsStaticPod)(p, config));
const noStaticPlugins = cordovaPlugins.filter(el => !staticPlugins.includes(el));
const staticPlugins = cordovaPlugins.filter((p) => (0, cordova_1.needsStaticPod)(p));
const noStaticPlugins = cordovaPlugins.filter((el) => !staticPlugins.includes(el));
generateCordovaPodspec(noStaticPlugins, config, false);
generateCordovaPodspec(staticPlugins, config, true);
}
@ -267,7 +302,7 @@ async function generateCordovaPodspec(cordovaPlugins, config, isStatic) {
}
});
});
const onlySystemLibraries = systemLibraries.filter(library => removeNoSystem(library, sourceFrameworks));
const onlySystemLibraries = systemLibraries.filter((library) => removeNoSystem(library, sourceFrameworks));
if (weakFrameworks.length > 0) {
frameworkDeps.push(`s.weak_frameworks = '${weakFrameworks.join(`', '`)}'`);
}
@ -312,7 +347,7 @@ async function generateCordovaPodspec(cordovaPlugins, config, isStatic) {
s.swift_version = '5.1'
${frameworksString}
end`;
await (0, utils_fs_1.writeFile)((0, path_1.join)(config.ios.cordovaPluginsDirAbs, `${name}.podspec`), content);
await (0, fs_extra_1.writeFile)((0, path_1.join)(config.ios.cordovaPluginsDirAbs, `${name}.podspec`), content);
}
function getLinkerFlags(config) {
var _a;
@ -328,7 +363,7 @@ async function copyPluginsNativeFiles(config, cordovaPlugins) {
const codeFiles = sourceFiles.concat(headerFiles);
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
let sourcesFolderName = 'sources';
if ((0, cordova_1.needsStaticPod)(p, config)) {
if ((0, cordova_1.needsStaticPod)(p)) {
sourcesFolderName += 'static';
}
const sourcesFolder = (0, path_1.join)(config.ios.cordovaPluginsDirAbs, sourcesFolderName, p.name);
@ -339,35 +374,33 @@ async function copyPluginsNativeFiles(config, cordovaPlugins) {
fileName = 'lib' + fileName;
}
let destFolder = sourcesFolderName;
if (codeFile.$['compiler-flags'] &&
codeFile.$['compiler-flags'] === '-fno-objc-arc') {
if (codeFile.$['compiler-flags'] && codeFile.$['compiler-flags'] === '-fno-objc-arc') {
destFolder = 'noarc';
}
const filePath = (0, plugin_1.getFilePath)(config, p, codeFile.$.src);
const fileDest = (0, path_1.join)(config.ios.cordovaPluginsDirAbs, destFolder, p.name, fileName);
await (0, utils_fs_1.copy)(filePath, fileDest);
await (0, fs_extra_1.copy)(filePath, fileDest);
if (!codeFile.$.framework) {
let fileContent = await (0, utils_fs_1.readFile)(fileDest, { encoding: 'utf-8' });
let fileContent = await (0, fs_extra_1.readFile)(fileDest, { encoding: 'utf-8' });
if (fileExt === 'swift') {
fileContent = 'import Cordova\n' + fileContent;
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
else {
if (fileContent.includes('@import Firebase;')) {
fileContent = fileContent.replace('@import Firebase;', '#import <Firebase/Firebase.h>');
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
if (fileContent.includes('[NSBundle bundleForClass:[self class]]') ||
fileContent.includes('[NSBundle bundleForClass:[CDVCapture class]]')) {
fileContent = fileContent.replace('[NSBundle bundleForClass:[self class]]', '[NSBundle mainBundle]');
fileContent = fileContent.replace('[NSBundle bundleForClass:[CDVCapture class]]', '[NSBundle mainBundle]');
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
if (fileContent.includes('[self.webView superview]') ||
fileContent.includes('self.webView.superview')) {
if (fileContent.includes('[self.webView superview]') || fileContent.includes('self.webView.superview')) {
fileContent = fileContent.replace(/\[self.webView superview\]/g, 'self.viewController.view');
fileContent = fileContent.replace(/self.webView.superview/g, 'self.viewController.view');
await (0, utils_fs_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
await (0, fs_extra_1.writeFile)(fileDest, fileContent, { encoding: 'utf-8' });
}
}
}
@ -375,17 +408,17 @@ async function copyPluginsNativeFiles(config, cordovaPlugins) {
const resourceFiles = (0, plugin_1.getPlatformElement)(p, platform, 'resource-file');
for (const resourceFile of resourceFiles) {
const fileName = resourceFile.$.src.split('/').pop();
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(config.ios.cordovaPluginsDirAbs, 'resources', fileName));
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(config.ios.cordovaPluginsDirAbs, 'resources', fileName));
}
for (const framework of frameworks) {
if (framework.$.custom && framework.$.custom === 'true') {
await (0, utils_fs_1.copy)((0, plugin_1.getFilePath)(config, p, framework.$.src), (0, path_1.join)(sourcesFolder, framework.$.src));
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, framework.$.src), (0, path_1.join)(sourcesFolder, framework.$.src));
}
}
}
}
async function removePluginsNativeFiles(config) {
await (0, utils_fs_1.remove)(config.ios.cordovaPluginsDirAbs);
await (0, fs_extra_1.remove)(config.ios.cordovaPluginsDirAbs);
await (0, template_1.extractTemplate)(config.cli.assets.ios.cordovaPluginsTemplateArchiveAbs, config.ios.cordovaPluginsDirAbs);
}
function filterResources(plugin) {
@ -394,12 +427,11 @@ function filterResources(plugin) {
}
function filterARCFiles(plugin) {
const sources = (0, plugin_1.getPlatformElement)(plugin, platform, 'source-file');
const sourcesARC = sources.filter((sourceFile) => sourceFile.$['compiler-flags'] &&
sourceFile.$['compiler-flags'] === '-fno-objc-arc');
const sourcesARC = sources.filter((sourceFile) => sourceFile.$['compiler-flags'] && sourceFile.$['compiler-flags'] === '-fno-objc-arc');
return sourcesARC.length > 0;
}
function removeNoSystem(library, sourceFrameworks) {
const libraries = sourceFrameworks.filter(framework => framework.includes(library));
const libraries = sourceFrameworks.filter((framework) => framework.includes(library));
return libraries.length === 0;
}
async function getPluginsTask(config) {

View file

@ -2,9 +2,9 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.receive = exports.send = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const utils_subprocess_1 = require("@ionic/utils-subprocess");
const debug_1 = tslib_1.__importDefault(require("debug"));
const fs_extra_1 = require("fs-extra");
const https_1 = require("https");
const path_1 = require("path");
const cli_1 = require("./util/cli");
@ -14,10 +14,10 @@ const debug = (0, debug_1.default)('capacitor:ipc');
*/
async function send(msg) {
const dir = cli_1.ENV_PATHS.log;
await (0, utils_fs_1.mkdirp)(dir);
await (0, fs_extra_1.mkdirp)(dir);
const logPath = (0, path_1.resolve)(dir, 'ipc.log');
debug('Sending %O IPC message to forked process (logs: %O)', msg.type, logPath);
const fd = await (0, utils_fs_1.open)(logPath, 'a');
const fd = await (0, fs_extra_1.open)(logPath, 'a');
const p = (0, utils_subprocess_1.fork)(process.argv[1], ['📡'], { stdio: ['ignore', fd, fd, 'ipc'] });
p.send(msg);
p.disconnect();
@ -43,10 +43,10 @@ async function receive(msg) {
headers: {
'Content-Type': 'application/json',
},
}, response => {
}, (response) => {
debug('Sent %O metric to events service (status: %O)', data.name, response.statusCode);
if (response.statusCode !== 204) {
response.on('data', chunk => {
response.on('data', (chunk) => {
debug('Bad response from events service. Request body: %O', chunk.toString());
});
}

View file

@ -9,9 +9,7 @@ const options = {
colors: colors_1.default,
stream: process.argv.includes('--json') ? process.stderr : process.stdout,
};
exports.output = (0, term_1.isInteractive)()
? new cli_framework_output_1.TTYOutputStrategy(options)
: new cli_framework_output_1.StreamOutputStrategy(options);
exports.output = (0, term_1.isInteractive)() ? new cli_framework_output_1.TTYOutputStrategy(options) : new cli_framework_output_1.StreamOutputStrategy(options);
exports.logger = (0, cli_framework_output_1.createDefaultLogger)({
output: exports.output,
formatterOptions: {

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAllElements = exports.getFilePath = exports.getAssets = exports.getJSModules = exports.getPluginType = exports.getPlatformElement = exports.getPluginPlatform = exports.printPlugins = exports.fixName = exports.getDependencies = exports.resolvePlugin = exports.getPlugins = exports.getIncludedPluginPackages = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("./colors"));
const errors_1 = require("./errors");
@ -31,11 +31,10 @@ async function resolvePlugin(config, name) {
try {
const packagePath = (0, node_1.resolveNode)(config.app.rootDir, name, 'package.json');
if (!packagePath) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong(`node_modules/${name}`)}.\n` +
`Are you sure ${colors_1.default.strong(name)} is installed?`);
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong(`node_modules/${name}`)}.\n` + `Are you sure ${colors_1.default.strong(name)} is installed?`);
}
const rootPath = (0, path_1.dirname)(packagePath);
const meta = await (0, utils_fs_1.readJSON)(packagePath);
const meta = await (0, fs_extra_1.readJSON)(packagePath);
if (!meta) {
return null;
}
@ -79,7 +78,7 @@ function fixName(name) {
.replace(/\//g, '_')
.replace(/-/g, '_')
.replace(/@/g, '')
.replace(/_\w/g, m => m[1].toUpperCase());
.replace(/_\w/g, (m) => m[1].toUpperCase());
return name.charAt(0).toUpperCase() + name.slice(1);
}
exports.fixName = fixName;
@ -100,7 +99,7 @@ function printPlugins(plugins, platform, type = 'capacitor') {
msg = `Found ${plugins.length} Capacitor plugin${plural} for ${colors_1.default.strong(platform)}:\n`;
break;
}
msg += plugins.map(p => `${p.id}${colors_1.default.weak(`@${p.version}`)}`).join('\n');
msg += plugins.map((p) => `${p.id}${colors_1.default.weak(`@${p.version}`)}`).join('\n');
log_1.logger.info(msg);
}
exports.printPlugins = printPlugins;
@ -155,10 +154,7 @@ function getFilePath(config, plugin, path) {
if (path.startsWith('node_modules')) {
let pathSegments = path.split('/').slice(1);
if (pathSegments[0].startsWith('@')) {
pathSegments = [
pathSegments[0] + '/' + pathSegments[1],
...pathSegments.slice(2),
];
pathSegments = [pathSegments[0] + '/' + pathSegments[1], ...pathSegments.slice(2)];
}
const filePath = (0, node_1.resolveNode)(config.app.rootDir, ...pathSegments);
if (!filePath) {

View file

@ -2,8 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeConfig = exports.readConfig = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const debug_1 = tslib_1.__importDefault(require("debug"));
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const cli_1 = require("./util/cli");
const uuid_1 = require("./util/uuid");
@ -13,7 +13,7 @@ const SYSCONFIG_PATH = (0, path_1.resolve)(cli_1.ENV_PATHS.config, SYSCONFIG_FIL
async function readConfig() {
debug('Reading from %O', SYSCONFIG_PATH);
try {
return await (0, utils_fs_1.readJSON)(SYSCONFIG_PATH);
return await (0, fs_extra_1.readJSON)(SYSCONFIG_PATH);
}
catch (e) {
if (e.code !== 'ENOENT') {
@ -29,7 +29,7 @@ async function readConfig() {
exports.readConfig = readConfig;
async function writeConfig(sysconfig) {
debug('Writing to %O', SYSCONFIG_PATH);
await (0, utils_fs_1.mkdirp)((0, path_1.dirname)(SYSCONFIG_PATH));
await (0, utils_fs_1.writeJSON)(SYSCONFIG_PATH, sysconfig, { spaces: '\t' });
await (0, fs_extra_1.mkdirp)((0, path_1.dirname)(SYSCONFIG_PATH));
await (0, fs_extra_1.writeJSON)(SYSCONFIG_PATH, sysconfig, { spaces: '\t' });
}
exports.writeConfig = writeConfig;

View file

@ -2,8 +2,8 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.addCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const utils_terminal_1 = require("@ionic/utils-terminal");
const fs_extra_1 = require("fs-extra");
const add_1 = require("../android/add");
const common_1 = require("../android/common");
const colors_1 = tslib_1.__importDefault(require("../colors"));
@ -47,14 +47,10 @@ async function addCommand(config, selectedPlatformName) {
`${colors_1.default.strong('WARNING')}: Your native project will be completely removed.`);
}
try {
await (0, common_2.check)([
() => (0, common_2.checkPackage)(),
() => (0, common_2.checkAppConfig)(config),
...addChecks(config, platformName),
]);
await (0, common_2.check)([() => (0, common_2.checkPackage)(), () => (0, common_2.checkAppConfig)(config), ...addChecks(config, platformName)]);
await doAdd(config, platformName);
await editPlatforms(config, platformName);
if (await (0, utils_fs_1.pathExists)(config.app.webDirAbs)) {
if (await (0, fs_extra_1.pathExists)(config.app.webDirAbs)) {
await (0, sync_1.sync)(config, platformName, false, false);
if (platformName === config.android.name) {
await (0, common_2.runTask)('Syncing Gradle', async () => {
@ -82,10 +78,7 @@ function printNextSteps(platformName) {
}
function addChecks(config, platformName) {
if (platformName === config.ios.name) {
return [
() => (0, common_3.checkIOSPackage)(config),
() => (0, common_3.checkBundler)(config) || (0, common_3.checkCocoaPods)(config),
];
return [() => (0, common_3.checkIOSPackage)(config), () => (0, common_3.checkBundler)(config) || (0, common_3.checkCocoaPods)(config)];
}
else if (platformName === config.android.name) {
return [() => (0, common_1.checkAndroidPackage)(config)];

View file

@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.build = exports.buildCommand = void 0;
const build_1 = require("../android/build");
const common_1 = require("../common");
const definitions_1 = require("../definitions");
const errors_1 = require("../errors");
const build_2 = require("../ios/build");
async function buildCommand(config, selectedPlatformName, buildOptions) {
@ -21,15 +22,15 @@ async function buildCommand(config, selectedPlatformName, buildOptions) {
keystorepath: buildOptions.keystorepath || config.android.buildOptions.keystorePath,
keystorepass: buildOptions.keystorepass || config.android.buildOptions.keystorePassword,
keystorealias: buildOptions.keystorealias || config.android.buildOptions.keystoreAlias,
keystorealiaspass: buildOptions.keystorealiaspass ||
config.android.buildOptions.keystoreAliasPassword,
androidreleasetype: buildOptions.androidreleasetype ||
config.android.buildOptions.releaseType ||
'AAB',
signingtype: buildOptions.signingtype ||
config.android.buildOptions.signingType ||
'jarsigner',
keystorealiaspass: buildOptions.keystorealiaspass || config.android.buildOptions.keystoreAliasPassword,
androidreleasetype: buildOptions.androidreleasetype || config.android.buildOptions.releaseType || 'AAB',
signingtype: buildOptions.signingtype || config.android.buildOptions.signingType || 'jarsigner',
configuration: buildOptions.configuration || 'Release',
xcodeTeamId: buildOptions.xcodeTeamId || config.ios.buildOptions.teamId,
xcodeExportMethod: buildOptions.xcodeExportMethod || config.ios.buildOptions.exportMethod || definitions_1.XcodeExportMethod.AppStoreConnect,
xcodeSigningType: buildOptions.xcodeSigningType || config.ios.buildOptions.xcodeSigningStyle || 'automatic',
xcodeSigningCertificate: buildOptions.xcodeSigningCertificate || config.ios.buildOptions.signingCertificate,
xcodeProvisioningProfile: buildOptions.xcodeProvisioningProfile || config.ios.buildOptions.provisioningProfile,
};
try {
await build(config, platformName, buildCommandOptions);
@ -58,5 +59,5 @@ async function build(config, platformName, buildOptions) {
}
exports.build = build;
function createBuildablePlatformFilter(config) {
return platform => platform === config.ios.name || platform === config.android.name;
return (platform) => platform === config.ios.name || platform === config.android.name;
}

View file

@ -15,10 +15,7 @@ async function configCommand(config, json) {
}
exports.configCommand = configCommand;
async function deepAwait(obj) {
if (obj &&
!Array.isArray(obj) &&
typeof obj === 'object' &&
obj.constructor === Object) {
if (obj && !Array.isArray(obj) && typeof obj === 'object' && obj.constructor === Object) {
const o = {};
for (const [k, v] of Object.entries(obj)) {
o[k] = await deepAwait(v);

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.copy = exports.copyCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
@ -13,7 +13,6 @@ const log_1 = require("../log");
const plugin_1 = require("../plugin");
const iosplugin_1 = require("../util/iosplugin");
const promise_1 = require("../util/promise");
const copy_1 = require("../web/copy");
const sourcemaps_1 = require("./sourcemaps");
async function copyCommand(config, selectedPlatformName, inline = false) {
var _a;
@ -29,7 +28,7 @@ async function copyCommand(config, selectedPlatformName, inline = false) {
else {
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
try {
await (0, promise_1.allSerial)(platforms.map(platformName => () => copy(config, platformName, inline)));
await (0, promise_1.allSerial)(platforms.map((platformName) => () => copy(config, platformName, inline)));
}
catch (e) {
if ((0, errors_1.isFatal)(e)) {
@ -50,17 +49,15 @@ async function copy(config, platformName, inline = false) {
await (0, common_1.runHooks)(config, platformName, config.app.rootDir, 'capacitor:copy:before');
const allPlugins = await (0, plugin_1.getPlugins)(config, platformName);
let usesFederatedCapacitor = false;
if (allPlugins.filter(plugin => plugin.id === '@ionic-enterprise/federated-capacitor').length > 0) {
if (allPlugins.filter((plugin) => plugin.id === '@ionic-enterprise/federated-capacitor').length > 0) {
usesFederatedCapacitor = true;
}
let usesLiveUpdates = false;
if (allPlugins.filter(plugin => plugin.id === '@capacitor/live-updates')
.length > 0) {
if (allPlugins.filter((plugin) => plugin.id === '@capacitor/live-updates').length > 0) {
usesLiveUpdates = true;
}
let usesSSLPinning = false;
if (allPlugins.filter(plugin => plugin.id === '@ionic-enterprise/ssl-pinning')
.length > 0) {
if (allPlugins.filter((plugin) => plugin.id === '@ionic-enterprise/ssl-pinning').length > 0) {
usesSSLPinning = true;
}
if (platformName === config.ios.name) {
@ -110,9 +107,6 @@ async function copy(config, platformName, inline = false) {
if (usesFederatedCapacitor) {
log_1.logger.info('FederatedCapacitor Plugin installed, skipping web bundling...');
}
else {
await (0, copy_1.copyWeb)(config);
}
}
else {
throw `Platform ${platformName} is not valid.`;
@ -129,9 +123,10 @@ async function copyCapacitorConfig(config, nativeAbsDir) {
const nativeConfigFile = 'capacitor.config.json';
const nativeConfigFilePath = (0, path_1.join)(nativeAbsDir, nativeConfigFile);
await (0, common_1.runTask)(`Creating ${colors_1.default.strong(nativeConfigFile)} in ${nativeRelDir}`, async () => {
var _a;
var _a, _b;
(_a = config.app.extConfig.android) === null || _a === void 0 ? true : delete _a.buildOptions;
await (0, utils_fs_1.writeJSON)(nativeConfigFilePath, config.app.extConfig, {
(_b = config.app.extConfig.ios) === null || _b === void 0 ? true : delete _b.buildOptions;
await (0, fs_extra_1.writeJSON)(nativeConfigFilePath, config.app.extConfig, {
spaces: '\t',
});
});
@ -140,14 +135,14 @@ async function copyWebDir(config, nativeAbsDir, webAbsDir) {
var _a;
const webRelDir = (0, path_1.basename)(webAbsDir);
const nativeRelDir = (0, path_1.relative)(config.app.rootDir, nativeAbsDir);
if (((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.url) && !(await (0, utils_fs_1.pathExists)(webAbsDir))) {
if (((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.url) && !(await (0, fs_extra_1.pathExists)(webAbsDir))) {
log_1.logger.warn(`Cannot copy web assets from ${colors_1.default.strong(webRelDir)} to ${nativeRelDir}\n` +
`Web asset directory specified by ${colors_1.default.input('webDir')} does not exist. This is not an error because ${colors_1.default.input('server.url')} is set in config.`);
return;
}
await (0, common_1.runTask)(`Copying web assets from ${colors_1.default.strong(webRelDir)} to ${nativeRelDir}`, async () => {
await (0, utils_fs_1.remove)(nativeAbsDir);
return (0, utils_fs_1.copy)(webAbsDir, nativeAbsDir);
await (0, fs_extra_1.remove)(nativeAbsDir);
return (0, fs_extra_1.copy)(webAbsDir, nativeAbsDir);
});
}
async function copyFederatedWebDirs(config, nativeAbsDir) {
@ -165,7 +160,7 @@ async function copyFederatedWebDirs(config, nativeAbsDir) {
throw `FederatedCapacitor plugin is present but there is a problem with the apps defined in the config.`;
}
const copyApps = () => {
return federatedConfig.apps.map(app => {
return federatedConfig.apps.map((app) => {
const appDir = (0, path_1.resolve)(config.app.rootDir, app.webDir);
return copyWebDir(config, (0, path_1.resolve)(nativeAbsDir, app.name), appDir);
});
@ -177,27 +172,26 @@ async function copyFederatedWebDirs(config, nativeAbsDir) {
}
}
function isFederatedApp(config) {
return (config.webDir !== undefined &&
config.name !== undefined);
return config.webDir !== undefined && config.name !== undefined;
}
async function copySecureLiveUpdatesKey(secureLiveUpdatesKeyFile, rootDir, nativeAbsDir) {
const keyAbsFromPath = (0, path_1.join)(rootDir, secureLiveUpdatesKeyFile);
const keyAbsToPath = (0, path_1.join)(nativeAbsDir, (0, path_1.basename)(keyAbsFromPath));
const keyRelToDir = (0, path_1.relative)(rootDir, nativeAbsDir);
if (!(await (0, utils_fs_1.pathExists)(keyAbsFromPath))) {
if (!(await (0, fs_extra_1.pathExists)(keyAbsFromPath))) {
log_1.logger.warn(`Cannot copy Secure Live Updates signature file from ${colors_1.default.strong(keyAbsFromPath)} to ${keyRelToDir}\n` +
`Signature file does not exist at specified key path.`);
return;
}
await (0, common_1.runTask)(`Copying Secure Live Updates key from ${colors_1.default.strong(secureLiveUpdatesKeyFile)} to ${keyRelToDir}`, async () => {
return (0, utils_fs_1.copy)(keyAbsFromPath, keyAbsToPath);
return (0, fs_extra_1.copy)(keyAbsFromPath, keyAbsToPath);
});
}
async function copySSLCert(sslCertPaths, rootDir, targetDir) {
const validCertPaths = [];
for (const sslCertPath of sslCertPaths) {
const certAbsFromPath = (0, path_1.join)(rootDir, sslCertPath);
if (!(await (0, utils_fs_1.pathExists)(certAbsFromPath))) {
if (!(await (0, fs_extra_1.pathExists)(certAbsFromPath))) {
log_1.logger.warn(`Cannot copy SSL Certificate file from ${colors_1.default.strong(certAbsFromPath)}\n` +
`SSL Certificate does not exist at specified path.`);
return;
@ -209,7 +203,7 @@ async function copySSLCert(sslCertPaths, rootDir, targetDir) {
await (0, common_1.runTask)(`Copying SSL Certificates from to ${certsDirRelToDir}`, async () => {
const promises = [];
for (const certPath of validCertPaths) {
promises.push((0, utils_fs_1.copy)(certPath, (0, path_1.join)(certsDirAbsToPath, (0, path_1.basename)(certPath))));
promises.push((0, fs_extra_1.copy)(certPath, (0, path_1.join)(certsDirAbsToPath, (0, path_1.basename)(certPath))));
}
return Promise.all(promises);
});

View file

@ -5,7 +5,6 @@ const tslib_1 = require("tslib");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
async function createCommand() {
(0, errors_1.fatal)(`The create command has been removed.\n` +
`Use ${colors_1.default.input('npm init @capacitor/app')}`);
(0, errors_1.fatal)(`The create command has been removed.\n` + `Use ${colors_1.default.input('npm init @capacitor/app')}`);
}
exports.createCommand = createCommand;

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.doctor = exports.doctorCore = exports.doctorCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const doctor_1 = require("../android/doctor");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
@ -15,7 +15,7 @@ async function doctorCommand(config, selectedPlatformName) {
log_1.output.write(`${(0, emoji_1.emoji)('💊', '')} ${colors_1.default.strong('Capacitor Doctor')} ${(0, emoji_1.emoji)('💊', '')} \n\n`);
await doctorCore(config);
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
await Promise.all(platforms.map(platformName => {
await Promise.all(platforms.map((platformName) => {
return doctor(config, platformName);
}));
}
@ -38,12 +38,7 @@ async function doctorCore(config) {
}
exports.doctorCore = doctorCore;
async function printInstalledPackages(config) {
const packageNames = [
'@capacitor/cli',
'@capacitor/core',
'@capacitor/android',
'@capacitor/ios',
];
const packageNames = ['@capacitor/cli', '@capacitor/core', '@capacitor/android', '@capacitor/ios'];
await Promise.all(packageNames.map(async (packageName) => {
const packagePath = (0, node_1.resolveNode)(config.app.rootDir, packageName, 'package.json');
await printPackageVersion(packageName, packagePath);
@ -52,7 +47,7 @@ async function printInstalledPackages(config) {
async function printPackageVersion(packageName, packagePath) {
let version;
if (packagePath) {
version = (await (0, utils_fs_1.readJSON)(packagePath)).version;
version = (await (0, fs_extra_1.readJSON)(packagePath)).version;
}
log_1.output.write(` ${packageName}: ${colors_1.default.weak(version || 'not installed')}\n`);
}

View file

@ -14,7 +14,7 @@ const log_1 = require("../log");
const sysconfig_1 = require("../sysconfig");
const node_1 = require("../util/node");
const term_1 = require("../util/term");
async function initCommand(config, name, id, webDirFromCLI) {
async function initCommand(config, name, id, webDirFromCLI, skipAppIDValidation) {
var _a, _b;
try {
if (!(0, term_1.checkInteractive)(name, id)) {
@ -30,11 +30,13 @@ async function initCommand(config, name, id, webDirFromCLI) {
const appId = await getAppId(config, id);
const webDir = (0, term_1.isInteractive)()
? await getWebDir(config, webDirFromCLI)
: (_a = webDirFromCLI !== null && webDirFromCLI !== void 0 ? webDirFromCLI : config.app.extConfig.webDir) !== null && _a !== void 0 ? _a : 'www';
await (0, common_1.check)([
() => (0, common_1.checkAppName)(config, appName),
() => (0, common_1.checkAppId)(config, appId),
]);
: ((_a = webDirFromCLI !== null && webDirFromCLI !== void 0 ? webDirFromCLI : config.app.extConfig.webDir) !== null && _a !== void 0 ? _a : 'www');
if (skipAppIDValidation === true) {
await (0, common_1.check)([() => (0, common_1.checkAppName)(config, appName)]);
}
else {
await (0, common_1.check)([() => (0, common_1.checkAppName)(config, appName), () => (0, common_1.checkAppId)(config, appId)]);
}
const cordova = await (0, cordova_1.getCordovaPreferences)(config);
await runMergeConfig(config, {
appId,
@ -45,8 +47,7 @@ async function initCommand(config, name, id, webDirFromCLI) {
}
catch (e) {
if (!(0, errors_1.isFatal)(e)) {
log_1.output.write('Usage: npx cap init appName appId\n' +
'Example: npx cap init "My App" "com.example.myapp"\n\n');
log_1.output.write('Usage: npx cap init appName appId\n' + 'Example: npx cap init "My App" "com.example.myapp"\n\n');
(0, errors_1.fatal)((_b = e.stack) !== null && _b !== void 0 ? _b : e);
}
throw e;
@ -61,9 +62,7 @@ async function getName(config, name) {
type: 'text',
name: 'name',
message: `Name`,
initial: config.app.appName
? config.app.appName
: (_a = config.app.package.name) !== null && _a !== void 0 ? _a : 'App',
initial: config.app.appName ? config.app.appName : ((_a = config.app.package.name) !== null && _a !== void 0 ? _a : 'App'),
});
return answers.name;
}

View file

@ -14,7 +14,7 @@ async function listCommand(config, selectedPlatformName) {
var _a;
const platforms = await (0, common_2.selectPlatforms)(config, selectedPlatformName);
try {
await (0, promise_1.allSerial)(platforms.map(platformName => () => list(config, platformName)));
await (0, promise_1.allSerial)(platforms.map((platformName) => () => list(config, platformName)));
}
catch (e) {
if ((0, errors_1.isFatal)(e)) {
@ -40,11 +40,11 @@ async function list(config, platform) {
else {
throw `Platform ${colors_1.default.input(platform)} is not valid.`;
}
const capacitorPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
const capacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
(0, plugin_1.printPlugins)(capacitorPlugins, platform);
const cordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
(0, plugin_1.printPlugins)(cordovaPlugins, platform, 'cordova');
const incompatibleCordovaPlugins = plugins.filter(p => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
const incompatibleCordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
}
exports.list = list;

View file

@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.migrateToSPM = void 0;
const errors_1 = require("../errors");
const log_1 = require("../log");
const spm_1 = require("../util/spm");
const update_1 = require("./update");
async function migrateToSPM(config) {
if ((await (0, spm_1.checkPackageManager)(config)) == 'SPM') {
(0, errors_1.fatal)('Capacitor project is already using SPM, exiting.');
}
await (0, spm_1.extractSPMPackageDirectory)(config);
await (0, spm_1.runCocoapodsDeintegrate)(config);
await (0, spm_1.removeCocoapodsFiles)(config);
await (0, spm_1.addInfoPlistDebugIfNeeded)(config);
await (0, update_1.update)(config, 'ios', true);
log_1.logger.info('To complete migration follow the manual steps at https://capacitorjs.com/docs/ios/spm#using-our-migration-tool');
}
exports.migrateToSPM = migrateToSPM;

View file

@ -2,28 +2,25 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.patchOldCapacitorPlugins = exports.migrateCommand = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const rimraf_1 = tslib_1.__importDefault(require("rimraf"));
const rimraf_1 = require("rimraf");
const semver_1 = require("semver");
const common_1 = require("../android/common");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_2 = require("../common");
const errors_1 = require("../errors");
const common_3 = require("../ios/common");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const fs_1 = require("../util/fs");
const node_1 = require("../util/node");
const spm_1 = require("../util/spm");
const subprocess_1 = require("../util/subprocess");
const template_1 = require("../util/template");
// eslint-disable-next-line prefer-const
let allDependencies = {};
const libs = [
'@capacitor/core',
'@capacitor/cli',
'@capacitor/ios',
'@capacitor/android',
];
const libs = ['@capacitor/core', '@capacitor/cli', '@capacitor/ios', '@capacitor/android'];
const plugins = [
'@capacitor/action-sheet',
'@capacitor/app',
@ -50,21 +47,22 @@ const plugins = [
'@capacitor/text-zoom',
'@capacitor/toast',
];
const coreVersion = '^6.0.0';
const pluginVersion = '^6.0.0';
const gradleVersion = '8.2.1';
const coreVersion = '^7.0.0';
const pluginVersion = '^7.0.0';
const gradleVersion = '8.11.1';
const iOSVersion = '14';
let installFailed = false;
async function migrateCommand(config, noprompt, packagemanager) {
if (config === null) {
(0, errors_1.fatal)('Config data missing');
}
const capMajor = await checkCapacitorMajorVersion(config);
if (capMajor < 5) {
(0, errors_1.fatal)('Migrate can only be used on capacitor 5 and above, please use the CLI in Capacitor 5 to upgrade to 5 first');
if (capMajor < 6) {
(0, errors_1.fatal)('Migrate can only be used on Capacitor 6, please use the CLI in Capacitor 6 to upgrade to 6 first');
}
const jdkMajor = await (0, common_2.checkJDKMajorVersion)();
if (jdkMajor < 17) {
log_1.logger.warn('Capacitor 6 requires JDK 17 or higher. Some steps may fail.');
if (jdkMajor < 21) {
log_1.logger.warn('Capacitor 7 requires JDK 21 or higher. Some steps may fail.');
}
const variablesAndClasspaths = await getAndroidVariablesAndClasspaths(config);
if (!variablesAndClasspaths) {
@ -78,14 +76,13 @@ async function migrateCommand(config, noprompt, packagemanager) {
log_1.logger.info(monorepoWarning);
const { migrateconfirm } = noprompt
? { migrateconfirm: 'y' }
: await (0, log_1.logPrompt)(`Capacitor 6 sets a deployment target of iOS 13 and Android 14 (SDK 34). \n`, {
: await (0, log_1.logPrompt)(`Capacitor 7 sets a deployment target of iOS ${iOSVersion} and Android 15 (SDK 35). \n`, {
type: 'text',
name: 'migrateconfirm',
message: `Are you sure you want to migrate? (Y/n)`,
initial: 'y',
});
if (typeof migrateconfirm === 'string' &&
migrateconfirm.toLowerCase() === 'y') {
if (typeof migrateconfirm === 'string' && migrateconfirm.toLowerCase() === 'y') {
try {
const { depInstallConfirm } = noprompt
? { depInstallConfirm: 'y' }
@ -95,8 +92,7 @@ async function migrateCommand(config, noprompt, packagemanager) {
message: `Run Dependency Install? (Y/n)`,
initial: 'y',
});
const runNpmInstall = typeof depInstallConfirm === 'string' &&
depInstallConfirm.toLowerCase() === 'y';
const runNpmInstall = typeof depInstallConfirm === 'string' && depInstallConfirm.toLowerCase() === 'y';
let installerType = 'npm';
if (runNpmInstall) {
const { manager } = packagemanager
@ -125,13 +121,23 @@ async function migrateCommand(config, noprompt, packagemanager) {
installFailed = true;
}
// Update iOS Projects
if (allDependencies['@capacitor/ios'] &&
(0, utils_fs_1.existsSync)(config.ios.platformDirAbs)) {
// ios template changes
// Remove NSLocationAlwaysUsageDescription
await (0, common_2.runTask)(`Migrating Info.plist by removing NSLocationAlwaysUsageDescription key.`, () => {
return removeKey((0, path_1.join)(config.ios.nativeTargetDirAbs, 'Info.plist'), 'NSLocationAlwaysUsageDescription');
});
if (allDependencies['@capacitor/ios'] && (0, fs_extra_1.existsSync)(config.ios.platformDirAbs)) {
const currentiOSVersion = (0, common_3.getMajoriOSVersion)(config);
if (parseInt(currentiOSVersion) < parseInt(iOSVersion)) {
// ios template changes
await (0, common_2.runTask)(`Migrating deployment target to ${iOSVersion}.0.`, () => {
return updateFile(config, (0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj'), 'IPHONEOS_DEPLOYMENT_TARGET = ', ';', `${iOSVersion}.0`);
});
if ((await (0, spm_1.checkPackageManager)(config)) === 'Cocoapods') {
// Update Podfile
await (0, common_2.runTask)(`Migrating Podfile to ${iOSVersion}.0.`, () => {
return updateFile(config, (0, path_1.join)(config.ios.nativeProjectDirAbs, 'Podfile'), `platform :ios, '`, `'`, `${iOSVersion}.0`);
});
}
}
else {
log_1.logger.warn('Skipped updating deployment target');
}
}
if (!installFailed) {
await (0, common_2.runTask)(`Running cap sync.`, () => {
@ -141,11 +147,18 @@ async function migrateCommand(config, noprompt, packagemanager) {
else {
log_1.logger.warn('Skipped Running cap sync.');
}
if (allDependencies['@capacitor/android'] &&
(0, utils_fs_1.existsSync)(config.android.platformDirAbs)) {
if (allDependencies['@capacitor/android'] && (0, fs_extra_1.existsSync)(config.android.platformDirAbs)) {
// AndroidManifest.xml add navigation"
await (0, common_2.runTask)(`Migrating AndroidManifest.xml by adding navigation to Activity configChanges.`, () => {
return updateAndroidManifest((0, path_1.join)(config.android.srcMainDirAbs, 'AndroidManifest.xml'));
});
const gradleWrapperVersion = getGradleWrapperVersion((0, path_1.join)(config.android.platformDirAbs, 'gradle', 'wrapper', 'gradle-wrapper.properties'));
if (!installFailed && (0, semver_1.gt)(gradleVersion, gradleWrapperVersion)) {
if (!installFailed && (0, semver_1.gte)(gradleVersion, gradleWrapperVersion)) {
try {
await (0, common_2.runTask)(`Upgrading gradle wrapper`, () => {
return updateGradleWrapperFiles(config.android.platformDirAbs);
});
// Run twice as first time it only updates the wrapper properties file
await (0, common_2.runTask)(`Upgrading gradle wrapper files`, () => {
return updateGradleWrapperFiles(config.android.platformDirAbs);
});
@ -165,22 +178,6 @@ async function migrateCommand(config, noprompt, packagemanager) {
await (0, common_2.runTask)(`Migrating build.gradle file.`, () => {
return updateBuildGradle((0, path_1.join)(config.android.platformDirAbs, 'build.gradle'), variablesAndClasspaths);
});
// Replace deprecated compileSdkVersion
await (0, common_2.runTask)('Replacing deprecated compileSdkVersion from build.gradle', () => {
return (async () => {
const buildGradleFilename = (0, path_1.join)(config.android.platformDirAbs, 'app', 'build.gradle');
const buildGradleText = readFile(buildGradleFilename);
if (!buildGradleText) {
log_1.logger.error(`Could not read ${buildGradleFilename}. Check its permissions and if it exists.`);
return;
}
const compileSdk = `compileSdkVersion rootProject.ext.compileSdkVersion`;
if (buildGradleText.includes(compileSdk)) {
const buildGradleReplaced = buildGradleText.replace(compileSdk, `compileSdk rootProject.ext.compileSdkVersion`);
(0, utils_fs_1.writeFileSync)(buildGradleFilename, buildGradleReplaced, 'utf-8');
}
})();
});
// Variables gradle
await (0, common_2.runTask)(`Migrating variables.gradle file.`, () => {
return (async () => {
@ -190,7 +187,7 @@ async function migrateCommand(config, noprompt, packagemanager) {
return;
}
txt = txt.replace(/= {2}'/g, `= '`);
(0, utils_fs_1.writeFileSync)(variablesPath, txt, { encoding: 'utf-8' });
(0, fs_extra_1.writeFileSync)(variablesPath, txt, { encoding: 'utf-8' });
for (const variable of Object.keys(variablesAndClasspaths.variables)) {
let replaceStart = `${variable} = '`;
let replaceEnd = `'\n`;
@ -201,11 +198,9 @@ async function migrateCommand(config, noprompt, packagemanager) {
if (txt.includes(replaceStart)) {
const first = txt.indexOf(replaceStart) + replaceStart.length;
const value = txt.substring(first, txt.indexOf(replaceEnd, first));
if ((typeof variablesAndClasspaths.variables[variable] ===
'number' &&
if ((typeof variablesAndClasspaths.variables[variable] === 'number' &&
value <= variablesAndClasspaths.variables[variable]) ||
(typeof variablesAndClasspaths.variables[variable] ===
'string' &&
(typeof variablesAndClasspaths.variables[variable] === 'string' &&
(0, semver_1.lt)(value, variablesAndClasspaths.variables[variable]))) {
await updateFile(config, variablesPath, replaceStart, replaceEnd, variablesAndClasspaths.variables[variable].toString(), true);
}
@ -214,16 +209,16 @@ async function migrateCommand(config, noprompt, packagemanager) {
let file = readFile(variablesPath);
if (file) {
file = file.replace('}', ` ${replaceStart}${variablesAndClasspaths.variables[variable].toString()}${replaceEnd}}`);
(0, utils_fs_1.writeFileSync)(variablesPath, file);
(0, fs_extra_1.writeFileSync)(variablesPath, file);
}
}
}
const pluginVariables = {
firebaseMessagingVersion: '23.3.1',
playServicesLocationVersion: '21.1.0',
androidxBrowserVersion: '1.7.0',
androidxMaterialVersion: '1.10.0',
androidxExifInterfaceVersion: '1.3.6',
firebaseMessagingVersion: '24.1.0',
playServicesLocationVersion: '21.3.0',
androidxBrowserVersion: '1.8.0',
androidxMaterialVersion: '1.12.0',
androidxExifInterfaceVersion: '1.3.7',
androidxCoreKTXVersion: '1.12.0',
googleMapsPlayServicesVersion: '18.2.0',
googleMapsUtilsVersion: '3.8.2',
@ -237,7 +232,7 @@ async function migrateCommand(config, noprompt, packagemanager) {
}
})();
});
rimraf_1.default.sync((0, path_1.join)(config.android.appDirAbs, 'build'));
rimraf_1.rimraf.sync((0, path_1.join)(config.android.appDirAbs, 'build'));
if (!installFailed) {
await (0, common_2.runTask)('Migrating package from Manifest to build.gradle in Capacitor plugins', () => {
return patchOldCapacitorPlugins(config);
@ -297,11 +292,11 @@ async function installLatestLibs(dependencyManager, runInstall, config) {
pkgJson['dependencies'][depKey] = pluginVersion;
}
}
(0, utils_fs_1.writeFileSync)(pkgJsonPath, JSON.stringify(pkgJson, null, 2), {
(0, fs_extra_1.writeFileSync)(pkgJsonPath, JSON.stringify(pkgJson, null, 2), {
encoding: 'utf-8',
});
if (runInstall) {
rimraf_1.default.sync((0, path_1.join)(config.app.rootDir, 'node_modules/@capacitor/!(cli)'));
rimraf_1.rimraf.sync((0, path_1.join)(config.app.rootDir, 'node_modules/@capacitor/!(cli)'));
await (0, subprocess_1.runCommand)(dependencyManager, ['install']);
if (dependencyManager == 'yarn') {
await (0, subprocess_1.runCommand)(dependencyManager, ['upgrade']);
@ -316,11 +311,11 @@ async function installLatestLibs(dependencyManager, runInstall, config) {
}
async function writeBreakingChanges() {
const breaking = [
'@capacitor/camera',
'@capacitor/filesystem',
'@capacitor/geolocation',
'@capacitor/google-maps',
'@capacitor/local-notifications',
'@capacitor/app',
'@capacitor/device',
'@capacitor/haptics',
'@capacitor/splash-screen',
'@capacitor/statusbar',
];
const broken = [];
for (const lib of breaking) {
@ -329,7 +324,7 @@ async function writeBreakingChanges() {
}
}
if (broken.length > 0) {
log_1.logger.info(`IMPORTANT: Review https://capacitorjs.com/docs/next/updating/6-0#plugins for breaking changes in these plugins that you use: ${broken.join(', ')}.`);
log_1.logger.info(`IMPORTANT: Review https://capacitorjs.com/docs/next/updating/7-0#plugins for breaking changes in these plugins that you use: ${broken.join(', ')}.`);
}
}
async function getAndroidVariablesAndClasspaths(config) {
@ -343,10 +338,8 @@ async function getAndroidVariablesAndClasspaths(config) {
(0, fs_1.deleteFolderRecursive)(tempAndroidTemplateFolder);
const firstIndxOfCATBGV = buildGradleFile.indexOf(`classpath 'com.android.tools.build:gradle:`) + 42;
const firstIndxOfCGGGS = buildGradleFile.indexOf(`com.google.gms:google-services:`) + 31;
const comAndroidToolsBuildGradleVersion = '' +
buildGradleFile.substring(firstIndxOfCATBGV, buildGradleFile.indexOf("'", firstIndxOfCATBGV));
const comGoogleGmsGoogleServices = '' +
buildGradleFile.substring(firstIndxOfCGGGS, buildGradleFile.indexOf("'", firstIndxOfCGGGS));
const comAndroidToolsBuildGradleVersion = '' + buildGradleFile.substring(firstIndxOfCATBGV, buildGradleFile.indexOf("'", firstIndxOfCATBGV));
const comGoogleGmsGoogleServices = '' + buildGradleFile.substring(firstIndxOfCGGGS, buildGradleFile.indexOf("'", firstIndxOfCGGGS));
const variablesGradleAsJSON = JSON.parse(variablesGradleFile
.replace('ext ', '')
.replace(/=/g, ':')
@ -359,18 +352,18 @@ async function getAndroidVariablesAndClasspaths(config) {
.replace(/\s/g, '')
.replace(/'/g, '"'));
return {
'variables': variablesGradleAsJSON,
variables: variablesGradleAsJSON,
'com.android.tools.build:gradle': comAndroidToolsBuildGradleVersion,
'com.google.gms:google-services': comGoogleGmsGoogleServices,
};
}
function readFile(filename) {
try {
if (!(0, utils_fs_1.existsSync)(filename)) {
if (!(0, fs_extra_1.existsSync)(filename)) {
log_1.logger.error(`Unable to find ${filename}. Try updating it manually`);
return;
}
return (0, utils_fs_1.readFileSync)(filename, 'utf-8');
return (0, fs_extra_1.readFileSync)(filename, 'utf-8');
}
catch (err) {
log_1.logger.error(`Unable to read ${filename}. Verify it is not already open. ${err}`);
@ -387,15 +380,7 @@ function getGradleWrapperVersion(filename) {
return semverVersion ? semverVersion : '0.0.0';
}
async function updateGradleWrapperFiles(platformDir) {
await (0, subprocess_1.runCommand)(`./gradlew`, [
'wrapper',
'--distribution-type',
'all',
'--gradle-version',
gradleVersion,
'--warning-mode',
'all',
], {
await (0, subprocess_1.runCommand)(`./gradlew`, ['wrapper', '--distribution-type', 'all', '--gradle-version', gradleVersion, '--warning-mode', 'all'], {
cwd: platformDir,
});
}
@ -437,8 +422,8 @@ async function movePackageFromManifestToBuildGradle(manifestFilename, buildGradl
log_1.logger.error(`Unable to update buildGradleText: no changes were detected in Android Manifest file`);
return;
}
(0, utils_fs_1.writeFileSync)(manifestFilename, manifestReplaced, 'utf-8');
(0, utils_fs_1.writeFileSync)(buildGradleFilename, buildGradleReplaced, 'utf-8');
(0, fs_extra_1.writeFileSync)(manifestFilename, manifestReplaced, 'utf-8');
(0, fs_extra_1.writeFileSync)(buildGradleFilename, buildGradleReplaced, 'utf-8');
}
async function updateBuildGradle(filename, variablesAndClasspaths) {
const txt = readFile(filename);
@ -460,7 +445,7 @@ async function updateBuildGradle(filename, variablesAndClasspaths) {
}
}
}
(0, utils_fs_1.writeFileSync)(filename, replaced, 'utf-8');
(0, fs_extra_1.writeFileSync)(filename, replaced, 'utf-8');
}
async function updateFile(config, filename, textStart, textEnd, replacement, skipIfNotFound) {
if (config === null) {
@ -474,7 +459,7 @@ async function updateFile(config, filename, textStart, textEnd, replacement, ski
if (txt.includes(textStart)) {
if (replacement) {
txt = setAllStringIn(txt, textStart, textEnd, replacement);
(0, utils_fs_1.writeFileSync)(path, txt, { encoding: 'utf-8' });
(0, fs_extra_1.writeFileSync)(path, txt, { encoding: 'utf-8' });
}
else {
// Replacing in code so we need to count the number of brackets to find the end of the function in swift
@ -497,7 +482,7 @@ async function updateFile(config, filename, textStart, textEnd, replacement, ski
replaced += line + '\n';
}
}
(0, utils_fs_1.writeFileSync)(path, replaced, { encoding: 'utf-8' });
(0, fs_extra_1.writeFileSync)(path, replaced, { encoding: 'utf-8' });
}
return true;
}
@ -518,14 +503,22 @@ function setAllStringIn(data, start, end, replacement) {
else {
const idx = foundIdx + start.length;
position = idx + replacement.length;
result =
result.substring(0, idx) +
replacement +
result.substring(result.indexOf(end, idx));
result = result.substring(0, idx) + replacement + result.substring(result.indexOf(end, idx));
}
}
return result;
}
async function updateAndroidManifest(filename) {
const txt = readFile(filename);
if (!txt) {
return;
}
if (txt.includes('navigation')) {
return; // Probably already updated
}
const replaced = txt.replace('android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode"', 'android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation"');
(0, fs_extra_1.writeFileSync)(filename, replaced, 'utf-8');
}
async function patchOldCapacitorPlugins(config) {
const allPlugins = await (0, plugin_1.getPlugins)(config, 'android');
const androidPlugins = await (0, common_1.getAndroidPlugins)(allPlugins);
@ -550,26 +543,3 @@ async function patchOldCapacitorPlugins(config) {
}));
}
exports.patchOldCapacitorPlugins = patchOldCapacitorPlugins;
async function removeKey(filename, key) {
const txt = readFile(filename);
if (!txt) {
return;
}
let lines = txt.split('\n');
let removed = false;
let removing = false;
lines = lines.filter(line => {
if (removing && line.includes('</string>')) {
removing = false;
return false;
}
if (line.includes(`<key>${key}</key`)) {
removing = true;
removed = true;
}
return !removing;
});
if (removed) {
(0, utils_fs_1.writeFileSync)(filename, lines.join('\n'), 'utf-8');
}
}

View file

@ -5,7 +5,6 @@ const tslib_1 = require("tslib");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
async function newPluginCommand() {
(0, errors_1.fatal)(`The plugin:generate command has been removed.\n` +
`Use ${colors_1.default.input('npm init @capacitor/plugin')}`);
(0, errors_1.fatal)(`The plugin:generate command has been removed.\n` + `Use ${colors_1.default.input('npm init @capacitor/plugin')}`);
}
exports.newPluginCommand = newPluginCommand;

View file

@ -41,7 +41,7 @@ async function openCommand(config, selectedPlatformName) {
}
exports.openCommand = openCommand;
function createOpenablePlatformFilter(config) {
return platform => platform === config.ios.name || platform === config.android.name;
return (platform) => platform === config.ios.name || platform === config.android.name;
}
async function open(config, platformName) {
if (platformName === config.ios.name) {

View file

@ -2,7 +2,6 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = exports.runCommand = void 0;
const tslib_1 = require("tslib");
const utils_process_1 = require("@ionic/utils-process");
const utils_terminal_1 = require("@ionic/utils-terminal");
const run_1 = require("../android/run");
const colors_1 = tslib_1.__importDefault(require("../colors"));
@ -16,8 +15,7 @@ const native_run_1 = require("../util/native-run");
const sync_1 = require("./sync");
async function runCommand(config, selectedPlatformName, options) {
var _a, _b, _c, _d;
options.host =
(_b = (_a = options.host) !== null && _a !== void 0 ? _a : livereload_1.CapLiveReloadHelper.getIpAddress()) !== null && _b !== void 0 ? _b : 'localhost';
options.host = (_b = (_a = options.host) !== null && _a !== void 0 ? _a : livereload_1.CapLiveReloadHelper.getIpAddress()) !== null && _b !== void 0 ? _b : 'localhost';
options.port = (_c = options.port) !== null && _c !== void 0 ? _c : '3000';
if (selectedPlatformName && !(await (0, common_1.isValidPlatform)(selectedPlatformName))) {
const platformDir = (0, common_1.resolvePlatform)(config, selectedPlatformName);
@ -39,7 +37,7 @@ async function runCommand(config, selectedPlatformName, options) {
}
if (options.list) {
const targets = await (0, native_run_1.getPlatformTargets)(platformName);
const outputTargets = targets.map(t => {
const outputTargets = targets.map((t) => {
var _a;
return ({
name: (0, common_1.getPlatformTargetName)(t),
@ -47,12 +45,11 @@ async function runCommand(config, selectedPlatformName, options) {
id: (_a = t.id) !== null && _a !== void 0 ? _a : '?',
});
});
// TODO: make hidden commander option (https://github.com/tj/commander.js/issues/1106)
if (process.argv.includes('--json')) {
if (options.json) {
process.stdout.write(`${JSON.stringify(outputTargets)}\n`);
}
else {
const rows = outputTargets.map(t => [t.name, t.api, t.id]);
const rows = outputTargets.map((t) => [t.name, t.api, t.id]);
log_1.output.write(`${(0, utils_terminal_1.columnar)(rows, {
headers: ['Name', 'API', 'Target ID'],
vsep: ' ',
@ -73,7 +70,7 @@ async function runCommand(config, selectedPlatformName, options) {
}
await run(config, platformName, options);
if (options.liveReload) {
new Promise(resolve => process.on('SIGINT', resolve))
new Promise((resolve) => process.on('SIGINT', resolve))
.then(async () => {
await livereload_1.CapLiveReloadHelper.revertCapConfigForLiveReload();
if (platformName === config.android.name) {
@ -82,7 +79,7 @@ async function runCommand(config, selectedPlatformName, options) {
})
.then(() => process.exit());
log_1.logger.info(`App running with live reload listing for: http://${options.host}:${options.port}. Press Ctrl+C to quit.`);
await (0, utils_process_1.sleepForever)();
await sleepForever();
}
}
catch (e) {
@ -110,5 +107,12 @@ async function run(config, platformName, options) {
}
exports.run = run;
function createRunnablePlatformFilter(config) {
return platform => platform === config.ios.name || platform === config.android.name;
return (platform) => platform === config.ios.name || platform === config.android.name;
}
async function sleepForever() {
return new Promise(() => {
setInterval(() => {
/* do nothing */
}, 1000);
});
}

View file

@ -1,25 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.inlineSourceMaps = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const log_1 = require("../log");
function walkDirectory(dirPath) {
const files = (0, utils_fs_1.readdirSync)(dirPath);
files.forEach(file => {
const files = (0, fs_extra_1.readdirSync)(dirPath);
files.forEach((file) => {
const targetFile = (0, path_1.join)(dirPath, file);
if ((0, utils_fs_1.existsSync)(targetFile) && (0, utils_fs_1.lstatSync)(targetFile).isDirectory()) {
if ((0, fs_extra_1.existsSync)(targetFile) && (0, fs_extra_1.lstatSync)(targetFile).isDirectory()) {
walkDirectory(targetFile);
}
else {
const mapFile = (0, path_1.join)(dirPath, `${file}.map`);
if ((0, path_1.extname)(file) === '.js' && (0, utils_fs_1.existsSync)(mapFile)) {
const bufMap = (0, utils_fs_1.readFileSync)(mapFile).toString('base64');
const bufFile = (0, utils_fs_1.readFileSync)(targetFile, 'utf8');
const result = bufFile.replace(`sourceMappingURL=${file}.map`, 'sourceMappingURL=data:application/json;charset=utf-8;base64,' +
bufMap);
(0, utils_fs_1.writeFileSync)(targetFile, result);
(0, utils_fs_1.unlinkSync)(mapFile);
if ((0, path_1.extname)(file) === '.js' && (0, fs_extra_1.existsSync)(mapFile)) {
const bufMap = (0, fs_extra_1.readFileSync)(mapFile).toString('base64');
const bufFile = (0, fs_extra_1.readFileSync)(targetFile, 'utf8');
const result = bufFile.replace(`sourceMappingURL=${file}.map`, 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + bufMap);
(0, fs_extra_1.writeFileSync)(targetFile, result);
(0, fs_extra_1.unlinkSync)(mapFile);
}
}
});

View file

@ -25,12 +25,8 @@ async function syncCommand(config, selectedPlatformName, deployment, inline = fa
const then = +new Date();
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
try {
await (0, common_1.check)([
() => (0, common_1.checkPackage)(),
() => (0, common_1.checkWebDir)(config),
...(0, update_1.updateChecks)(config, platforms),
]);
await (0, promise_1.allSerial)(platforms.map(platformName => () => sync(config, platformName, deployment, inline)));
await (0, common_1.check)([() => (0, common_1.checkPackage)(), () => (0, common_1.checkWebDir)(config), ...(0, update_1.updateChecks)(config, platforms)]);
await (0, promise_1.allSerial)(platforms.map((platformName) => () => sync(config, platformName, deployment, inline)));
const now = +new Date();
const diff = (now - then) / 1000;
log_1.logger.info(`Sync finished in ${diff}s`);

View file

@ -6,7 +6,8 @@ const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
const log_1 = require("../log");
const sysconfig_1 = require("../sysconfig");
const telemetry_1 = require("../telemetry");
const THANK_YOU = `\nThank you for helping to make Capacitor better! 💖` +
`\nInformation about the data we collect is available on our website: ${colors_1.default.strong('https://capacitorjs.com/docs/next/cli/telemetry')}\n`;
async function telemetryCommand(onOrOff) {
const sysconfig = await (0, sysconfig_1.readConfig)();
const enabled = interpretEnabled(onOrOff);
@ -18,7 +19,7 @@ async function telemetryCommand(onOrOff) {
await (0, sysconfig_1.writeConfig)({ ...sysconfig, telemetry: enabled });
(0, log_1.logSuccess)(`You have ${colors_1.default.strong(`opted ${enabled ? 'in' : 'out'}`)} ${enabled ? 'for' : 'of'} telemetry on this machine.`);
if (enabled) {
log_1.output.write(telemetry_1.THANK_YOU);
log_1.output.write(THANK_YOU);
}
}
}

View file

@ -26,7 +26,7 @@ async function updateCommand(config, selectedPlatformName, deployment) {
const platforms = await (0, common_1.selectPlatforms)(config, selectedPlatformName);
try {
await (0, common_1.check)([() => (0, common_1.checkPackage)(), ...updateChecks(config, platforms)]);
await (0, promise_1.allSerial)(platforms.map(platformName => async () => await update(config, platformName, deployment)));
await (0, promise_1.allSerial)(platforms.map((platformName) => async () => await update(config, platformName, deployment)));
const now = +new Date();
const diff = (now - then) / 1000;
log_1.logger.info(`Update finished in ${diff}s`);

View file

@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendMetric = exports.telemetryAction = exports.THANK_YOU = void 0;
exports.sendMetric = exports.telemetryAction = void 0;
const tslib_1 = require("tslib");
const commander_1 = require("commander");
const debug_1 = tslib_1.__importDefault(require("debug"));
@ -11,8 +11,9 @@ const sysconfig_1 = require("./sysconfig");
const subprocess_1 = require("./util/subprocess");
const term_1 = require("./util/term");
const debug = (0, debug_1.default)('capacitor:telemetry');
exports.THANK_YOU = `\nThank you for helping to make Capacitor better! 💖` +
`\nInformation about the data we collect is available on our website: ${colors_1.default.strong('https://capacitorjs.com/telemetry')}\n`;
const THANK_YOU = `\nThank you for helping improve Capacitor by sharing anonymous usage data! 💖` +
`\nInformation about the data we collect is available on our website: ${colors_1.default.strong('https://capacitorjs.com/docs/next/cli/telemetry')}` +
`\nYou can disable telemetry at any time by using the ${colors_1.default.input('npx cap telemetry off')} command.`;
function telemetryAction(config, action) {
return async (...actionArgs) => {
const start = new Date();
@ -55,9 +56,10 @@ function telemetryAction(config, action) {
if ((0, term_1.isInteractive)()) {
let sysconfig = await (0, sysconfig_1.readConfig)();
if (!error && typeof sysconfig.telemetry === 'undefined') {
const confirm = await promptForTelemetry();
sysconfig = { ...sysconfig, telemetry: confirm };
// Telemetry is opt-out; turn telemetry on then inform the user how to opt-out.
sysconfig = { ...sysconfig, telemetry: true };
await (0, sysconfig_1.writeConfig)(sysconfig);
log_1.output.write(THANK_YOU);
}
await sendMetric(sysconfig, 'capacitor_cli_command', data);
}
@ -86,19 +88,6 @@ async function sendMetric(sysconfig, name, data) {
}
}
exports.sendMetric = sendMetric;
async function promptForTelemetry() {
const { confirm } = await (0, log_1.logPrompt)(`${colors_1.default.strong('Would you like to help improve Capacitor by sharing anonymous usage data? 💖')}\n` +
`Read more about what is being collected and why here: ${colors_1.default.strong('https://capacitorjs.com/telemetry')}. You can change your mind at any time by using the ${colors_1.default.input('npx cap telemetry')} command.`, {
type: 'confirm',
name: 'confirm',
message: 'Share anonymous usage data?',
initial: true,
});
if (confirm) {
log_1.output.write(exports.THANK_YOU);
}
return confirm;
}
/**
* Get a unique anonymous identifier for this app.
*/

View file

@ -1,24 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deleteFolderRecursive = exports.convertToUnixPath = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
exports.readdirp = exports.deleteFolderRecursive = exports.convertToUnixPath = void 0;
const fs_1 = require("fs");
const promises_1 = require("fs/promises");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const convertToUnixPath = (path) => {
return path.replace(/\\/g, '/');
};
exports.convertToUnixPath = convertToUnixPath;
const deleteFolderRecursive = (directoryPath) => {
if ((0, utils_fs_1.existsSync)(directoryPath)) {
(0, utils_fs_1.readdirSync)(directoryPath).forEach(file => {
if ((0, fs_extra_1.existsSync)(directoryPath)) {
(0, fs_extra_1.readdirSync)(directoryPath).forEach((file) => {
const curPath = (0, path_1.join)(directoryPath, file);
if ((0, utils_fs_1.lstatSync)(curPath).isDirectory()) {
if ((0, fs_extra_1.lstatSync)(curPath).isDirectory()) {
(0, exports.deleteFolderRecursive)(curPath);
}
else {
(0, utils_fs_1.unlinkSync)(curPath);
(0, fs_extra_1.unlinkSync)(curPath);
}
});
(0, utils_fs_1.rmdirSync)(directoryPath);
(0, fs_extra_1.rmdirSync)(directoryPath);
}
};
exports.deleteFolderRecursive = deleteFolderRecursive;
async function readdirp(dir, { filter }) {
const dirContent = await (0, promises_1.readdir)(dir, { recursive: true });
const dirContentWalker = [];
const filteredContent = [];
dirContent.forEach((element) => {
const path = (0, path_1.join)(dir, element);
const stats = (0, fs_1.statSync)(path);
dirContentWalker.push({ path, stats });
});
dirContentWalker.forEach((element) => {
if (filter(element)) {
filteredContent.push(element.path);
}
});
return filteredContent;
}
exports.readdirp = readdirp;

View file

@ -1,17 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateIOSPackageJSON = exports.writePluginJSON = exports.findPluginClasses = exports.getPluginFiles = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const cordova_1 = require("../cordova");
const plugin_1 = require("../plugin");
const fs_1 = require("./fs");
async function getPluginFiles(plugins) {
var _a;
let filenameList = [];
const options = {
filter: item => {
if (item.stats.isFile() &&
(item.path.endsWith('.swift') || item.path.endsWith('.m'))) {
filter: (item) => {
if (item.stats.isFile() && (item.path.endsWith('.swift') || item.path.endsWith('.m'))) {
return true;
}
else {
@ -22,7 +22,7 @@ async function getPluginFiles(plugins) {
for (const plugin of plugins) {
if (plugin.ios && (0, plugin_1.getPluginType)(plugin, 'ios') === 0 /* PluginType.Core */) {
const pluginPath = (0, path_1.resolve)(plugin.rootPath, (_a = plugin.ios) === null || _a === void 0 ? void 0 : _a.path);
const filenames = await (0, utils_fs_1.readdirp)(pluginPath, options);
const filenames = await (0, fs_1.readdirp)(pluginPath, options);
filenameList = filenameList.concat(filenames);
}
}
@ -32,7 +32,7 @@ exports.getPluginFiles = getPluginFiles;
async function findPluginClasses(files) {
const classList = [];
for (const file of files) {
const fileData = (0, utils_fs_1.readFileSync)(file, 'utf-8');
const fileData = (0, fs_extra_1.readFileSync)(file, 'utf-8');
const swiftPluginRegex = RegExp(/@objc\(([A-Za-z0-9_-]+)\)/);
const objcPluginRegex = RegExp(/CAP_PLUGIN\(([A-Za-z0-9_-]+)/);
const swiftMatches = swiftPluginRegex.exec(fileData);
@ -49,9 +49,9 @@ async function findPluginClasses(files) {
exports.findPluginClasses = findPluginClasses;
async function writePluginJSON(config, classList) {
const capJSONFile = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'capacitor.config.json');
const capJSON = (0, utils_fs_1.readJSONSync)(capJSONFile);
const capJSON = (0, fs_extra_1.readJSONSync)(capJSONFile);
capJSON['packageClassList'] = classList;
(0, utils_fs_1.writeJSONSync)(capJSONFile, capJSON, { spaces: '\t' });
(0, fs_extra_1.writeJSONSync)(capJSONFile, capJSON, { spaces: '\t' });
}
exports.writePluginJSON = writePluginJSON;
async function generateIOSPackageJSON(config, plugins) {

View file

@ -1,7 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CapLiveReloadHelper = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const os_1 = require("os");
const path_1 = require("path");
class CapLiveReload {
@ -73,7 +73,7 @@ class CapLiveReload {
return res[0].address;
}
const all = Object.keys(interfaces)
.map(nic => {
.map((nic) => {
//
// Note: name will only be `public` or `private`
// when this is called.
@ -86,9 +86,7 @@ class CapLiveReload {
if (!name) {
return true;
}
return name === 'public'
? isPrivate(details.address)
: isPublic(details.address);
return name === 'public' ? isPrivate(details.address) : isPublic(details.address);
});
return addresses.length ? addresses[0].address : undefined;
})
@ -128,22 +126,21 @@ class CapLiveReload {
const capConfigPath = rootConfigChange
? config.app.extConfigFilePath
: (0, path_1.join)(platformAbsPath, 'capacitor.config.json');
const configJson = (0, utils_fs_1.readJSONSync)(capConfigPath);
const configJson = (0, fs_extra_1.readJSONSync)(capConfigPath);
this.configJsonToRevertTo.json = JSON.stringify(configJson, null, 2);
this.configJsonToRevertTo.platformPath = capConfigPath;
const url = `http://${options.host}:${options.port}`;
configJson.server = {
url,
};
(0, utils_fs_1.writeJSONSync)(capConfigPath, configJson, { spaces: '\t' });
(0, fs_extra_1.writeJSONSync)(capConfigPath, configJson, { spaces: '\t' });
}
async revertCapConfigForLiveReload() {
if (this.configJsonToRevertTo.json == null ||
this.configJsonToRevertTo.platformPath == null)
if (this.configJsonToRevertTo.json == null || this.configJsonToRevertTo.platformPath == null)
return;
const capConfigPath = this.configJsonToRevertTo.platformPath;
const configJson = this.configJsonToRevertTo.json;
(0, utils_fs_1.writeJSONSync)(capConfigPath, JSON.parse(configJson), { spaces: '\t' });
(0, fs_extra_1.writeJSONSync)(capConfigPath, JSON.parse(configJson), { spaces: '\t' });
this.configJsonToRevertTo.json = null;
this.configJsonToRevertTo.platformPath = null;
}

View file

@ -13,8 +13,7 @@ function findMonorepoRoot(currentPath) {
const packageJsonPath = (0, node_path_1.join)(currentPath, 'package.json');
const pnpmWorkspacePath = (0, node_path_1.join)(currentPath, 'pnpm-workspace.yaml');
if ((0, node_fs_1.existsSync)(pnpmWorkspacePath) ||
((0, node_fs_1.existsSync)(packageJsonPath) &&
JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8')).workspaces)) {
((0, node_fs_1.existsSync)(packageJsonPath) && JSON.parse((0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8')).workspaces)) {
return currentPath;
}
const parentPath = (0, node_path_1.dirname)(currentPath);

View file

@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const errors_1 = require("../errors");
const log_1 = require("../log");
const node_1 = require("./node");
const subprocess_1 = require("./subprocess");
async function runNativeRun(args, options = {}) {
@ -39,6 +40,10 @@ async function getPlatformTargets(platformName) {
const err = JSON.parse(e);
errors.push(err);
}
if (errors.length === 0) {
log_1.logger.info('No devices found.');
return [];
}
const plural = errors.length > 1 ? 's' : '';
const errMsg = `${colors_1.default.strong('native-run')} failed with error${plural}\n
${errors

View file

@ -1,8 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveNode = exports.requireTS = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
const fs_1 = require("fs");
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
/**
* @see https://github.com/ionic-team/stencil/blob/HEAD/src/compiler/sys/node-require.ts
@ -12,7 +12,7 @@ const requireTS = (ts, p) => {
delete require.cache[id];
require.extensions['.ts'] = (module, fileName) => {
var _a;
let sourceText = (0, utils_fs_1.readFileSync)(fileName, 'utf8');
let sourceText = (0, fs_extra_1.readFileSync)(fileName, 'utf8');
if (fileName.endsWith('.ts')) {
const tsResults = ts.transpileModule(sourceText, {
fileName,

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.lazy = exports.LazyPromise = exports.allSerial = void 0;
function allSerial(funcs) {
return funcs.reduce((promise, func) => promise.then(result => func().then(x => result.concat(x))), Promise.resolve([]));
return funcs.reduce((promise, func) => promise.then((result) => func().then((x) => result.concat(x))), Promise.resolve([]));
}
exports.allSerial = allSerial;
class LazyPromise extends Promise {

View file

@ -1,12 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generatePackageFile = exports.findPackageSwiftFile = exports.checkPackageManager = void 0;
const utils_fs_1 = require("@ionic/utils-fs");
exports.addInfoPlistDebugIfNeeded = exports.runCocoapodsDeintegrate = exports.generatePackageText = exports.removeCocoapodsFiles = exports.extractSPMPackageDirectory = exports.checkPluginsForPackageSwift = exports.generatePackageFile = exports.findPackageSwiftFile = exports.checkPackageManager = void 0;
const fs_extra_1 = require("fs-extra");
const os_1 = require("os");
const path_1 = require("path");
const plist_1 = require("plist");
const tar_1 = require("tar");
const common_1 = require("../common");
const errors_1 = require("../errors");
const common_2 = require("../ios/common");
const log_1 = require("../log");
const plugin_1 = require("../plugin");
const subprocess_1 = require("../util/subprocess");
async function checkPackageManager(config) {
const iosDirectory = config.ios.nativeProjectDirAbs;
if ((0, utils_fs_1.existsSync)((0, path_1.resolve)(iosDirectory, 'CapApp-SPM'))) {
if ((0, fs_extra_1.existsSync)((0, path_1.resolve)(iosDirectory, 'CapApp-SPM'))) {
return 'SPM';
}
return 'Cocoapods';
@ -20,20 +28,60 @@ exports.findPackageSwiftFile = findPackageSwiftFile;
async function generatePackageFile(config, plugins) {
const packageSwiftFile = await findPackageSwiftFile(config);
try {
log_1.logger.warn('SPM Support is still experimental');
const textToWrite = generatePackageText(config, plugins);
(0, utils_fs_1.writeFileSync)(packageSwiftFile, textToWrite);
log_1.logger.info('Writing Package.swift');
const textToWrite = await generatePackageText(config, plugins);
(0, fs_extra_1.writeFileSync)(packageSwiftFile, textToWrite);
}
catch (err) {
log_1.logger.error(`Unable to write to ${packageSwiftFile}. Verify it is not already open. \n Error: ${err}`);
}
}
exports.generatePackageFile = generatePackageFile;
function generatePackageText(config, plugins) {
async function checkPluginsForPackageSwift(config, plugins) {
const iOSCapacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, 'ios') === 0 /* PluginType.Core */);
const packageSwiftPluginList = await pluginsWithPackageSwift(iOSCapacitorPlugins);
if (plugins.length == packageSwiftPluginList.length) {
log_1.logger.debug(`Found ${plugins.length} iOS plugins, ${packageSwiftPluginList.length} have a Package.swift file`);
log_1.logger.info('All plugins have a Package.swift file and will be included in Package.swift');
}
else {
log_1.logger.warn('Some installed packages my not be compatable with SPM');
}
return packageSwiftPluginList;
}
exports.checkPluginsForPackageSwift = checkPluginsForPackageSwift;
async function extractSPMPackageDirectory(config) {
const spmDirectory = (0, path_1.join)(config.ios.nativeProjectDirAbs, 'CapApp-SPM');
const spmTemplate = (0, path_1.join)(config.cli.assetsDirAbs, 'ios-spm-template.tar.gz');
const debugConfig = (0, path_1.join)(config.ios.platformDirAbs, 'debug.xcconfig');
log_1.logger.info('Extracting ' + spmTemplate + ' to ' + spmDirectory);
try {
const tempCapDir = await (0, fs_extra_1.mkdtemp)((0, path_1.join)((0, os_1.tmpdir)(), 'cap-'));
const tempCapSPM = (0, path_1.join)(tempCapDir, 'App', 'CapApp-SPM');
const tempDebugXCConfig = (0, path_1.join)(tempCapDir, 'debug.xcconfig');
await (0, tar_1.extract)({ file: spmTemplate, cwd: tempCapDir });
await (0, fs_extra_1.move)(tempCapSPM, spmDirectory);
await (0, fs_extra_1.move)(tempDebugXCConfig, debugConfig);
}
catch (err) {
(0, errors_1.fatal)('Failed to create ' + spmDirectory + ' with error: ' + err);
}
}
exports.extractSPMPackageDirectory = extractSPMPackageDirectory;
async function removeCocoapodsFiles(config) {
const iosDirectory = config.ios.nativeProjectDirAbs;
const podFile = (0, path_1.resolve)(iosDirectory, 'Podfile');
const podlockFile = (0, path_1.resolve)(iosDirectory, 'Podfile.lock');
const xcworkspaceFile = (0, path_1.resolve)(iosDirectory, 'App.xcworkspace');
await (0, fs_extra_1.remove)(podFile);
await (0, fs_extra_1.remove)(podlockFile);
await (0, fs_extra_1.remove)(xcworkspaceFile);
}
exports.removeCocoapodsFiles = removeCocoapodsFiles;
async function generatePackageText(config, plugins) {
var _a, _b, _c;
const pbx = (0, utils_fs_1.readFileSync)((0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj'), 'utf-8');
const searchString = 'IPHONEOS_DEPLOYMENT_TARGET = ';
const iosVersion = pbx.substring(pbx.indexOf(searchString) + searchString.length, pbx.indexOf(searchString) + searchString.length + 2);
const iosPlatformVersion = await (0, common_1.getCapacitorPackageVersion)(config, config.ios.name);
const iosVersion = (0, common_2.getMajoriOSVersion)(config);
let packageSwiftText = `// swift-tools-version: 5.9
import PackageDescription
@ -47,10 +95,15 @@ let package = Package(
targets: ["CapApp-SPM"])
],
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", branch: "main")`;
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", exact: "${iosPlatformVersion}")`;
for (const plugin of plugins) {
const relPath = (0, path_1.relative)(config.ios.nativeXcodeProjDirAbs, plugin.rootPath);
packageSwiftText += `,\n .package(name: "${(_a = plugin.ios) === null || _a === void 0 ? void 0 : _a.name}", path: "${relPath}")`;
if ((0, plugin_1.getPluginType)(plugin, config.ios.name) === 1 /* PluginType.Cordova */) {
packageSwiftText += `,\n .package(name: "${plugin.name}", path: "../../capacitor-cordova-ios-plugins/sources/${plugin.name}")`;
}
else {
const relPath = (0, path_1.relative)(config.ios.nativeXcodeProjDirAbs, plugin.rootPath);
packageSwiftText += `,\n .package(name: "${(_a = plugin.ios) === null || _a === void 0 ? void 0 : _a.name}", path: "${relPath}")`;
}
}
packageSwiftText += `
],
@ -71,3 +124,64 @@ let package = Package(
`;
return packageSwiftText;
}
exports.generatePackageText = generatePackageText;
async function runCocoapodsDeintegrate(config) {
const podPath = await config.ios.podPath;
const projectFileName = config.ios.nativeXcodeProjDirAbs;
const useBundler = podPath.startsWith('bundle') && (await (0, subprocess_1.isInstalled)('bundle'));
const podCommandExists = await (0, subprocess_1.isInstalled)('pod');
if (useBundler)
log_1.logger.info('Found bundler, using it to run CocoaPods.');
log_1.logger.info('Running pod deintegrate on project ' + projectFileName);
if (useBundler || podCommandExists) {
if (useBundler) {
await (0, subprocess_1.runCommand)('bundle', ['exec', 'pod', 'deintegrate', projectFileName], {
cwd: config.ios.nativeProjectDirAbs,
});
}
else {
await (0, subprocess_1.runCommand)(podPath, ['deintegrate', projectFileName], {
cwd: config.ios.nativeProjectDirAbs,
});
}
}
else {
log_1.logger.warn('Skipping pod deintegrate because CocoaPods is not installed - migration will be incomplete');
}
}
exports.runCocoapodsDeintegrate = runCocoapodsDeintegrate;
async function addInfoPlistDebugIfNeeded(config) {
const infoPlist = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
log_1.logger.info('Checking ' + infoPlist + ' for CAPACITOR_DEBUG');
if ((0, fs_extra_1.existsSync)(infoPlist)) {
const infoPlistContents = (0, fs_extra_1.readFileSync)(infoPlist, 'utf-8');
const plistEntries = (0, plist_1.parse)(infoPlistContents);
if (plistEntries['CAPACITOR_DEBUG'] === undefined) {
log_1.logger.info('Writing CAPACITOR_DEBUG to ' + infoPlist);
plistEntries['CAPACITOR_DEBUG'] = '$(CAPACITOR_DEBUG)';
const plistToWrite = (0, plist_1.build)(plistEntries);
(0, fs_extra_1.writeFileSync)(infoPlist, plistToWrite);
}
else {
log_1.logger.warn('Found CAPACITOR_DEBUG set to ' + plistEntries['CAPACITOR_DEBUG'] + ', skipping.');
}
}
else {
log_1.logger.warn(infoPlist + ' not found.');
}
}
exports.addInfoPlistDebugIfNeeded = addInfoPlistDebugIfNeeded;
// Private Functions
async function pluginsWithPackageSwift(plugins) {
const pluginList = [];
for (const plugin of plugins) {
const packageSwiftFound = await (0, fs_extra_1.pathExists)((0, path_1.join)(plugin.rootPath, 'Package.swift'));
if (packageSwiftFound) {
pluginList.push(plugin);
}
else {
log_1.logger.warn(plugin.id + ' does not have a Package.swift');
}
}
return pluginList;
}

View file

@ -10,13 +10,7 @@ async function runCommand(command, args, options = {}) {
catch (e) {
if (e instanceof utils_subprocess_1.SubprocessError) {
// old behavior of just throwing the stdout/stderr strings
throw e.output
? e.output
: e.code
? e.code
: e.error
? e.error.message
: 'Unknown error';
throw e.output ? e.output : e.cause ? `${e.message} ${e.cause.toString()}` : e.code ? e.code : 'Unknown error';
}
throw e;
}

View file

@ -2,10 +2,10 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractTemplate = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const tar_1 = tslib_1.__importDefault(require("tar"));
async function extractTemplate(src, dir) {
await (0, utils_fs_1.mkdirp)(dir);
await (0, fs_extra_1.mkdirp)(dir);
await tar_1.default.extract({ file: src, cwd: dir });
}
exports.extractTemplate = extractTemplate;

View file

@ -18,7 +18,7 @@ const checkInteractive = (...args) => {
}
// Make sure none of the provided args are empty, otherwise print the interactive
// warning and return false
if (args.filter(arg => !arg).length) {
if (args.filter((arg) => !arg).length) {
log_1.logger.error(`Non-interactive shell detected.\n` +
`Run the command with ${colors_1.default.input('--help')} to see a list of arguments that must be provided.`);
return false;

View file

@ -2,7 +2,7 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.uuidv4 = void 0;
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);

View file

@ -2,12 +2,12 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildXmlElement = exports.writeXML = exports.parseXML = exports.readXML = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const fs_extra_1 = require("fs-extra");
const xml2js_1 = tslib_1.__importDefault(require("xml2js"));
async function readXML(path) {
var _a;
try {
const xmlStr = await (0, utils_fs_1.readFile)(path, { encoding: 'utf-8' });
const xmlStr = await (0, fs_extra_1.readFile)(path, { encoding: 'utf-8' });
try {
return await xml2js_1.default.parseStringPromise(xmlStr);
}
@ -21,9 +21,7 @@ async function readXML(path) {
}
exports.readXML = readXML;
function parseXML(xmlStr, options) {
const parser = options !== undefined
? new xml2js_1.default.Parser({ ...options })
: new xml2js_1.default.Parser();
const parser = options !== undefined ? new xml2js_1.default.Parser({ ...options }) : new xml2js_1.default.Parser();
let xmlObj;
parser.parseString(xmlStr, (err, result) => {
if (!err) {
@ -34,7 +32,7 @@ function parseXML(xmlStr, options) {
}
exports.parseXML = parseXML;
async function writeXML(object) {
return new Promise(resolve => {
return new Promise((resolve) => {
const builder = new xml2js_1.default.Builder({
headless: true,
explicitRoot: false,

View file

@ -1,22 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.copyWeb = void 0;
const tslib_1 = require("tslib");
const utils_fs_1 = require("@ionic/utils-fs");
const path_1 = require("path");
const colors_1 = tslib_1.__importDefault(require("../colors"));
const common_1 = require("../common");
const errors_1 = require("../errors");
const node_1 = require("../util/node");
async function copyWeb(config) {
if (config.app.bundledWebRuntime) {
const runtimePath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/core', 'dist', 'capacitor.js');
if (!runtimePath) {
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/core/dist/capacitor.js')}.\n` + `Are you sure ${colors_1.default.strong('@capacitor/core')} is installed?`);
}
return (0, common_1.runTask)(`Copying ${colors_1.default.strong('capacitor.js')} to web dir`, () => {
return (0, utils_fs_1.copy)(runtimePath, (0, path_1.join)(config.app.webDirAbs, 'capacitor.js'));
});
}
}
exports.copyWeb = copyWeb;

1
@capacitor/cli/node_modules/.bin/glob generated vendored Symbolic link
View file

@ -0,0 +1 @@
../glob/dist/esm/bin.mjs

View file

@ -1 +1 @@
../rimraf/dist/cjs/src/bin.js
../rimraf/dist/esm/bin.mjs

View file

@ -0,0 +1,185 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.1.6](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.1.5...@ionic/utils-array@2.1.6) (2023-03-29)
**Note:** Version bump only for package @ionic/utils-array
## [2.1.5](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.1.4...@ionic/utils-array@2.1.5) (2020-08-28)
**Note:** Version bump only for package @ionic/utils-array
## [2.1.4](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.1.3...@ionic/utils-array@2.1.4) (2020-08-25)
**Note:** Version bump only for package @ionic/utils-array
## [2.1.3](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.1.2...@ionic/utils-array@2.1.3) (2020-05-12)
### Bug Fixes
* pin tslib to avoid "Cannot set property pathExists" error ([689e1f0](https://github.com/ionic-team/ionic-cli/commit/689e1f038b907356ef855a067a76d4822e7072a8))
## [2.1.2](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.1.1...@ionic/utils-array@2.1.2) (2020-05-06)
**Note:** Version bump only for package @ionic/utils-array
## [2.1.1](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.1.0...@ionic/utils-array@2.1.1) (2020-03-03)
**Note:** Version bump only for package @ionic/utils-array
# 2.1.0 (2020-02-11)
### Features
* **start:** add new list starter option ([#4315](https://github.com/ionic-team/ionic-cli/issues/4315)) ([1df44c1](https://github.com/ionic-team/ionic-cli/commit/1df44c1591f37b89f2b672857740edd6cb2aea67))
## [2.0.2](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.0.1...@ionic/utils-array@2.0.2) (2020-02-10)
**Note:** Version bump only for package @ionic/utils-array
## [2.0.1](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@2.0.0...@ionic/utils-array@2.0.1) (2020-02-03)
**Note:** Version bump only for package @ionic/utils-array
# [2.0.0](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.2.2...@ionic/utils-array@2.0.0) (2020-01-25)
### chore
* require Node 10 ([5a47874](https://github.com/ionic-team/ionic-cli/commit/5a478746c074207b6dc96aa8771f04a606deb1ef))
### BREAKING CHANGES
* A minimum of Node.js 10.3.0 is required.
## [1.2.2](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.2.1...@ionic/utils-array@1.2.2) (2019-12-05)
**Note:** Version bump only for package @ionic/utils-array
## [1.2.1](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.2.0...@ionic/utils-array@1.2.1) (2019-09-18)
**Note:** Version bump only for package @ionic/utils-array
# [1.2.0](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.1.1...@ionic/utils-array@1.2.0) (2019-08-28)
### Features
* **replace:** add replace item in array by index function ([011ddf7](https://github.com/ionic-team/ionic-cli/commit/011ddf7))
* **splice:** add non-mutating splice function ([758d287](https://github.com/ionic-team/ionic-cli/commit/758d287))
## [1.1.1](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.1.0...@ionic/utils-array@1.1.1) (2019-08-23)
**Note:** Version bump only for package @ionic/utils-array
# [1.1.0](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.0.2...@ionic/utils-array@1.1.0) (2019-08-14)
### Features
* add new `move` function ([ba8da3b](https://github.com/ionic-team/ionic-cli/commit/ba8da3b))
## [1.0.2](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.0.1...@ionic/utils-array@1.0.2) (2019-08-07)
**Note:** Version bump only for package @ionic/utils-array
## [1.0.1](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@1.0.0...@ionic/utils-array@1.0.1) (2019-06-05)
**Note:** Version bump only for package @ionic/utils-array
# [1.0.0](https://github.com/ionic-team/ionic-cli/compare/@ionic/utils-array@0.0.1...@ionic/utils-array@1.0.0) (2019-05-29)
### chore
* require Node 8 ([5670e68](https://github.com/ionic-team/ionic-cli/commit/5670e68))
### BREAKING CHANGES
* A minimum of Node.js 8.9.4 is required.
<a name="0.0.1"></a>
## 0.0.1 (2019-02-27)
**Note:** Version bump only for package @ionic/utils-array

21
@capacitor/cli/node_modules/@ionic/utils-array/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Drifty Co
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1 @@
# @ionic/utils-array

View file

@ -0,0 +1,39 @@
export declare function conform<T>(t?: T | T[]): T[];
export declare function concurrentFilter<T>(array: T[], callback: (currentValue: T) => Promise<boolean>): Promise<T[]>;
export declare function filter<T>(array: T[], callback: (currentValue: T, currentIndex: number, array: readonly T[]) => Promise<boolean>): Promise<T[]>;
export declare function filter<T>(array: readonly T[], callback: (currentValue: T, currentIndex: number, array: readonly T[]) => Promise<boolean>): Promise<readonly T[]>;
export declare function map<T, U>(array: T[], callback: (currentValue: T, currentIndex: number, array: readonly T[]) => Promise<U>): Promise<U[]>;
export declare function map<T, U>(array: T[], callback: (currentValue: T, currentIndex: number, array: readonly T[]) => Promise<U>): Promise<readonly U[]>;
export declare function map<T, U>(array: readonly T[], callback: (currentValue: T, currentIndex: number, array: readonly T[]) => Promise<U>): Promise<U[]>;
export declare function map<T, U>(array: readonly T[], callback: (currentValue: T, currentIndex: number, array: readonly T[]) => Promise<U>): Promise<readonly U[]>;
export declare function reduce<T>(array: T[], callback: (accumulator: T, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<T>): Promise<T>;
export declare function reduce<T>(array: T[], callback: (accumulator: T, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<T>, initialValue: T): Promise<T>;
export declare function reduce<T, R>(array: T[], callback: (accumulator: R, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<R>): Promise<R>;
export declare function reduce<T, U>(array: T[], callback: (accumulator: U, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<U>, initialValue: U): Promise<U>;
export declare function reduce<T>(array: readonly T[], callback: (accumulator: T, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<T>): Promise<T>;
export declare function reduce<T>(array: readonly T[], callback: (accumulator: T, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<T>, initialValue: T): Promise<T>;
export declare function reduce<T, R>(array: readonly T[], callback: (accumulator: R, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<R>): Promise<R>;
export declare function reduce<T, U>(array: readonly T[], callback: (accumulator: U, currentValue: T, currentIndex: number, array: readonly T[]) => Promise<U>, initialValue: U): Promise<U>;
/**
* Splice an array.
*
* This function will return a new array with the standard splice behavior
* applied. Unlike the standard array splice, the array of removed items is not
* returned.
*/
export declare function splice<T>(array: readonly T[], start: number, deleteCount?: number, ...items: T[]): T[];
/**
* Move an item in an array by index.
*
* This function will return a new array with the item in the `fromIndex`
* position moved to the `toIndex` position. If `fromIndex` or `toIndex` are
* out of bounds, the array items remain unmoved.
*/
export declare function move<T>(array: readonly T[], fromIndex: number, toIndex: number): T[];
/**
* Replace an item in an array by index.
*
* This function will return a new array with the item in the `index` position
* replaced with `item`. If `index` is out of bounds, the item is not replaced.
*/
export declare function replace<T>(array: readonly T[], index: number, item: T): T[];

View file

@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.replace = exports.move = exports.splice = exports.reduce = exports.map = exports.filter = exports.concurrentFilter = exports.conform = void 0;
function conform(t) {
if (typeof t === 'undefined') {
return [];
}
if (!Array.isArray(t)) {
return [t];
}
return t;
}
exports.conform = conform;
async function concurrentFilter(array, callback) {
const mapper = async (v) => [v, await callback(v)];
const mapped = await Promise.all(array.map(mapper));
return mapped
.filter(([, f]) => f)
.map(([v]) => v);
}
exports.concurrentFilter = concurrentFilter;
async function filter(array, callback) {
const initial = [];
return reduce(array, async (acc, v, i, arr) => {
if (await callback(v, i, arr)) {
acc.push(v);
}
return acc;
}, initial);
}
exports.filter = filter;
async function map(array, callback) {
const initial = [];
return reduce(array, async (acc, v, i, arr) => {
acc.push(await callback(v, i, arr));
return acc;
}, initial);
}
exports.map = map;
async function reduce(array, callback, initialValue) {
const hadInitialValue = typeof initialValue === 'undefined';
const startingIndex = hadInitialValue ? 1 : 0;
if (typeof initialValue === 'undefined') {
if (array.length === 0) {
throw new TypeError('Reduce of empty array with no initial value');
}
initialValue = array[0];
}
let value = initialValue;
for (let i = startingIndex; i < array.length; i++) {
const v = await callback(value, array[i], i, array);
value = v;
}
return value;
}
exports.reduce = reduce;
/**
* Splice an array.
*
* This function will return a new array with the standard splice behavior
* applied. Unlike the standard array splice, the array of removed items is not
* returned.
*/
function splice(array, start, deleteCount = array.length - start, ...items) {
const result = [...array];
result.splice(start, deleteCount, ...items);
return result;
}
exports.splice = splice;
/**
* Move an item in an array by index.
*
* This function will return a new array with the item in the `fromIndex`
* position moved to the `toIndex` position. If `fromIndex` or `toIndex` are
* out of bounds, the array items remain unmoved.
*/
function move(array, fromIndex, toIndex) {
const element = array[fromIndex];
if (fromIndex < 0 || toIndex < 0 || fromIndex >= array.length || toIndex >= array.length) {
return [...array];
}
return splice(splice(array, fromIndex, 1), toIndex, 0, element);
}
exports.move = move;
/**
* Replace an item in an array by index.
*
* This function will return a new array with the item in the `index` position
* replaced with `item`. If `index` is out of bounds, the item is not replaced.
*/
function replace(array, index, item) {
if (index < 0 || index > array.length) {
return [...array];
}
return splice(array, index, 1, item);
}
exports.replace = replace;

View file

@ -0,0 +1,49 @@
{
"name": "@ionic/utils-array",
"version": "2.1.6",
"description": "Array utils",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"homepage": "https://ionicframework.com/",
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
"license": "MIT",
"engines": {
"node": ">=16.0.0"
},
"files": [
"dist/",
"LICENSE",
"README.md"
],
"repository": {
"type": "git",
"url": "https://github.com/ionic-team/ionic-cli.git"
},
"bugs": {
"url": "https://github.com/ionic-team/ionic-cli/issues"
},
"scripts": {
"clean": "rimraf dist",
"lint": "true",
"build": "npm run clean && tsc",
"watch": "tsc -w --preserveWatchOutput",
"test": "jest --maxWorkers=4",
"prepublishOnly": "npm run build"
},
"dependencies": {
"debug": "^4.0.0",
"tslib": "^2.0.1"
},
"devDependencies": {
"@types/debug": "^4.1.1",
"@types/jest": "^26.0.10",
"@types/node": "~16.0.0",
"jest": "^26.4.2",
"jest-cli": "^26.0.1",
"lint-staged": "^10.0.2",
"rimraf": "^3.0.0",
"ts-jest": "~26.3.0",
"typescript": "~4.8.0"
},
"gitHead": "15ef6e7da4eace4fd55d16fd9508d156a4bc8203"
}

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Drifty Co
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1 @@
# @ionic/utils-stream

View file

@ -0,0 +1,39 @@
/// <reference types="node" />
/// <reference types="node" />
import { Readable, ReadableOptions, Writable, WritableOptions } from 'stream';
export declare class NullStream extends Writable {
_write(chunk: any, encoding: string, callback: () => void): void;
}
export interface ReadableStreamBufferOptions extends ReadableOptions {
chunkSize?: number;
allocSize?: number;
growSize?: number;
}
export declare class ReadableStreamBuffer extends Readable {
protected buffer: Buffer;
protected _size: number;
protected _stopped: boolean;
protected chunkSize: number;
protected growSize: number;
constructor(opts?: ReadableStreamBufferOptions);
get size(): number;
get stopped(): boolean;
_read(): void;
feed(data: Buffer | string, encoding?: BufferEncoding): void;
stop(): void;
protected _send(): void;
}
export interface WritableStreamBufferOptions extends WritableOptions {
allocSize?: number;
growSize?: number;
}
export declare class WritableStreamBuffer extends Writable {
protected buffer: Buffer;
protected _size: number;
protected growSize: number;
constructor(opts?: WritableStreamBufferOptions);
get size(): number;
_write(chunk: any, encoding: string, callback: () => void): void;
consume(bytes?: number): Buffer;
}
export declare function growBufferForAppendedData(buf: Buffer, actualsize: number, appendsize: number): Buffer;

View file

@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.growBufferForAppendedData = exports.WritableStreamBuffer = exports.ReadableStreamBuffer = exports.NullStream = void 0;
const stream_1 = require("stream");
const DEFAULT_CHUNK_SIZE = 4;
const DEFAULT_ALLOC_SIZE = 32;
const DEFAULT_GROW_SIZE = 16;
class NullStream extends stream_1.Writable {
_write(chunk, encoding, callback) {
callback();
}
}
exports.NullStream = NullStream;
class ReadableStreamBuffer extends stream_1.Readable {
constructor(opts) {
super(opts);
this._size = 0;
this._stopped = false;
this.buffer = Buffer.alloc(opts && opts.allocSize ? opts.allocSize : DEFAULT_ALLOC_SIZE);
this.chunkSize = opts && opts.chunkSize ? opts.chunkSize : DEFAULT_CHUNK_SIZE;
this.growSize = opts && opts.growSize ? opts.growSize : DEFAULT_GROW_SIZE;
}
get size() {
return this._size;
}
get stopped() {
return this._stopped;
}
_read() {
this._send();
}
feed(data, encoding = 'utf8') {
if (this._stopped) {
throw new Error('ReadableStreamBuffer is stopped. Can no longer feed.');
}
const datasize = typeof data === 'string' ? Buffer.byteLength(data) : data.length;
this.buffer = growBufferForAppendedData(this.buffer, this._size, Math.ceil(datasize / this.growSize) * this.growSize);
if (typeof data === 'string') {
this.buffer.write(data, this._size, datasize, encoding);
}
else {
this.buffer.copy(data, this._size, 0);
}
this._size += datasize;
}
stop() {
if (this._stopped) {
return;
}
this._stopped = true;
if (this._size === 0) {
this.push(null);
}
}
_send() {
const chunkSize = Math.min(this.chunkSize, this._size);
let done = false;
if (chunkSize > 0) {
const chunk = Buffer.alloc(chunkSize);
this.buffer.copy(chunk, 0, 0, chunkSize);
done = !this.push(chunk);
this.buffer.copy(this.buffer, 0, chunkSize, this._size);
this._size -= chunkSize;
}
if (this._size === 0 && this._stopped) {
this.push(null);
}
if (!done) {
setTimeout(() => this._send(), 1);
}
}
}
exports.ReadableStreamBuffer = ReadableStreamBuffer;
class WritableStreamBuffer extends stream_1.Writable {
constructor(opts) {
super(opts);
this._size = 0;
this.buffer = Buffer.alloc(opts && opts.allocSize ? opts.allocSize : DEFAULT_ALLOC_SIZE);
this.growSize = opts && opts.growSize ? opts.growSize : DEFAULT_GROW_SIZE;
}
get size() {
return this._size;
}
_write(chunk, encoding, callback) {
this.buffer = growBufferForAppendedData(this.buffer, this._size, Math.ceil(chunk.length / this.growSize) * this.growSize);
chunk.copy(this.buffer, this._size, 0);
this._size += chunk.length;
callback();
}
consume(bytes) {
bytes = typeof bytes === 'number' ? bytes : this._size;
const data = Buffer.alloc(bytes);
this.buffer.copy(data, 0, 0, data.length);
this.buffer.copy(this.buffer, 0, data.length);
this._size -= data.length;
return data;
}
}
exports.WritableStreamBuffer = WritableStreamBuffer;
function growBufferForAppendedData(buf, actualsize, appendsize) {
if ((buf.length - actualsize) >= appendsize) {
return buf;
}
const newbuffer = Buffer.alloc(buf.length + appendsize);
buf.copy(newbuffer, 0, 0, actualsize);
return newbuffer;
}
exports.growBufferForAppendedData = growBufferForAppendedData;

View file

@ -0,0 +1,49 @@
{
"name": "@ionic/utils-stream",
"version": "3.1.7",
"description": "Stream utils for NodeJS",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"homepage": "https://ionicframework.com/",
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
"license": "MIT",
"engines": {
"node": ">=16.0.0"
},
"files": [
"dist/",
"LICENSE",
"README.md"
],
"repository": {
"type": "git",
"url": "https://github.com/ionic-team/ionic-cli.git"
},
"bugs": {
"url": "https://github.com/ionic-team/ionic-cli/issues"
},
"scripts": {
"clean": "rimraf dist",
"lint": "true",
"build": "npm run clean && tsc",
"watch": "tsc -w --preserveWatchOutput",
"test": "jest --maxWorkers=4",
"prepublishOnly": "npm run build"
},
"dependencies": {
"debug": "^4.0.0",
"tslib": "^2.0.1"
},
"devDependencies": {
"@types/debug": "^4.1.1",
"@types/jest": "^26.0.10",
"@types/node": "~16.0.0",
"jest": "^26.4.2",
"jest-cli": "^26.0.1",
"lint-staged": "^10.0.2",
"rimraf": "^3.0.0",
"stream-combiner2": "^1.1.1",
"ts-jest": "~26.3.0",
"typescript": "~4.8.0"
}
}

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Drifty Co
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Some files were not shown because too many files have changed in this diff Show more