@thelacanians/vue-native-cli 0.4.14 → 0.6.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/dist/cli.js +789 -200
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Bridge/NativeBridge.kt +156 -5
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VListFactory.kt +33 -13
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VScrollViewFactory.kt +27 -6
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VSliderFactory.kt +9 -2
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Components/Factories/VViewFactory.kt +178 -1
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Helpers/EventThrottle.kt +57 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/GeneratedModuleRegistry.kt +28 -0
- package/native/android/VueNativeCore/src/main/kotlin/com/vuenative/core/Modules/NativeModuleRegistry.kt +3 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ComponentFactoryTest.kt +674 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/ErrorOverlayViewTest.kt +183 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/EventThrottleTest.kt +203 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/HotReloadManagerTest.kt +162 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/JSPolyfillsTest.kt +153 -0
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeBridgeTest.kt +6 -3
- package/native/android/VueNativeCore/src/test/kotlin/com/vuenative/core/NativeModuleTest.kt +475 -0
- package/native/android/gradle.properties +1 -0
- package/native/android/gradlew +1 -1
- package/native/ios/VueNativeCore/Package.swift +1 -1
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/EventThrottle.swift +80 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/NativeBridge.swift +244 -112
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VListFactory.swift +19 -2
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VScrollViewFactory.swift +9 -4
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VSliderFactory.swift +8 -3
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VTextFactory.swift +43 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/Factories/VViewFactory.swift +116 -4
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Helpers/GestureWrapper.swift +100 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/GeneratedModuleRegistry.swift +28 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Modules/NativeModuleRegistry.swift +3 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/CertificatePinningTests.swift +190 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/ComponentFactoryTests.swift +585 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/EventThrottleTests.swift +161 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/HotReloadManagerTests.swift +88 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/JSPolyfillsTests.swift +319 -0
- package/native/ios/VueNativeCore/Tests/VueNativeCoreTests/NativeModuleTests.swift +400 -0
- package/native/macos/VueNativeMacOS/Package.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/ErrorOverlayView.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/EventThrottle.swift +58 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/HotReloadManager.swift +153 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSPolyfills.swift +696 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/JSRuntime.swift +347 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/NativeBridge.swift +877 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Bridge/VueNativeWindowController.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/ComponentRegistry.swift +209 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActionSheetFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VActivityIndicatorFactory.swift +85 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VAlertDialogFactory.swift +132 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VButtonFactory.swift +83 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VCheckboxFactory.swift +108 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VDropdownFactory.swift +155 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VImageFactory.swift +270 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VInputFactory.swift +257 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VKeyboardAvoidingFactory.swift +22 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VListFactory.swift +324 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VModalFactory.swift +231 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VOutlineViewFactory.swift +276 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPickerFactory.swift +134 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VPressableFactory.swift +120 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VProgressBarFactory.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRadioFactory.swift +193 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VRefreshControlFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSafeAreaFactory.swift +46 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VScrollViewFactory.swift +190 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSectionListFactory.swift +374 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSegmentedControlFactory.swift +125 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSliderFactory.swift +131 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSplitViewFactory.swift +215 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VStatusBarFactory.swift +25 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VSwitchFactory.swift +92 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VTextFactory.swift +336 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VToolbarFactory.swift +212 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VVideoFactory.swift +245 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VViewFactory.swift +314 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/Factories/VWebViewFactory.swift +162 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Components/NativeComponentFactory.swift +54 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/ClickableView.swift +100 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/Extensions.swift +23 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/GestureWrapper.swift +183 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Helpers/NSColor+Hex.swift +78 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/FlippedView.swift +19 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Layout/LayoutNode.swift +493 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AnimationModule.swift +354 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/AppStateModule.swift +62 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/BiometryModule.swift +60 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/CameraModule.swift +167 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ClipboardModule.swift +34 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DeviceInfoModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/DragDropModule.swift +50 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/FileDialogModule.swift +86 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/HapticsModule.swift +42 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/KeyboardModule.swift +28 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/LinkingModule.swift +49 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/MenuModule.swift +95 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NativeModuleRegistry.swift +63 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/NotificationsModule.swift +112 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/PermissionsModule.swift +149 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/ShareModule.swift +37 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Modules/WindowModule.swift +71 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Resources/vue-native-placeholder.js +2 -0
- package/native/macos/VueNativeMacOS/Sources/VueNativeMacOS/Styling/StyleEngine.swift +885 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/ComponentFactoryTests.swift +80 -0
- package/native/macos/VueNativeMacOS/Tests/VueNativeMacOSTests/VueNativeMacOSTests.swift +149 -0
- package/native/shared/VueNativeShared/AGENTS.md +129 -0
- package/native/shared/VueNativeShared/Package.swift +14 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/CertificatePinning.swift +134 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/EventThrottle.swift +78 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/HotReloadManager.swift +162 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/JSRuntime.swift +412 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AsyncStorageModule.swift +68 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/AudioModule.swift +359 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/DatabaseModule.swift +259 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/FileSystemModule.swift +233 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/GeolocationModule.swift +156 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/NetworkModule.swift +59 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/PerformanceModule.swift +113 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/SecureStorageModule.swift +119 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/Modules/WebSocketModule.swift +212 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeEventDispatcher.swift +6 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModule.swift +26 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/NativeModuleRegistry.swift +37 -0
- package/native/shared/VueNativeShared/Sources/VueNativeShared/SharedJSPolyfills.swift +673 -0
- package/native/shared/VueNativeShared/Tests/VueNativeSharedTests/VueNativeSharedTests.swift +44 -0
- package/package.json +8 -2
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Native module for WebSocket connections.
|
|
4
|
+
/// Uses URLSession which is available on both iOS and macOS.
|
|
5
|
+
///
|
|
6
|
+
/// Supports multiple simultaneous connections keyed by connection ID.
|
|
7
|
+
///
|
|
8
|
+
/// Methods:
|
|
9
|
+
/// - connect(url: String, connectionId: String)
|
|
10
|
+
/// - send(connectionId: String, data: String)
|
|
11
|
+
/// - close(connectionId: String, code: Int?, reason: String?)
|
|
12
|
+
///
|
|
13
|
+
/// Global events dispatched via NativeEventDispatcher:
|
|
14
|
+
/// "websocket:open" { connectionId }
|
|
15
|
+
/// "websocket:message" { connectionId, data }
|
|
16
|
+
/// "websocket:close" { connectionId, code, reason }
|
|
17
|
+
/// "websocket:error" { connectionId, message }
|
|
18
|
+
public final class WebSocketModule: NativeModule {
|
|
19
|
+
public var moduleName: String { "WebSocket" }
|
|
20
|
+
private weak var eventDispatcher: NativeEventDispatcher?
|
|
21
|
+
|
|
22
|
+
/// Active WebSocket tasks keyed by connectionId
|
|
23
|
+
private var connections: [String: URLSessionWebSocketTask] = [:]
|
|
24
|
+
private var sessions: [String: URLSession] = [:]
|
|
25
|
+
|
|
26
|
+
public init(eventDispatcher: NativeEventDispatcher) {
|
|
27
|
+
self.eventDispatcher = eventDispatcher
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
|
|
31
|
+
switch method {
|
|
32
|
+
case "connect":
|
|
33
|
+
guard let url = args.first as? String,
|
|
34
|
+
let connectionId = args.count > 1 ? args[1] as? String : nil else {
|
|
35
|
+
callback(nil, "WebSocketModule: expected (url, connectionId)")
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
connect(url: url, connectionId: connectionId, callback: callback)
|
|
39
|
+
|
|
40
|
+
case "send":
|
|
41
|
+
guard let connectionId = args.first as? String,
|
|
42
|
+
let data = args.count > 1 ? args[1] as? String : nil else {
|
|
43
|
+
callback(nil, "WebSocketModule: expected (connectionId, data)")
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
send(connectionId: connectionId, data: data, callback: callback)
|
|
47
|
+
|
|
48
|
+
case "close":
|
|
49
|
+
guard let connectionId = args.first as? String else {
|
|
50
|
+
callback(nil, "WebSocketModule: expected (connectionId)")
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
let code = args.count > 1 ? args[1] as? Int : nil
|
|
54
|
+
let reason = args.count > 2 ? args[2] as? String : nil
|
|
55
|
+
close(connectionId: connectionId, code: code, reason: reason, callback: callback)
|
|
56
|
+
|
|
57
|
+
default:
|
|
58
|
+
callback(nil, "WebSocketModule: Unknown method '\(method)'")
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// MARK: - Connect
|
|
63
|
+
|
|
64
|
+
private func connect(url: String, connectionId: String, callback: @escaping (Any?, String?) -> Void) {
|
|
65
|
+
guard let wsURL = URL(string: url) else {
|
|
66
|
+
callback(nil, "WebSocketModule: invalid URL '\(url)'")
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Clean up existing connection with same ID if any
|
|
71
|
+
closeConnection(connectionId)
|
|
72
|
+
|
|
73
|
+
let session = URLSession(configuration: .default)
|
|
74
|
+
let task = session.webSocketTask(with: wsURL)
|
|
75
|
+
connections[connectionId] = task
|
|
76
|
+
sessions[connectionId] = session
|
|
77
|
+
|
|
78
|
+
task.resume()
|
|
79
|
+
|
|
80
|
+
// Dispatch open event once resumed
|
|
81
|
+
let weakDispatcher = eventDispatcher
|
|
82
|
+
DispatchQueue.main.async {
|
|
83
|
+
weakDispatcher?.dispatchGlobalEvent("websocket:open", payload: [
|
|
84
|
+
"connectionId": connectionId
|
|
85
|
+
])
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Start receive loop
|
|
89
|
+
receiveLoop(connectionId: connectionId, task: task)
|
|
90
|
+
|
|
91
|
+
callback(true, nil)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// MARK: - Receive loop
|
|
95
|
+
|
|
96
|
+
private func receiveLoop(connectionId: String, task: URLSessionWebSocketTask) {
|
|
97
|
+
task.receive { [weak self] result in
|
|
98
|
+
guard let self = self else { return }
|
|
99
|
+
// Check if connection still exists (may have been closed)
|
|
100
|
+
guard self.connections[connectionId] != nil else { return }
|
|
101
|
+
|
|
102
|
+
switch result {
|
|
103
|
+
case .success(let message):
|
|
104
|
+
let data: String
|
|
105
|
+
switch message {
|
|
106
|
+
case .string(let text):
|
|
107
|
+
data = text
|
|
108
|
+
case .data(let bytes):
|
|
109
|
+
data = String(data: bytes, encoding: .utf8) ?? ""
|
|
110
|
+
@unknown default:
|
|
111
|
+
data = ""
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let weakDispatcher = self.eventDispatcher
|
|
115
|
+
DispatchQueue.main.async {
|
|
116
|
+
weakDispatcher?.dispatchGlobalEvent("websocket:message", payload: [
|
|
117
|
+
"connectionId": connectionId,
|
|
118
|
+
"data": data
|
|
119
|
+
])
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Continue receiving
|
|
123
|
+
self.receiveLoop(connectionId: connectionId, task: task)
|
|
124
|
+
|
|
125
|
+
case .failure(let error):
|
|
126
|
+
let weakDispatcher = self.eventDispatcher
|
|
127
|
+
let errorMessage = error.localizedDescription
|
|
128
|
+
DispatchQueue.main.async {
|
|
129
|
+
// Check if this is a normal close or an actual error
|
|
130
|
+
let nsError = error as NSError
|
|
131
|
+
if nsError.domain == NSPOSIXErrorDomain && nsError.code == 57 {
|
|
132
|
+
// Socket not connected — normal close, dispatch close event
|
|
133
|
+
weakDispatcher?.dispatchGlobalEvent("websocket:close", payload: [
|
|
134
|
+
"connectionId": connectionId,
|
|
135
|
+
"code": 1000,
|
|
136
|
+
"reason": ""
|
|
137
|
+
])
|
|
138
|
+
} else {
|
|
139
|
+
weakDispatcher?.dispatchGlobalEvent("websocket:error", payload: [
|
|
140
|
+
"connectionId": connectionId,
|
|
141
|
+
"message": errorMessage
|
|
142
|
+
])
|
|
143
|
+
weakDispatcher?.dispatchGlobalEvent("websocket:close", payload: [
|
|
144
|
+
"connectionId": connectionId,
|
|
145
|
+
"code": 1006,
|
|
146
|
+
"reason": errorMessage
|
|
147
|
+
])
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
self.connections.removeValue(forKey: connectionId)
|
|
151
|
+
self.sessions[connectionId]?.invalidateAndCancel()
|
|
152
|
+
self.sessions.removeValue(forKey: connectionId)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// MARK: - Send
|
|
158
|
+
|
|
159
|
+
private func send(connectionId: String, data: String, callback: @escaping (Any?, String?) -> Void) {
|
|
160
|
+
guard let task = connections[connectionId] else {
|
|
161
|
+
callback(nil, "WebSocketModule: no connection '\(connectionId)'")
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
task.send(.string(data)) { error in
|
|
165
|
+
if let error = error {
|
|
166
|
+
callback(nil, error.localizedDescription)
|
|
167
|
+
} else {
|
|
168
|
+
callback(true, nil)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// MARK: - Close
|
|
174
|
+
|
|
175
|
+
private func close(connectionId: String, code: Int?, reason: String?, callback: @escaping (Any?, String?) -> Void) {
|
|
176
|
+
guard let task = connections[connectionId] else {
|
|
177
|
+
callback(nil, nil) // Already closed, not an error
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let closeCode = URLSessionWebSocketTask.CloseCode(rawValue: code ?? 1000) ?? .normalClosure
|
|
182
|
+
let reasonData = reason?.data(using: .utf8)
|
|
183
|
+
task.cancel(with: closeCode, reason: reasonData)
|
|
184
|
+
|
|
185
|
+
let weakDispatcher = eventDispatcher
|
|
186
|
+
DispatchQueue.main.async {
|
|
187
|
+
weakDispatcher?.dispatchGlobalEvent("websocket:close", payload: [
|
|
188
|
+
"connectionId": connectionId,
|
|
189
|
+
"code": code ?? 1000,
|
|
190
|
+
"reason": reason ?? ""
|
|
191
|
+
])
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
connections.removeValue(forKey: connectionId)
|
|
195
|
+
sessions[connectionId]?.invalidateAndCancel()
|
|
196
|
+
sessions.removeValue(forKey: connectionId)
|
|
197
|
+
|
|
198
|
+
callback(true, nil)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// MARK: - Helpers
|
|
202
|
+
|
|
203
|
+
private func closeConnection(_ connectionId: String) {
|
|
204
|
+
guard let task = connections[connectionId] else { return }
|
|
205
|
+
task.cancel(with: .normalClosure, reason: nil)
|
|
206
|
+
connections.removeValue(forKey: connectionId)
|
|
207
|
+
sessions[connectionId]?.invalidateAndCancel()
|
|
208
|
+
sessions.removeValue(forKey: connectionId)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public func invokeSync(method: String, args: [Any]) -> Any? { nil }
|
|
212
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Protocol that all native modules must conform to.
|
|
4
|
+
/// Modules are registered with NativeModuleRegistry and invoked from JS
|
|
5
|
+
/// via the platform-specific bridge's invokeNativeModule / invokeNativeModuleSync operations.
|
|
6
|
+
public protocol NativeModule: AnyObject {
|
|
7
|
+
/// The name used to identify this module from JS (e.g. "Haptics", "AsyncStorage").
|
|
8
|
+
var moduleName: String { get }
|
|
9
|
+
|
|
10
|
+
/// Invoke a method asynchronously.
|
|
11
|
+
/// - Parameters:
|
|
12
|
+
/// - method: The method name to invoke.
|
|
13
|
+
/// - args: Arguments passed from JS.
|
|
14
|
+
/// - callback: Called when the method completes. Pass (result, nil) on success,
|
|
15
|
+
/// (nil, errorMessage) on failure.
|
|
16
|
+
func invoke(method: String, args: [Any], callback: @escaping (Any?, String?) -> Void)
|
|
17
|
+
|
|
18
|
+
/// Invoke a method synchronously and return the result.
|
|
19
|
+
/// Use sparingly — prefer the async variant.
|
|
20
|
+
func invokeSync(method: String, args: [Any]) -> Any?
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public extension NativeModule {
|
|
24
|
+
/// Default sync implementation: just returns nil.
|
|
25
|
+
func invokeSync(method: String, args: [Any]) -> Any? { return nil }
|
|
26
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// Registry for all native modules.
|
|
4
|
+
/// Modules are registered by name and looked up when JS invokes them.
|
|
5
|
+
/// Each platform registers its own set of modules — there is no `registerDefaults()` here.
|
|
6
|
+
public final class NativeModuleRegistry {
|
|
7
|
+
|
|
8
|
+
public static let shared = NativeModuleRegistry()
|
|
9
|
+
|
|
10
|
+
private var modules: [String: NativeModule] = [:]
|
|
11
|
+
|
|
12
|
+
private init() {}
|
|
13
|
+
|
|
14
|
+
// MARK: - Registration
|
|
15
|
+
|
|
16
|
+
public func register(_ module: NativeModule) {
|
|
17
|
+
modules[module.moduleName] = module
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// MARK: - Invocation
|
|
21
|
+
|
|
22
|
+
public func invoke(module moduleName: String, method: String, args: [Any], callback: @escaping (Any?, String?) -> Void) {
|
|
23
|
+
guard let module = modules[moduleName] else {
|
|
24
|
+
callback(nil, "Module '\(moduleName)' not found")
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
module.invoke(method: method, args: args, callback: callback)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public func invokeSync(module moduleName: String, method: String, args: [Any]) -> Any? {
|
|
31
|
+
guard let module = modules[moduleName] else {
|
|
32
|
+
NSLog("[VueNative] NativeModuleRegistry: Module '\(moduleName)' not found")
|
|
33
|
+
return nil
|
|
34
|
+
}
|
|
35
|
+
return module.invokeSync(method: method, args: args)
|
|
36
|
+
}
|
|
37
|
+
}
|