Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: unified errors and error codes #3673

Merged
merged 14 commits into from
Oct 19, 2020
Merged
14 changes: 10 additions & 4 deletions android/capacitor/src/main/java/com/getcapacitor/PluginCall.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ public class PluginCall {
* in the case of an app resuming with saved instance data, for example.
*/
public static final String CALLBACK_ID_DANGLING = "-1";
private static final String UNIMPLEMENTED = "not implemented";
private static final String UNAVAILABLE = "not available";

private final MessageHandler msgHandler;
private final String pluginId;
Expand Down Expand Up @@ -148,11 +146,19 @@ public void reject(String msg) {
}

public void unimplemented() {
reject(UNIMPLEMENTED, null, null);
unimplemented("not implemented");
}

public void unimplemented(String msg) {
reject(msg, "UNIMPLEMENTED", null);
}

public void unavailable() {
reject(UNAVAILABLE, null, null);
unavailable("not available");
}

public void unavailable(String msg) {
reject(msg, "UNAVAILABLE", null);
}

public String getPluginId() {
Expand Down
11 changes: 10 additions & 1 deletion core/native-bridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
// Add any legacy handlers to keep Cordova compat 100% good
addLegacyHandlers(win);

capacitor.Exception = function CapacitorException(message, code) {
var e = Error.call(this, message);
e.code = code;

return e;
};

capacitor.Exception.prototype = Error.prototype;

capacitor.Plugins = capacitor.Plugins || {};

capacitor.DEBUG =
Expand Down Expand Up @@ -241,7 +250,7 @@
result.error = Object.keys(result.error).reduce(function (err, key) {
err[key] = result.error[key];
return err;
}, new Error());
}, new capacitor.Exception());
}

if (typeof storedCall.callback === 'function') {
Expand Down
29 changes: 29 additions & 0 deletions core/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,36 @@ export interface PluginConfig {
name: string;
}

export enum ExceptionCode {
/**
* API is not implemented.
*
* This usually means the API can't be used because it is not implemented for
* the current platform.
*/
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
*/
Unavailable = 'UNAVAILABLE',
}

export interface CapacitorException extends Error {
code?: ExceptionCode;
}

declare const CapacitorException: {
prototype: CapacitorException;
new (message: string, code?: ExceptionCode): CapacitorException;
};

export interface Capacitor {
Exception: typeof CapacitorException;
isNative?: boolean;
platform?: string;
isPluginAvailable: (name: string) => boolean;
Expand Down
1 change: 1 addition & 0 deletions core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export {
ExceptionCode,
PluginCallback,
PluginListenerHandle,
PluginResultData,
Expand Down
20 changes: 0 additions & 20 deletions core/src/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,6 @@
import { Capacitor, Plugins } from './global';
import type { WebPlugin } from './web';

export enum ExceptionCodes {
UnsupportedBrowser = 'UNSUPPORTED_BROWSER',
}

export class Exception extends Error {
readonly code: ExceptionCodes;
}

/**
* Feature unavailable for the current browser (or all browsers).
*
* This error is thrown when the requested API is not supported in the browser.
*
* This can happen particularly for the web platform when implementation is
* uncertain due to the plethora of browsers available to end users.
*/
export class UnsupportedBrowserException extends Exception {
code = ExceptionCodes.UnsupportedBrowser;
}

const PLUGIN_REGISTRY = new (class {
protected readonly plugins: {
[plugin: string]: RegisteredPlugin<unknown>;
Expand Down
11 changes: 9 additions & 2 deletions core/src/web-runtime.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import type { PluginRegistry } from './definitions';
import type { Capacitor, PluginRegistry, ExceptionCode } from './definitions';

export class CapacitorWeb {
class CapacitorException extends Error {
constructor(readonly message: string, readonly code: ExceptionCode) {
super(message);
}
}

export class CapacitorWeb implements Capacitor {
Exception = CapacitorException;
Plugins: PluginRegistry;
platform = 'web';
isNative = false;
Expand Down
10 changes: 10 additions & 0 deletions core/src/web/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type {
CapacitorException,
PluginListenerHandle,
PermissionsRequestResult,
} from '../definitions';
import { ExceptionCode } from '../definitions';
import { Capacitor } from '../global';

export type ListenerCallback = (err: any, ...args: any[]) => void;
Expand Down Expand Up @@ -35,6 +37,14 @@ export class WebPlugin {

constructor(public config: WebPluginConfig) {}

protected unimplemented(msg = 'not implemented'): CapacitorException {
return new Capacitor.Exception(msg, ExceptionCode.Unimplemented);
}

protected unavailable(msg = 'not available'): CapacitorException {
return new Capacitor.Exception(msg, ExceptionCode.Unavailable);
}

private addWindowListener(handle: WindowListenerHandle): void {
window.addEventListener(handle.windowEventName, handle.handler);
handle.registered = true;
Expand Down
16 changes: 13 additions & 3 deletions ios/Capacitor/Capacitor/CAPPluginCall.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ public typealias PluginEventListener = CAPPluginCall
*/
@objc public extension CAPPluginCall {

private static let UNIMPLEMENTED = "not implemented"

@nonobjc func get<T>(_ key: String, _ ofType: T.Type, _ defaultValue: T? = nil) -> T? {
return self.options[key] as? T ?? defaultValue
}
Expand Down Expand Up @@ -90,6 +88,18 @@ public typealias PluginEventListener = CAPPluginCall
}

func unimplemented() {
errorHandler(CAPPluginCallError(message: CAPPluginCall.UNIMPLEMENTED, code: nil, error: nil, data: [:]))
unimplemented("not implemented")
}

func unimplemented(_ message: String) {
errorHandler(CAPPluginCallError(message: message, code: "UNIMPLEMENTED", error: nil, data: [:]))
}

func unavailable() {
unavailable("not available")
}

func unavailable(_ message: String) {
errorHandler(CAPPluginCallError(message: message, code: "UNAVAILABLE", error: nil, data: [:]))
}
}