@capacitor/core
Version:
Capacitor: Cross-platform apps with JavaScript and the web
411 lines (403 loc) • 17.4 kB
JavaScript
/*! Capacitor: https://capacitorjs.com/ - MIT License */
const createCapacitorPlatforms = (win) => {
const defaultPlatformMap = new Map();
defaultPlatformMap.set('web', { name: 'web' });
const capPlatforms = win.CapacitorPlatforms || {
currentPlatform: { name: 'web' },
platforms: defaultPlatformMap,
};
const addPlatform = (name, platform) => {
capPlatforms.platforms.set(name, platform);
};
const setPlatform = (name) => {
if (capPlatforms.platforms.has(name)) {
capPlatforms.currentPlatform = capPlatforms.platforms.get(name);
}
};
capPlatforms.addPlatform = addPlatform;
capPlatforms.setPlatform = setPlatform;
return capPlatforms;
};
const initPlatforms = (win) => (win.CapacitorPlatforms = createCapacitorPlatforms(win));
/**
* @deprecated Set `CapacitorCustomPlatform` on the window object prior to runtime executing in the web app instead
*/
const CapacitorPlatforms = /*#__PURE__*/ initPlatforms((typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: {}));
/**
* @deprecated Set `CapacitorCustomPlatform` on the window object prior to runtime executing in the web app instead
*/
const addPlatform = CapacitorPlatforms.addPlatform;
/**
* @deprecated Set `CapacitorCustomPlatform` on the window object prior to runtime executing in the web app instead
*/
const setPlatform = CapacitorPlatforms.setPlatform;
const legacyRegisterWebPlugin = (cap, webPlugin) => {
var _a;
const config = webPlugin.config;
const Plugins = cap.Plugins;
if (!config || !config.name) {
// TODO: add link to upgrade guide
throw new Error(`Capacitor WebPlugin is using the deprecated "registerWebPlugin()" function, but without the config. Please use "registerPlugin()" instead to register this web plugin."`);
}
// TODO: add link to upgrade guide
console.warn(`Capacitor plugin "${config.name}" is using the deprecated "registerWebPlugin()" function`);
if (!Plugins[config.name] || ((_a = config === null || config === void 0 ? void 0 : config.platforms) === null || _a === void 0 ? void 0 : _a.includes(cap.getPlatform()))) {
// Add the web plugin into the plugins registry if there already isn't
// an existing one. If it doesn't already exist, that means
// there's no existing native implementation for it.
// - OR -
// If we already have a plugin registered (meaning it was defined in the native layer),
// then we should only overwrite it if the corresponding web plugin activates on
// a certain platform. For example: Geolocation uses the WebPlugin on Android but not iOS
Plugins[config.name] = webPlugin;
}
};
var ExceptionCode;
(function (ExceptionCode) {
/**
* API is not implemented.
*
* This usually means the API can't be used because it is not implemented for
* the current platform.
*/
ExceptionCode["Unimplemented"] = "UNIMPLEMENTED";
/**
* API is not available.
*
* This means the API can't be used right now because:
* - it is currently missing a prerequisite, such as network connectivity
* - it requires a particular platform or browser version
*/
ExceptionCode["Unavailable"] = "UNAVAILABLE";
})(ExceptionCode || (ExceptionCode = {}));
class CapacitorException extends Error {
constructor(message, code) {
super(message);
this.message = message;
this.code = code;
}
}
const getPlatformId = (win) => {
var _a, _b;
if (win === null || win === void 0 ? void 0 : win.androidBridge) {
return 'android';
}
else if ((_b = (_a = win === null || win === void 0 ? void 0 : win.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) {
return 'ios';
}
else {
return 'web';
}
};
const createCapacitor = (win) => {
var _a, _b, _c, _d, _e;
const capCustomPlatform = win.CapacitorCustomPlatform || null;
const cap = win.Capacitor || {};
const Plugins = (cap.Plugins = cap.Plugins || {});
/**
* @deprecated Use `capCustomPlatform` instead, default functions like registerPlugin will function with the new object.
*/
const capPlatforms = win.CapacitorPlatforms;
const defaultGetPlatform = () => {
return capCustomPlatform !== null
? capCustomPlatform.name
: getPlatformId(win);
};
const getPlatform = ((_a = capPlatforms === null || capPlatforms === void 0 ? void 0 : capPlatforms.currentPlatform) === null || _a === void 0 ? void 0 : _a.getPlatform) || defaultGetPlatform;
const defaultIsNativePlatform = () => getPlatform() !== 'web';
const isNativePlatform = ((_b = capPlatforms === null || capPlatforms === void 0 ? void 0 : capPlatforms.currentPlatform) === null || _b === void 0 ? void 0 : _b.isNativePlatform) || defaultIsNativePlatform;
const defaultIsPluginAvailable = (pluginName) => {
const plugin = registeredPlugins.get(pluginName);
if (plugin === null || plugin === void 0 ? void 0 : plugin.platforms.has(getPlatform())) {
// JS implementation available for the current platform.
return true;
}
if (getPluginHeader(pluginName)) {
// Native implementation available.
return true;
}
return false;
};
const isPluginAvailable = ((_c = capPlatforms === null || capPlatforms === void 0 ? void 0 : capPlatforms.currentPlatform) === null || _c === void 0 ? void 0 : _c.isPluginAvailable) ||
defaultIsPluginAvailable;
const defaultGetPluginHeader = (pluginName) => { var _a; return (_a = cap.PluginHeaders) === null || _a === void 0 ? void 0 : _a.find(h => h.name === pluginName); };
const getPluginHeader = ((_d = capPlatforms === null || capPlatforms === void 0 ? void 0 : capPlatforms.currentPlatform) === null || _d === void 0 ? void 0 : _d.getPluginHeader) || defaultGetPluginHeader;
const handleError = (err) => win.console.error(err);
const pluginMethodNoop = (_target, prop, pluginName) => {
return Promise.reject(`${pluginName} does not have an implementation of "${prop}".`);
};
const registeredPlugins = new Map();
const defaultRegisterPlugin = (pluginName, jsImplementations = {}) => {
const registeredPlugin = registeredPlugins.get(pluginName);
if (registeredPlugin) {
console.warn(`Capacitor plugin "${pluginName}" already registered. Cannot register plugins twice.`);
return registeredPlugin.proxy;
}
const platform = getPlatform();
const pluginHeader = getPluginHeader(pluginName);
let jsImplementation;
const loadPluginImplementation = async () => {
if (!jsImplementation && platform in jsImplementations) {
jsImplementation =
typeof jsImplementations[platform] === 'function'
? (jsImplementation = await jsImplementations[platform]())
: (jsImplementation = jsImplementations[platform]);
}
else if (capCustomPlatform !== null &&
!jsImplementation &&
'web' in jsImplementations) {
jsImplementation =
typeof jsImplementations['web'] === 'function'
? (jsImplementation = await jsImplementations['web']())
: (jsImplementation = jsImplementations['web']);
}
return jsImplementation;
};
const createPluginMethod = (impl, prop) => {
var _a, _b;
if (pluginHeader) {
const methodHeader = pluginHeader === null || pluginHeader === void 0 ? void 0 : pluginHeader.methods.find(m => prop === m.name);
if (methodHeader) {
if (methodHeader.rtype === 'promise') {
return (options) => cap.nativePromise(pluginName, prop.toString(), options);
}
else {
return (options, callback) => cap.nativeCallback(pluginName, prop.toString(), options, callback);
}
}
else if (impl) {
return (_a = impl[prop]) === null || _a === void 0 ? void 0 : _a.bind(impl);
}
}
else if (impl) {
return (_b = impl[prop]) === null || _b === void 0 ? void 0 : _b.bind(impl);
}
else {
throw new CapacitorException(`"${pluginName}" plugin is not implemented on ${platform}`, ExceptionCode.Unimplemented);
}
};
const createPluginMethodWrapper = (prop) => {
let remove;
const wrapper = (...args) => {
const p = loadPluginImplementation().then(impl => {
const fn = createPluginMethod(impl, prop);
if (fn) {
const p = fn(...args);
remove = p === null || p === void 0 ? void 0 : p.remove;
return p;
}
else {
throw new CapacitorException(`"${pluginName}.${prop}()" is not implemented on ${platform}`, ExceptionCode.Unimplemented);
}
});
if (prop === 'addListener') {
p.remove = async () => remove();
}
return p;
};
// Some flair ✨
wrapper.toString = () => `${prop.toString()}() { [capacitor code] }`;
Object.defineProperty(wrapper, 'name', {
value: prop,
writable: false,
configurable: false,
});
return wrapper;
};
const addListener = createPluginMethodWrapper('addListener');
const removeListener = createPluginMethodWrapper('removeListener');
const addListenerNative = (eventName, callback) => {
const call = addListener({ eventName }, callback);
const remove = async () => {
const callbackId = await call;
removeListener({
eventName,
callbackId,
}, callback);
};
const p = new Promise(resolve => call.then(() => resolve({ remove })));
p.remove = async () => {
console.warn(`Using addListener() without 'await' is deprecated.`);
await remove();
};
return p;
};
const proxy = new Proxy({}, {
get(_, prop) {
switch (prop) {
// https://github.com/facebook/react/issues/20030
case '$$typeof':
return undefined;
case 'toJSON':
return () => ({});
case 'addListener':
return pluginHeader ? addListenerNative : addListener;
case 'removeListener':
return removeListener;
default:
return createPluginMethodWrapper(prop);
}
},
});
Plugins[pluginName] = proxy;
registeredPlugins.set(pluginName, {
name: pluginName,
proxy,
platforms: new Set([
...Object.keys(jsImplementations),
...(pluginHeader ? [platform] : []),
]),
});
return proxy;
};
const registerPlugin = ((_e = capPlatforms === null || capPlatforms === void 0 ? void 0 : capPlatforms.currentPlatform) === null || _e === void 0 ? void 0 : _e.registerPlugin) || defaultRegisterPlugin;
// Add in convertFileSrc for web, it will already be available in native context
if (!cap.convertFileSrc) {
cap.convertFileSrc = filePath => filePath;
}
cap.getPlatform = getPlatform;
cap.handleError = handleError;
cap.isNativePlatform = isNativePlatform;
cap.isPluginAvailable = isPluginAvailable;
cap.pluginMethodNoop = pluginMethodNoop;
cap.registerPlugin = registerPlugin;
cap.Exception = CapacitorException;
cap.DEBUG = !!cap.DEBUG;
cap.isLoggingEnabled = !!cap.isLoggingEnabled;
// Deprecated props
cap.platform = cap.getPlatform();
cap.isNative = cap.isNativePlatform();
return cap;
};
const initCapacitorGlobal = (win) => (win.Capacitor = createCapacitor(win));
const Capacitor = /*#__PURE__*/ initCapacitorGlobal(typeof globalThis !== 'undefined'
? globalThis
: typeof self !== 'undefined'
? self
: typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: {});
const registerPlugin = Capacitor.registerPlugin;
/**
* @deprecated Provided for backwards compatibility for Capacitor v2 plugins.
* Capacitor v3 plugins should import the plugin directly. This "Plugins"
* export is deprecated in v3, and will be removed in v4.
*/
const Plugins = Capacitor.Plugins;
/**
* Provided for backwards compatibility. Use the registerPlugin() API
* instead, and provide the web plugin as the "web" implmenetation.
* For example
*
* export const Example = registerPlugin('Example', {
* web: () => import('./web').then(m => new m.Example())
* })
*
* @deprecated Deprecated in v3, will be removed from v4.
*/
const registerWebPlugin = (plugin) => legacyRegisterWebPlugin(Capacitor, plugin);
/**
* Base class web plugins should extend.
*/
class WebPlugin {
constructor(config) {
this.listeners = {};
this.windowListeners = {};
if (config) {
// TODO: add link to upgrade guide
console.warn(`Capacitor WebPlugin "${config.name}" config object was deprecated in v3 and will be removed in v4.`);
this.config = config;
}
}
addListener(eventName, listenerFunc) {
const listeners = this.listeners[eventName];
if (!listeners) {
this.listeners[eventName] = [];
}
this.listeners[eventName].push(listenerFunc);
// If we haven't added a window listener for this event and it requires one,
// go ahead and add it
const windowListener = this.windowListeners[eventName];
if (windowListener && !windowListener.registered) {
this.addWindowListener(windowListener);
}
const remove = async () => this.removeListener(eventName, listenerFunc);
const p = Promise.resolve({ remove });
Object.defineProperty(p, 'remove', {
value: async () => {
console.warn(`Using addListener() without 'await' is deprecated.`);
await remove();
},
});
return p;
}
async removeAllListeners() {
this.listeners = {};
for (const listener in this.windowListeners) {
this.removeWindowListener(this.windowListeners[listener]);
}
this.windowListeners = {};
}
notifyListeners(eventName, data) {
const listeners = this.listeners[eventName];
if (listeners) {
listeners.forEach(listener => listener(data));
}
}
hasListeners(eventName) {
return !!this.listeners[eventName].length;
}
registerWindowListener(windowEventName, pluginEventName) {
this.windowListeners[pluginEventName] = {
registered: false,
windowEventName,
pluginEventName,
handler: event => {
this.notifyListeners(pluginEventName, event);
},
};
}
unimplemented(msg = 'not implemented') {
return new Capacitor.Exception(msg, ExceptionCode.Unimplemented);
}
unavailable(msg = 'not available') {
return new Capacitor.Exception(msg, ExceptionCode.Unavailable);
}
async removeListener(eventName, listenerFunc) {
const listeners = this.listeners[eventName];
if (!listeners) {
return;
}
const index = listeners.indexOf(listenerFunc);
this.listeners[eventName].splice(index, 1);
// If there are no more listeners for this type of event,
// remove the window listener
if (!this.listeners[eventName].length) {
this.removeWindowListener(this.windowListeners[eventName]);
}
}
addWindowListener(handle) {
window.addEventListener(handle.windowEventName, handle.handler);
handle.registered = true;
}
removeWindowListener(handle) {
if (!handle) {
return;
}
window.removeEventListener(handle.windowEventName, handle.handler);
handle.registered = false;
}
}
const WebView = /*#__PURE__*/ registerPlugin('WebView');
export { Capacitor, CapacitorException, CapacitorPlatforms, ExceptionCode, Plugins, WebPlugin, WebView, addPlatform, registerPlugin, registerWebPlugin, setPlatform };
//# sourceMappingURL=index.js.map