@capacitor-plus/ios 8.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Capacitor/Capacitor/AppUUID.swift +51 -0
- package/Capacitor/Capacitor/Array+Capacitor.swift +31 -0
- package/Capacitor/Capacitor/CAPApplicationDelegateProxy.swift +32 -0
- package/Capacitor/Capacitor/CAPBridge.swift +25 -0
- package/Capacitor/Capacitor/CAPBridgeDelegate.swift +6 -0
- package/Capacitor/Capacitor/CAPBridgeProtocol.swift +148 -0
- package/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.h +6 -0
- package/Capacitor/Capacitor/CAPBridgeViewController+CDVScreenOrientationDelegate.m +5 -0
- package/Capacitor/Capacitor/CAPBridgeViewController.swift +384 -0
- package/Capacitor/Capacitor/CAPBridgedJSTypes.h +18 -0
- package/Capacitor/Capacitor/CAPBridgedJSTypes.m +43 -0
- package/Capacitor/Capacitor/CAPBridgedPlugin+getMethod.swift +13 -0
- package/Capacitor/Capacitor/CAPBridgedPlugin.h +41 -0
- package/Capacitor/Capacitor/CAPFile.swift +14 -0
- package/Capacitor/Capacitor/CAPInstanceConfiguration.h +38 -0
- package/Capacitor/Capacitor/CAPInstanceConfiguration.m +93 -0
- package/Capacitor/Capacitor/CAPInstanceConfiguration.swift +78 -0
- package/Capacitor/Capacitor/CAPInstanceDescriptor.h +167 -0
- package/Capacitor/Capacitor/CAPInstanceDescriptor.m +56 -0
- package/Capacitor/Capacitor/CAPInstanceDescriptor.swift +198 -0
- package/Capacitor/Capacitor/CAPInstancePlugin.swift +10 -0
- package/Capacitor/Capacitor/CAPLog.swift +11 -0
- package/Capacitor/Capacitor/CAPNotifications.swift +69 -0
- package/Capacitor/Capacitor/CAPPlugin+LoadInstance.swift +20 -0
- package/Capacitor/Capacitor/CAPPlugin.h +60 -0
- package/Capacitor/Capacitor/CAPPlugin.m +180 -0
- package/Capacitor/Capacitor/CAPPluginCall.h +25 -0
- package/Capacitor/Capacitor/CAPPluginCall.m +36 -0
- package/Capacitor/Capacitor/CAPPluginCall.swift +97 -0
- package/Capacitor/Capacitor/CAPPluginMethod.h +36 -0
- package/Capacitor/Capacitor/CAPPluginMethod.m +44 -0
- package/Capacitor/Capacitor/CAPPluginMethod.swift +17 -0
- package/Capacitor/Capacitor/Capacitor.h +15 -0
- package/Capacitor/Capacitor/Capacitor.modulemap +8 -0
- package/Capacitor/Capacitor/CapacitorBridge.swift +768 -0
- package/Capacitor/Capacitor/CapacitorExtension.swift +24 -0
- package/Capacitor/Capacitor/Codable/JSValueDecoder.swift +479 -0
- package/Capacitor/Capacitor/Codable/JSValueEncoder.swift +671 -0
- package/Capacitor/Capacitor/Data+Capacitor.swift +22 -0
- package/Capacitor/Capacitor/DocLinks.swift +8 -0
- package/Capacitor/Capacitor/Info.plist +24 -0
- package/Capacitor/Capacitor/JS.swift +122 -0
- package/Capacitor/Capacitor/JSExport.swift +218 -0
- package/Capacitor/Capacitor/JSTypes.swift +254 -0
- package/Capacitor/Capacitor/KeyPath.swift +60 -0
- package/Capacitor/Capacitor/KeyValueStore.swift +303 -0
- package/Capacitor/Capacitor/NotificationHandlerProtocol.swift +6 -0
- package/Capacitor/Capacitor/NotificationRouter.swift +60 -0
- package/Capacitor/Capacitor/PluginCallResult.swift +106 -0
- package/Capacitor/Capacitor/PluginConfig.swift +56 -0
- package/Capacitor/Capacitor/Plugins/CapacitorCookieManager.swift +141 -0
- package/Capacitor/Capacitor/Plugins/CapacitorCookies.swift +57 -0
- package/Capacitor/Capacitor/Plugins/CapacitorHttp.swift +57 -0
- package/Capacitor/Capacitor/Plugins/CapacitorUrlRequest.swift +225 -0
- package/Capacitor/Capacitor/Plugins/Console.swift +16 -0
- package/Capacitor/Capacitor/Plugins/HttpRequestHandler.swift +236 -0
- package/Capacitor/Capacitor/Plugins/SystemBars.swift +133 -0
- package/Capacitor/Capacitor/Plugins/WebView.swift +44 -0
- package/Capacitor/Capacitor/PrivacyInfo.xcprivacy +14 -0
- package/Capacitor/Capacitor/Router.swift +29 -0
- package/Capacitor/Capacitor/TmpViewController.swift +8 -0
- package/Capacitor/Capacitor/UIColor.swift +55 -0
- package/Capacitor/Capacitor/UIStatusBarManager+CAPHandleTapAction.m +37 -0
- package/Capacitor/Capacitor/WKWebView+Capacitor.m +15 -0
- package/Capacitor/Capacitor/WKWebView+Capacitor.swift +80 -0
- package/Capacitor/Capacitor/WebViewAssetHandler.swift +550 -0
- package/Capacitor/Capacitor/WebViewDelegationHandler.swift +361 -0
- package/Capacitor/Capacitor/assets/native-bridge.js +1029 -0
- package/Capacitor.podspec +23 -0
- package/CapacitorCordova/CapacitorCordova/CapacitorCordova.h +25 -0
- package/CapacitorCordova/CapacitorCordova/CapacitorCordova.modulemap +6 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.h +8 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/AppDelegate.m +5 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDV.h +28 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailability.h +109 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVAvailabilityDeprecated.h +21 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegate.h +49 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.h +39 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVCommandDelegateImpl.m +149 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.h +31 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVConfigParser.m +81 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.h +52 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVInvokedUrlCommand.m +116 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.h +39 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin+Resources.m +38 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.h +76 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPlugin.m +136 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.h +25 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginManager.m +77 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.h +82 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVPluginResult.m +216 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVScreenOrientationDelegate.h +33 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.h +27 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVURLProtocol.m +74 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.h +30 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVViewController.m +37 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.h +34 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/CDVWebViewProcessPoolFactory.m +55 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.h +35 -0
- package/CapacitorCordova/CapacitorCordova/Classes/Public/NSDictionary+CordovaPreferences.m +63 -0
- package/CapacitorCordova/CapacitorCordova/Info.plist +26 -0
- package/CapacitorCordova/CapacitorCordova/PrivacyInfo.xcprivacy +14 -0
- package/CapacitorCordova.podspec +26 -0
- package/LICENSE +21 -0
- package/package.json +33 -0
- package/scripts/pods_helpers.rb +12 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleExecutable</key>
|
|
8
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
9
|
+
<key>CFBundleIdentifier</key>
|
|
10
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
11
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
12
|
+
<string>6.0</string>
|
|
13
|
+
<key>CFBundleName</key>
|
|
14
|
+
<string>$(PRODUCT_NAME)</string>
|
|
15
|
+
<key>CFBundlePackageType</key>
|
|
16
|
+
<string>FMWK</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>$(CURRENT_PROJECT_VERSION)</string>
|
|
21
|
+
<key>NSPrincipalClass</key>
|
|
22
|
+
<string></string>
|
|
23
|
+
</dict>
|
|
24
|
+
</plist>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public class JSDate {
|
|
4
|
+
@available(*, deprecated, message: "No longer needed. Dates will be mapped to strings during serialization.")
|
|
5
|
+
static func toString(_ date: Date) -> String {
|
|
6
|
+
let formatter = ISO8601DateFormatter()
|
|
7
|
+
return formatter.string(from: date)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@available(*, deprecated, renamed: "PluginCallResultData")
|
|
12
|
+
public typealias JSResultBody = [String: Any]
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A call originating from JavaScript land
|
|
16
|
+
*/
|
|
17
|
+
internal struct JSCall {
|
|
18
|
+
let options: [String: Any]
|
|
19
|
+
let pluginId: String
|
|
20
|
+
let method: String
|
|
21
|
+
let callbackId: String
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
internal protocol JSResultProtocol {
|
|
25
|
+
var call: JSCall { get }
|
|
26
|
+
var callbackID: String { get }
|
|
27
|
+
var pluginID: String { get }
|
|
28
|
+
var methodName: String { get }
|
|
29
|
+
func jsonPayload() -> String
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
internal extension JSResultProtocol {
|
|
33
|
+
var callbackID: String {
|
|
34
|
+
return call.callbackId
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
var pluginID: String {
|
|
38
|
+
return call.pluginId
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var methodName: String {
|
|
42
|
+
return call.method
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private enum SerializationResult: String {
|
|
47
|
+
case undefined = "undefined"
|
|
48
|
+
case empty = "{}"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A result of processing a JSCall, contains
|
|
53
|
+
* a reference to the original call and the new result.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
internal struct JSResult: JSResultProtocol {
|
|
57
|
+
let call: JSCall
|
|
58
|
+
let result: PluginCallResult?
|
|
59
|
+
|
|
60
|
+
func jsonPayload() -> String {
|
|
61
|
+
guard let result = result else {
|
|
62
|
+
return SerializationResult.undefined.rawValue
|
|
63
|
+
}
|
|
64
|
+
do {
|
|
65
|
+
if let payload = try result.jsonRepresentation() {
|
|
66
|
+
return payload
|
|
67
|
+
}
|
|
68
|
+
} catch PluginCallResult.SerializationError.invalidObject {
|
|
69
|
+
CAPLog.print("[Capacitor Plugin Error] - \(call.pluginId) - \(call.method) - Unable to serialize plugin response as JSON." +
|
|
70
|
+
"Ensure that all data passed to success callback from module method is JSON serializable!")
|
|
71
|
+
} catch {
|
|
72
|
+
CAPLog.print("Unable to serialize plugin response as JSON: \(error.localizedDescription)")
|
|
73
|
+
}
|
|
74
|
+
return SerializationResult.empty.rawValue
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
internal extension JSResult {
|
|
79
|
+
init(call: JSCall, callResult: CAPPluginCallResult) {
|
|
80
|
+
self.call = call
|
|
81
|
+
self.result = callResult.resultData
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
internal struct JSResultError: JSResultProtocol {
|
|
86
|
+
let call: JSCall
|
|
87
|
+
let errorMessage: String
|
|
88
|
+
let errorDescription: String
|
|
89
|
+
let errorCode: String?
|
|
90
|
+
let result: PluginCallResult
|
|
91
|
+
|
|
92
|
+
func jsonPayload() -> String {
|
|
93
|
+
var errorDictionary: [String: Any] = [
|
|
94
|
+
"message": self.errorMessage,
|
|
95
|
+
"errorMessage": self.errorMessage
|
|
96
|
+
]
|
|
97
|
+
errorDictionary["code"] = self.errorCode
|
|
98
|
+
|
|
99
|
+
do {
|
|
100
|
+
if let payload = try result.jsonRepresentation(includingFields: errorDictionary) {
|
|
101
|
+
CAPLog.print("ERROR MESSAGE: ", payload.prefix(512))
|
|
102
|
+
return payload
|
|
103
|
+
}
|
|
104
|
+
} catch PluginCallResult.SerializationError.invalidObject {
|
|
105
|
+
CAPLog.print("[Capacitor Plugin Error] - \(call.pluginId) - \(call.method) - Unable to serialize plugin response as JSON." +
|
|
106
|
+
"Ensure that all data passed to success callback from module method is JSON serializable!")
|
|
107
|
+
} catch {
|
|
108
|
+
CAPLog.print("Unable to serialize plugin response as JSON: \(error.localizedDescription)")
|
|
109
|
+
}
|
|
110
|
+
return SerializationResult.empty.rawValue
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
internal extension JSResultError {
|
|
115
|
+
init(call: JSCall, callError: CAPPluginCallError) {
|
|
116
|
+
self.call = call
|
|
117
|
+
errorMessage = callError.message
|
|
118
|
+
errorDescription = callError.error?.localizedDescription ?? ""
|
|
119
|
+
errorCode = callError.code
|
|
120
|
+
result = callError.resultData ?? .dictionary([:])
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
internal struct PluginHeaderMethod: Codable {
|
|
2
|
+
let name: String
|
|
3
|
+
let rtype: String?
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
internal struct PluginHeader: Codable {
|
|
7
|
+
let name: String
|
|
8
|
+
let methods: [PluginHeaderMethod]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
JSExport handles defining JS APIs that map to registered plugins and are responsible for proxying calls to our bridge.
|
|
13
|
+
*/
|
|
14
|
+
internal class JSExport {
|
|
15
|
+
static let catchallOptionsParameter = "_options"
|
|
16
|
+
static let callbackParameter = "_callback"
|
|
17
|
+
|
|
18
|
+
static func exportCapacitorGlobalJS(userContentController: WKUserContentController, isDebug: Bool, loggingEnabled: Bool, localUrl: String) throws {
|
|
19
|
+
let data = "window.Capacitor = { DEBUG: \(isDebug), isLoggingEnabled: \(loggingEnabled), Plugins: {} }; window.WEBVIEW_SERVER_URL = '\(localUrl)';"
|
|
20
|
+
let userScript = WKUserScript(source: data, injectionTime: .atDocumentStart, forMainFrameOnly: true)
|
|
21
|
+
userContentController.addUserScript(userScript)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static func exportBridgeJS(userContentController: WKUserContentController) throws {
|
|
25
|
+
let capBundle = Bundle(for: Self.self)
|
|
26
|
+
guard let jsUrl = capBundle.url(forResource: "native-bridge", withExtension: "js") else {
|
|
27
|
+
CAPLog.print("ERROR: Required native-bridge.js file in Capacitor not found. Bridge will not function!")
|
|
28
|
+
throw CapacitorBridgeError.errorExportingCoreJS
|
|
29
|
+
}
|
|
30
|
+
do {
|
|
31
|
+
try self.injectFile(fileURL: jsUrl, userContentController: userContentController)
|
|
32
|
+
} catch {
|
|
33
|
+
CAPLog.print("ERROR: Unable to read required native-bridge.js file from the Capacitor framework. Bridge will not function!")
|
|
34
|
+
throw CapacitorBridgeError.errorExportingCoreJS
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static func exportCordovaJS(userContentController: WKUserContentController) throws {
|
|
39
|
+
guard let cordovaUrl = Bundle.main.url(forResource: "public/cordova", withExtension: "js") else {
|
|
40
|
+
CAPLog.print("ERROR: Required cordova.js file not found. Cordova plugins will not function!")
|
|
41
|
+
throw CapacitorBridgeError.errorExportingCoreJS
|
|
42
|
+
}
|
|
43
|
+
guard let cordovaPluginsUrl = Bundle.main.url(forResource: "public/cordova_plugins", withExtension: "js") else {
|
|
44
|
+
CAPLog.print("ERROR: Required cordova_plugins.js file not found. Cordova plugins will not function!")
|
|
45
|
+
throw CapacitorBridgeError.errorExportingCoreJS
|
|
46
|
+
}
|
|
47
|
+
do {
|
|
48
|
+
try self.injectFile(fileURL: cordovaUrl, userContentController: userContentController)
|
|
49
|
+
try self.injectFile(fileURL: cordovaPluginsUrl, userContentController: userContentController)
|
|
50
|
+
} catch {
|
|
51
|
+
CAPLog.print("ERROR: Unable to read required cordova files. Cordova plugins will not function!")
|
|
52
|
+
throw CapacitorBridgeError.errorExportingCoreJS
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static func exportMiscFileJS(paths: [String], userContentController: WKUserContentController) {
|
|
57
|
+
for path in paths {
|
|
58
|
+
if let miscJSFilePath = Bundle.main.url(forResource: "public/\(path.replacingOccurrences(of: ".js", with: ""))", withExtension: "js") {
|
|
59
|
+
do {
|
|
60
|
+
try self.injectFile(fileURL: miscJSFilePath, userContentController: userContentController)
|
|
61
|
+
} catch {
|
|
62
|
+
CAPLog.print("WARNING: Unable to inject js from path \(miscJSFilePath)")
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
CAPLog.print("WARNING: Unable to inject js from path \(path)")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
Export the JS required to implement the given plugin.
|
|
72
|
+
*/
|
|
73
|
+
static func exportJS(for plugin: CapacitorPlugin, in userContentController: WKUserContentController) {
|
|
74
|
+
var lines = [String]()
|
|
75
|
+
|
|
76
|
+
lines.append("""
|
|
77
|
+
(function(w) {
|
|
78
|
+
var a = (w.Capacitor = w.Capacitor || {});
|
|
79
|
+
var p = (a.Plugins = a.Plugins || {});
|
|
80
|
+
var t = (p['\(plugin.jsName)'] = {});
|
|
81
|
+
t.addListener = function(eventName, callback) {
|
|
82
|
+
return w.Capacitor.addListener('\(plugin.jsName)', eventName, callback);
|
|
83
|
+
}
|
|
84
|
+
t.removeAllListeners = function() {
|
|
85
|
+
return w.Capacitor.nativePromise('\(plugin.jsName)', 'removeAllListeners');
|
|
86
|
+
}
|
|
87
|
+
""")
|
|
88
|
+
|
|
89
|
+
for method in plugin.pluginMethods {
|
|
90
|
+
lines.append(generateMethod(pluginClassName: plugin.jsName, method: method))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
lines.append("""
|
|
94
|
+
})(window);
|
|
95
|
+
""")
|
|
96
|
+
if let data = try? JSONEncoder().encode(createPluginHeader(for: plugin)),
|
|
97
|
+
let header = String(data: data, encoding: .utf8) {
|
|
98
|
+
lines.append("""
|
|
99
|
+
(function(w) {
|
|
100
|
+
var a = (w.Capacitor = w.Capacitor || {});
|
|
101
|
+
var h = (a.PluginHeaders = a.PluginHeaders || []);
|
|
102
|
+
h.push(\(header));
|
|
103
|
+
})(window);
|
|
104
|
+
""")
|
|
105
|
+
}
|
|
106
|
+
let js = lines.joined(separator: "\n")
|
|
107
|
+
let userScript = WKUserScript(source: js, injectionTime: .atDocumentStart, forMainFrameOnly: true)
|
|
108
|
+
userContentController.addUserScript(userScript)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private static func createPluginHeader(for plugin: CapacitorPlugin) -> PluginHeader? {
|
|
112
|
+
let methods = [
|
|
113
|
+
PluginHeaderMethod(name: "addListener", rtype: nil),
|
|
114
|
+
PluginHeaderMethod(name: "removeListener", rtype: nil),
|
|
115
|
+
PluginHeaderMethod(name: "removeAllListeners", rtype: "promise"),
|
|
116
|
+
PluginHeaderMethod(name: "checkPermissions", rtype: "promise"),
|
|
117
|
+
PluginHeaderMethod(name: "requestPermissions", rtype: "promise")
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
return PluginHeader(
|
|
121
|
+
name: plugin.jsName,
|
|
122
|
+
methods: methods + plugin.pluginMethods.map(createPluginHeaderMethod)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private static func createPluginHeaderMethod(method: CAPPluginMethod) -> PluginHeaderMethod {
|
|
128
|
+
var rtype = method.returnType
|
|
129
|
+
if rtype == "none" {
|
|
130
|
+
rtype = nil
|
|
131
|
+
}
|
|
132
|
+
return PluginHeaderMethod(name: method.name, rtype: rtype)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private static func generateMethod(pluginClassName: String, method: CAPPluginMethod) -> String {
|
|
136
|
+
let methodName = method.name!
|
|
137
|
+
let returnType = method.returnType!
|
|
138
|
+
var paramList = [String]()
|
|
139
|
+
|
|
140
|
+
// add the catch-all
|
|
141
|
+
// options argument which takes a full object and converts each
|
|
142
|
+
// key/value pair into an option for plugin call.
|
|
143
|
+
paramList.append(catchallOptionsParameter)
|
|
144
|
+
|
|
145
|
+
// Automatically add the _callback param if returning data through a callback
|
|
146
|
+
if returnType == CAPPluginReturnCallback {
|
|
147
|
+
paramList.append(callbackParameter)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Create a param string of the form "param1, param2, param3"
|
|
151
|
+
let paramString = paramList.joined(separator: ", ")
|
|
152
|
+
|
|
153
|
+
// Generate the argument object that will be sent on each call
|
|
154
|
+
let argObjectString = catchallOptionsParameter
|
|
155
|
+
|
|
156
|
+
var lines = [String]()
|
|
157
|
+
|
|
158
|
+
// Create the function declaration
|
|
159
|
+
lines.append("t['\(method.name!)'] = function(\(paramString)) {")
|
|
160
|
+
|
|
161
|
+
// Create the call to Capacitor ...
|
|
162
|
+
if returnType == CAPPluginReturnNone {
|
|
163
|
+
// ...using none
|
|
164
|
+
lines.append("""
|
|
165
|
+
return w.Capacitor.nativeCallback('\(pluginClassName)', '\(methodName)', \(argObjectString));
|
|
166
|
+
""")
|
|
167
|
+
} else if returnType == CAPPluginReturnPromise {
|
|
168
|
+
|
|
169
|
+
// ...using a promise
|
|
170
|
+
lines.append("""
|
|
171
|
+
return w.Capacitor.nativePromise('\(pluginClassName)', '\(methodName)', \(argObjectString));
|
|
172
|
+
""")
|
|
173
|
+
} else if returnType == CAPPluginReturnCallback {
|
|
174
|
+
// ...using a callback
|
|
175
|
+
lines.append("""
|
|
176
|
+
return w.Capacitor.nativeCallback('\(pluginClassName)', '\(methodName)', \(argObjectString), \(callbackParameter));
|
|
177
|
+
""")
|
|
178
|
+
} else {
|
|
179
|
+
CAPLog.print("Error: plugin method return type \(returnType) is not supported!")
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Close the function
|
|
183
|
+
lines.append("}")
|
|
184
|
+
return lines.joined(separator: "\n")
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static func exportCordovaPluginsJS(userContentController: WKUserContentController) throws {
|
|
188
|
+
if let pluginsJSFolder = Bundle.main.url(forResource: "public/plugins", withExtension: nil) {
|
|
189
|
+
self.injectFilesForFolder(folder: pluginsJSFolder, userContentController: userContentController)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
static func injectFilesForFolder(folder: URL, userContentController: WKUserContentController) {
|
|
194
|
+
let fileManager = FileManager.default
|
|
195
|
+
do {
|
|
196
|
+
let fileURLs = try fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil, options: [])
|
|
197
|
+
for fileURL in fileURLs {
|
|
198
|
+
if fileURL.hasDirectoryPath {
|
|
199
|
+
injectFilesForFolder(folder: fileURL, userContentController: userContentController)
|
|
200
|
+
} else {
|
|
201
|
+
try self.injectFile(fileURL: fileURL, userContentController: userContentController)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
} catch {
|
|
205
|
+
CAPLog.print("Error while enumerating files")
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static func injectFile(fileURL: URL, userContentController: WKUserContentController) throws {
|
|
210
|
+
do {
|
|
211
|
+
let data = try String(contentsOf: fileURL, encoding: .utf8)
|
|
212
|
+
let userScript = WKUserScript(source: data, injectionTime: .atDocumentStart, forMainFrameOnly: true)
|
|
213
|
+
userContentController.addUserScript(userScript)
|
|
214
|
+
} catch {
|
|
215
|
+
CAPLog.print("Unable to inject js file")
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
// declare our empty protocol, and conformance, for typing
|
|
4
|
+
public protocol JSValue {}
|
|
5
|
+
extension String: JSValue {}
|
|
6
|
+
extension Bool: JSValue {}
|
|
7
|
+
extension Int: JSValue {}
|
|
8
|
+
extension Float: JSValue {}
|
|
9
|
+
extension Double: JSValue {}
|
|
10
|
+
extension NSNumber: JSValue {}
|
|
11
|
+
extension NSNull: JSValue {}
|
|
12
|
+
extension Array: JSValue {}
|
|
13
|
+
extension Date: JSValue {}
|
|
14
|
+
extension Dictionary: JSValue where Key == String, Value == JSValue {}
|
|
15
|
+
|
|
16
|
+
// convenience aliases
|
|
17
|
+
public typealias JSObject = [String: JSValue]
|
|
18
|
+
public typealias JSArray = [JSValue]
|
|
19
|
+
|
|
20
|
+
// string types
|
|
21
|
+
public protocol JSStringContainer {
|
|
22
|
+
func getString(_ key: String, _ defaultValue: String) -> String
|
|
23
|
+
func getString(_ key: String) -> String?
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
extension JSStringContainer {
|
|
27
|
+
public func getString(_ key: String, _ defaultValue: String) -> String {
|
|
28
|
+
return getString(key) ?? defaultValue
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// boolean types
|
|
33
|
+
public protocol JSBoolContainer {
|
|
34
|
+
func getBool(_ key: String, _ defaultValue: Bool) -> Bool
|
|
35
|
+
func getBool(_ key: String) -> Bool?
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
extension JSBoolContainer {
|
|
39
|
+
public func getBool(_ key: String, _ defaultValue: Bool) -> Bool {
|
|
40
|
+
return getBool(key) ?? defaultValue
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// integer types
|
|
45
|
+
public protocol JSIntContainer {
|
|
46
|
+
func getInt(_ key: String, _ defaultValue: Int) -> Int
|
|
47
|
+
func getInt(_ key: String) -> Int?
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
extension JSIntContainer {
|
|
51
|
+
public func getInt(_ key: String, _ defaultValue: Int) -> Int {
|
|
52
|
+
return getInt(key) ?? defaultValue
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// float types
|
|
57
|
+
public protocol JSFloatContainer {
|
|
58
|
+
func getFloat(_ key: String, _ defaultValue: Float) -> Float
|
|
59
|
+
func getFloat(_ key: String) -> Float?
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
extension JSFloatContainer {
|
|
63
|
+
public func getFloat(_ key: String, _ defaultValue: Float) -> Float {
|
|
64
|
+
return getFloat(key) ?? defaultValue
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// double types
|
|
69
|
+
public protocol JSDoubleContainer {
|
|
70
|
+
func getDouble(_ key: String, _ defaultValue: Double) -> Double
|
|
71
|
+
func getDouble(_ key: String) -> Double?
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
extension JSDoubleContainer {
|
|
75
|
+
public func getDouble(_ key: String, _ defaultValue: Double) -> Double {
|
|
76
|
+
return getDouble(key) ?? defaultValue
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// date types
|
|
81
|
+
public protocol JSDateContainer {
|
|
82
|
+
func getDate(_ key: String, _ defaultValue: Date) -> Date
|
|
83
|
+
func getDate(_ key: String) -> Date?
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
extension JSDateContainer {
|
|
87
|
+
public func getDate(_ key: String, _ defaultValue: Date) -> Date {
|
|
88
|
+
return getDate(key) ?? defaultValue
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// array types
|
|
93
|
+
public protocol JSArrayContainer {
|
|
94
|
+
func getArray(_ key: String, _ defaultValue: JSArray) -> JSArray
|
|
95
|
+
func getArray<T>(_ key: String, _ ofType: T.Type) -> [T]?
|
|
96
|
+
func getArray(_ key: String) -> JSArray?
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
extension JSArrayContainer {
|
|
100
|
+
public func getArray(_ key: String, _ defaultValue: JSArray) -> JSArray {
|
|
101
|
+
return getArray(key) ?? defaultValue
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public func getArray<T>(_ key: String, _ ofType: T.Type) -> [T]? {
|
|
105
|
+
return getArray(key) as? [T]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// dictionary types
|
|
110
|
+
public protocol JSObjectContainer {
|
|
111
|
+
func getObject(_ key: String, _ defaultValue: JSObject) -> JSObject
|
|
112
|
+
func getObject(_ key: String) -> JSObject?
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
extension JSObjectContainer {
|
|
116
|
+
public func getObject(_ key: String, _ defaultValue: JSObject) -> JSObject {
|
|
117
|
+
return getObject(key) ?? defaultValue
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public protocol JSValueContainer: JSStringContainer, JSBoolContainer, JSIntContainer, JSFloatContainer,
|
|
122
|
+
JSDoubleContainer, JSDateContainer, JSArrayContainer, JSObjectContainer {
|
|
123
|
+
static var jsDateFormatter: ISO8601DateFormatter { get }
|
|
124
|
+
var jsObjectRepresentation: JSObject { get }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
extension JSValueContainer {
|
|
128
|
+
public func getValue(_ key: String) -> JSValue? {
|
|
129
|
+
return jsObjectRepresentation[key]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@available(*, message: "All values returned conform to JSValue, use getValue(_:) instead.", renamed: "getValue(_:)")
|
|
133
|
+
public func getAny(_ key: String) -> Any? {
|
|
134
|
+
return getValue(key)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public func getString(_ key: String) -> String? {
|
|
138
|
+
return jsObjectRepresentation[key] as? String
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public func getBool(_ key: String) -> Bool? {
|
|
142
|
+
return jsObjectRepresentation[key] as? Bool
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public func getInt(_ key: String) -> Int? {
|
|
146
|
+
return jsObjectRepresentation[key] as? Int
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public func getFloat(_ key: String) -> Float? {
|
|
150
|
+
if let floatValue = jsObjectRepresentation[key] as? Float {
|
|
151
|
+
return floatValue
|
|
152
|
+
} else if let doubleValue = jsObjectRepresentation[key] as? Double {
|
|
153
|
+
return Float(doubleValue)
|
|
154
|
+
}
|
|
155
|
+
return nil
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public func getDouble(_ key: String) -> Double? {
|
|
159
|
+
return jsObjectRepresentation[key] as? Double
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public func getDate(_ key: String) -> Date? {
|
|
163
|
+
if let isoString = jsObjectRepresentation[key] as? String {
|
|
164
|
+
return Self.jsDateFormatter.date(from: isoString)
|
|
165
|
+
}
|
|
166
|
+
return jsObjectRepresentation[key] as? Date
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public func getArray(_ key: String) -> JSArray? {
|
|
170
|
+
return jsObjectRepresentation[key] as? JSArray
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public func getObject(_ key: String) -> JSObject? {
|
|
174
|
+
return jsObjectRepresentation[key] as? JSObject
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/// Decodes a value of the given type for the given key.
|
|
178
|
+
/// - Parameters:
|
|
179
|
+
/// - type: The type of the value to decode.
|
|
180
|
+
/// - key: The key that the decoded value is associated with.
|
|
181
|
+
/// - decoder: The decoder to use to decode the value. Defaults to `JSValueDecoder()`.
|
|
182
|
+
/// - Returns: A value of the requested type, if present for the given key and convertible to the requested type.
|
|
183
|
+
/// - Throws: `DecodingError` if the encountered encoded value is corrupted.
|
|
184
|
+
public func decode<T: Decodable>(_ type: T.Type, for key: String, with decoder: JSValueDecoder = JSValueDecoder()) throws -> T {
|
|
185
|
+
try decoder.decode(type, from: jsObjectRepresentation[key] ?? [:])
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@objc protocol BridgedJSValueContainer: NSObjectProtocol {
|
|
190
|
+
static var jsDateFormatter: ISO8601DateFormatter { get }
|
|
191
|
+
var dictionaryRepresentation: NSDictionary { get }
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/*
|
|
195
|
+
Simply casting objects from foundation class clusters (such as __NSArrayM)
|
|
196
|
+
doesn't work with the JSValue protocol and will always fail. So we need to
|
|
197
|
+
recursively and explicitly convert each value in the dictionary.
|
|
198
|
+
*/
|
|
199
|
+
public enum JSTypes {}
|
|
200
|
+
extension JSTypes {
|
|
201
|
+
public static func coerceDictionaryToJSObject(_ dictionary: NSDictionary?, formattingDatesAsStrings: Bool = false) -> JSObject? {
|
|
202
|
+
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public static func coerceDictionaryToJSObject(_ dictionary: [AnyHashable: Any]?, formattingDatesAsStrings: Bool = false) -> JSObject? {
|
|
206
|
+
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public static func coerceArrayToJSArray(_ array: [Any]?, formattingDatesAsStrings: Bool = false) -> JSArray? {
|
|
210
|
+
return array?.compactMap { coerceToJSValue($0, formattingDates: formattingDatesAsStrings) }
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private let dateStringFormatter = ISO8601DateFormatter()
|
|
215
|
+
|
|
216
|
+
// We need a large switch statement because we have a lot of types.
|
|
217
|
+
// swiftlint:disable:next cyclomatic_complexity
|
|
218
|
+
private func coerceToJSValue(_ value: Any?, formattingDates: Bool) -> JSValue? {
|
|
219
|
+
guard let value = value else {
|
|
220
|
+
return nil
|
|
221
|
+
}
|
|
222
|
+
switch value {
|
|
223
|
+
case let stringValue as String:
|
|
224
|
+
return stringValue
|
|
225
|
+
case let numberValue as NSNumber:
|
|
226
|
+
return numberValue
|
|
227
|
+
case let boolValue as Bool:
|
|
228
|
+
return boolValue
|
|
229
|
+
case let intValue as Int:
|
|
230
|
+
return intValue
|
|
231
|
+
case let floatValue as Float:
|
|
232
|
+
return floatValue
|
|
233
|
+
case let doubleValue as Double:
|
|
234
|
+
return doubleValue
|
|
235
|
+
case let dateValue as Date:
|
|
236
|
+
if formattingDates {
|
|
237
|
+
return dateStringFormatter.string(from: dateValue)
|
|
238
|
+
}
|
|
239
|
+
return dateValue
|
|
240
|
+
case let nullValue as NSNull:
|
|
241
|
+
return nullValue
|
|
242
|
+
case let arrayValue as NSArray:
|
|
243
|
+
return arrayValue.compactMap { coerceToJSValue($0, formattingDates: formattingDates) }
|
|
244
|
+
case let dictionaryValue as NSDictionary:
|
|
245
|
+
let keys = dictionaryValue.allKeys.compactMap { $0 as? String }
|
|
246
|
+
var result: JSObject = [:]
|
|
247
|
+
for key in keys {
|
|
248
|
+
result[key] = coerceToJSValue(dictionaryValue[key], formattingDates: formattingDates)
|
|
249
|
+
}
|
|
250
|
+
return result
|
|
251
|
+
default:
|
|
252
|
+
return nil
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
public struct KeyPath {
|
|
4
|
+
var segments: [String]
|
|
5
|
+
var isEmpty: Bool { return segments.isEmpty }
|
|
6
|
+
var path: String {
|
|
7
|
+
return segments.joined(separator: ".")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// initializers
|
|
11
|
+
init(_ string: String) {
|
|
12
|
+
self.segments = string.components(separatedBy: ".")
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
init(segments: [String]) {
|
|
16
|
+
self.segments = segments
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// returns a tuple of the first segment and the remaining key path. result is nil if the key path has no segments.
|
|
20
|
+
func headAndRemainder() -> (head: String, remainder: KeyPath)? {
|
|
21
|
+
guard !isEmpty else {
|
|
22
|
+
return nil
|
|
23
|
+
}
|
|
24
|
+
var paths = segments
|
|
25
|
+
let head = paths.removeFirst()
|
|
26
|
+
return (head, KeyPath(segments: paths))
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
extension KeyPath: ExpressibleByStringLiteral {
|
|
31
|
+
public init(stringLiteral value: String) {
|
|
32
|
+
self.init(value)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public init(unicodeScalarLiteral value: String) {
|
|
36
|
+
self.init(value)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public init(extendedGraphemeClusterLiteral value: String) {
|
|
40
|
+
self.init(value)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
extension JSObject {
|
|
45
|
+
public subscript(keyPath keyPath: KeyPath) -> JSValue? {
|
|
46
|
+
switch keyPath.headAndRemainder() {
|
|
47
|
+
case nil: // path is empty
|
|
48
|
+
return nil
|
|
49
|
+
case let (head, remainder)? where remainder.isEmpty: // reached the end of the path
|
|
50
|
+
return self[head]
|
|
51
|
+
case let (head, remainder)?: // we have at least one level to traverse
|
|
52
|
+
switch self[head] {
|
|
53
|
+
case let childObject as JSObject: // iterate down the next level
|
|
54
|
+
return childObject[keyPath: remainder]
|
|
55
|
+
default: // not an object, can't go any deeper
|
|
56
|
+
return nil
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|