driftx 0.1.1 → 0.1.2
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/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/bin.js +834 -81
- package/dist/bin.js.map +1 -1
- package/driftx-plugin/skills/driftx/SKILL.md +235 -20
- package/ios-companion/DriftxCompanion/DriftxCompanionApp.swift +10 -0
- package/ios-companion/DriftxCompanion/Info.plist +22 -0
- package/ios-companion/DriftxCompanion.xcodeproj/project.pbxproj +376 -0
- package/ios-companion/DriftxCompanion.xcodeproj/xcshareddata/xcschemes/DriftxCompanionUITests.xcscheme +109 -0
- package/ios-companion/DriftxCompanionUITests/CompanionServer.swift +176 -0
- package/ios-companion/DriftxCompanionUITests/DriftxCompanionUITests.swift +15 -0
- package/ios-companion/DriftxCompanionUITests/HierarchyEndpoint.swift +140 -0
- package/ios-companion/DriftxCompanionUITests/Info.plist +22 -0
- package/ios-companion/DriftxCompanionUITests/InteractionEndpoint.swift +142 -0
- package/ios-companion/DriftxCompanionUITests/Router.swift +47 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/DriftxCompanion +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/DriftxCompanion.debug.dylib +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/PkgInfo +1 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/__preview.dylib +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/DriftxCompanionUITests-Runner +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/Testing +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/_CodeSignature/CodeResources +168 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/Testing.framework/version.plist +18 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/XCTAutomationSupport +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/_CodeSignature/CodeResources +113 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTAutomationSupport.framework/version.plist +18 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/XCTest +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/_CodeSignature/CodeResources +817 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTest.framework/version.plist +18 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/XCTestCore +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/_CodeSignature/CodeResources +113 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestCore.framework/version.plist +18 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/XCTestSupport +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/_CodeSignature/CodeResources +113 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCTestSupport.framework/version.plist +18 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/XCUIAutomation +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/_CodeSignature/CodeResources +432 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUIAutomation.framework/version.plist +18 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/Info.plist +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/XCUnit +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/_CodeSignature/CodeResources +113 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/XCUnit.framework/version.plist +18 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Frameworks/libXCTestSwiftSupport.dylib +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/Info.plist +254 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/PkgInfo +1 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/PlugIns/DriftxCompanionUITests.xctest/DriftxCompanionUITests +0 -0
- package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanionUITests-Runner.app/PlugIns/DriftxCompanionUITests.xctest/Info.plist +0 -0
- package/ios-companion/prebuilt/DriftxCompanionUITests.xctestrun +135 -0
- package/ios-companion/prebuilt/build-info.json +6 -0
- package/package.json +14 -3
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import XCTest
|
|
3
|
+
|
|
4
|
+
enum HierarchyEndpoint {
|
|
5
|
+
private static let maxDepth = 30
|
|
6
|
+
|
|
7
|
+
static func register(on router: Router, app: XCUIApplication) {
|
|
8
|
+
router.register(method: "GET", path: "/hierarchy") { _ in
|
|
9
|
+
do {
|
|
10
|
+
let snapshot: XCUIElementSnapshot = try DispatchQueue.main.sync {
|
|
11
|
+
try app.snapshot()
|
|
12
|
+
}
|
|
13
|
+
let tree = walk(snapshot, depth: 0)
|
|
14
|
+
let data = try JSONSerialization.data(withJSONObject: [tree], options: [])
|
|
15
|
+
return (200, data)
|
|
16
|
+
} catch {
|
|
17
|
+
return (500, jsonResponse(["error": error.localizedDescription]))
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private static func walk(_ snap: XCUIElementSnapshot, depth: Int) -> [String: Any] {
|
|
23
|
+
var node: [String: Any] = [
|
|
24
|
+
"elementType": elementTypeName(snap.elementType),
|
|
25
|
+
"identifier": snap.identifier,
|
|
26
|
+
"label": snap.label,
|
|
27
|
+
"frame": [
|
|
28
|
+
"x": snap.frame.origin.x,
|
|
29
|
+
"y": snap.frame.origin.y,
|
|
30
|
+
"width": snap.frame.size.width,
|
|
31
|
+
"height": snap.frame.size.height
|
|
32
|
+
],
|
|
33
|
+
"isEnabled": snap.isEnabled
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
if let value = snap.value {
|
|
37
|
+
node["value"] = "\(value)"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if depth < maxDepth {
|
|
41
|
+
let children = snap.children.map { child in
|
|
42
|
+
walk(child, depth: depth + 1)
|
|
43
|
+
}
|
|
44
|
+
node["children"] = children
|
|
45
|
+
} else {
|
|
46
|
+
node["children"] = [] as [[String: Any]]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return node
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private static func elementTypeName(_ type: XCUIElement.ElementType) -> String {
|
|
53
|
+
switch type {
|
|
54
|
+
case .any: return "any"
|
|
55
|
+
case .other: return "other"
|
|
56
|
+
case .application: return "application"
|
|
57
|
+
case .group: return "group"
|
|
58
|
+
case .window: return "window"
|
|
59
|
+
case .sheet: return "sheet"
|
|
60
|
+
case .drawer: return "drawer"
|
|
61
|
+
case .alert: return "alert"
|
|
62
|
+
case .dialog: return "dialog"
|
|
63
|
+
case .button: return "button"
|
|
64
|
+
case .radioButton: return "radioButton"
|
|
65
|
+
case .radioGroup: return "radioGroup"
|
|
66
|
+
case .checkBox: return "checkBox"
|
|
67
|
+
case .disclosureTriangle: return "disclosureTriangle"
|
|
68
|
+
case .popUpButton: return "popUpButton"
|
|
69
|
+
case .comboBox: return "comboBox"
|
|
70
|
+
case .menuButton: return "menuButton"
|
|
71
|
+
case .toolbarButton: return "toolbarButton"
|
|
72
|
+
case .popover: return "popover"
|
|
73
|
+
case .keyboard: return "keyboard"
|
|
74
|
+
case .key: return "key"
|
|
75
|
+
case .navigationBar: return "navigationBar"
|
|
76
|
+
case .tabBar: return "tabBar"
|
|
77
|
+
case .tabGroup: return "tabGroup"
|
|
78
|
+
case .toolbar: return "toolbar"
|
|
79
|
+
case .statusBar: return "statusBar"
|
|
80
|
+
case .table: return "table"
|
|
81
|
+
case .tableRow: return "tableRow"
|
|
82
|
+
case .tableColumn: return "tableColumn"
|
|
83
|
+
case .outline: return "outline"
|
|
84
|
+
case .outlineRow: return "outlineRow"
|
|
85
|
+
case .browser: return "browser"
|
|
86
|
+
case .collectionView: return "collectionView"
|
|
87
|
+
case .slider: return "slider"
|
|
88
|
+
case .pageIndicator: return "pageIndicator"
|
|
89
|
+
case .progressIndicator: return "progressIndicator"
|
|
90
|
+
case .activityIndicator: return "activityIndicator"
|
|
91
|
+
case .segmentedControl: return "segmentedControl"
|
|
92
|
+
case .picker: return "picker"
|
|
93
|
+
case .pickerWheel: return "pickerWheel"
|
|
94
|
+
case .switch: return "switch"
|
|
95
|
+
case .toggle: return "toggle"
|
|
96
|
+
case .link: return "link"
|
|
97
|
+
case .image: return "image"
|
|
98
|
+
case .icon: return "icon"
|
|
99
|
+
case .searchField: return "searchField"
|
|
100
|
+
case .scrollView: return "scrollView"
|
|
101
|
+
case .scrollBar: return "scrollBar"
|
|
102
|
+
case .staticText: return "staticText"
|
|
103
|
+
case .textField: return "textField"
|
|
104
|
+
case .secureTextField: return "secureTextField"
|
|
105
|
+
case .datePicker: return "datePicker"
|
|
106
|
+
case .textView: return "textView"
|
|
107
|
+
case .menu: return "menu"
|
|
108
|
+
case .menuItem: return "menuItem"
|
|
109
|
+
case .menuBar: return "menuBar"
|
|
110
|
+
case .menuBarItem: return "menuBarItem"
|
|
111
|
+
case .map: return "map"
|
|
112
|
+
case .webView: return "webView"
|
|
113
|
+
case .incrementArrow: return "incrementArrow"
|
|
114
|
+
case .decrementArrow: return "decrementArrow"
|
|
115
|
+
case .timeline: return "timeline"
|
|
116
|
+
case .ratingIndicator: return "ratingIndicator"
|
|
117
|
+
case .valueIndicator: return "valueIndicator"
|
|
118
|
+
case .splitGroup: return "splitGroup"
|
|
119
|
+
case .splitter: return "splitter"
|
|
120
|
+
case .relevanceIndicator: return "relevanceIndicator"
|
|
121
|
+
case .colorWell: return "colorWell"
|
|
122
|
+
case .helpTag: return "helpTag"
|
|
123
|
+
case .matte: return "matte"
|
|
124
|
+
case .dockItem: return "dockItem"
|
|
125
|
+
case .ruler: return "ruler"
|
|
126
|
+
case .rulerMarker: return "rulerMarker"
|
|
127
|
+
case .grid: return "grid"
|
|
128
|
+
case .levelIndicator: return "levelIndicator"
|
|
129
|
+
case .cell: return "cell"
|
|
130
|
+
case .layoutArea: return "layoutArea"
|
|
131
|
+
case .layoutItem: return "layoutItem"
|
|
132
|
+
case .handle: return "handle"
|
|
133
|
+
case .stepper: return "stepper"
|
|
134
|
+
case .tab: return "tab"
|
|
135
|
+
case .touchBar: return "touchBar"
|
|
136
|
+
case .statusItem: return "statusItem"
|
|
137
|
+
@unknown default: return "unknown(\(type.rawValue))"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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>en</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>BNDL</string>
|
|
17
|
+
<key>CFBundleShortVersionString</key>
|
|
18
|
+
<string>1.0</string>
|
|
19
|
+
<key>CFBundleVersion</key>
|
|
20
|
+
<string>1</string>
|
|
21
|
+
</dict>
|
|
22
|
+
</plist>
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import XCTest
|
|
3
|
+
|
|
4
|
+
enum InteractionEndpoint {
|
|
5
|
+
static func register(on router: Router, app: XCUIApplication) {
|
|
6
|
+
router.register(method: "POST", path: "/tap") { body in
|
|
7
|
+
guard let json = parseJSONBody(body),
|
|
8
|
+
let x = json["x"] as? Double,
|
|
9
|
+
let y = json["y"] as? Double else {
|
|
10
|
+
return (400, jsonResponse(["success": false, "error": "Missing x or y"]))
|
|
11
|
+
}
|
|
12
|
+
DispatchQueue.main.sync {
|
|
13
|
+
let normalized = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
|
|
14
|
+
let point = normalized.withOffset(CGVector(dx: x, dy: y))
|
|
15
|
+
point.tap()
|
|
16
|
+
}
|
|
17
|
+
return (200, jsonResponse(["success": true]))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
router.register(method: "POST", path: "/longPress") { body in
|
|
21
|
+
guard let json = parseJSONBody(body),
|
|
22
|
+
let x = json["x"] as? Double,
|
|
23
|
+
let y = json["y"] as? Double else {
|
|
24
|
+
return (400, jsonResponse(["success": false, "error": "Missing x or y"]))
|
|
25
|
+
}
|
|
26
|
+
let duration = json["duration"] as? Double ?? 1.0
|
|
27
|
+
DispatchQueue.main.sync {
|
|
28
|
+
let normalized = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
|
|
29
|
+
let point = normalized.withOffset(CGVector(dx: x, dy: y))
|
|
30
|
+
point.press(forDuration: duration)
|
|
31
|
+
}
|
|
32
|
+
return (200, jsonResponse(["success": true]))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
router.register(method: "POST", path: "/swipe") { body in
|
|
36
|
+
guard let json = parseJSONBody(body),
|
|
37
|
+
let fromX = json["fromX"] as? Double,
|
|
38
|
+
let fromY = json["fromY"] as? Double,
|
|
39
|
+
let toX = json["toX"] as? Double,
|
|
40
|
+
let toY = json["toY"] as? Double else {
|
|
41
|
+
return (400, jsonResponse(["success": false, "error": "Missing fromX, fromY, toX, or toY"]))
|
|
42
|
+
}
|
|
43
|
+
let duration = json["duration"] as? Double ?? 0.3
|
|
44
|
+
DispatchQueue.main.sync {
|
|
45
|
+
let normalized = app.coordinate(withNormalizedOffset: CGVector(dx: 0, dy: 0))
|
|
46
|
+
let start = normalized.withOffset(CGVector(dx: fromX, dy: fromY))
|
|
47
|
+
let end = normalized.withOffset(CGVector(dx: toX, dy: toY))
|
|
48
|
+
start.press(forDuration: duration, thenDragTo: end)
|
|
49
|
+
}
|
|
50
|
+
return (200, jsonResponse(["success": true]))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
router.register(method: "POST", path: "/type") { body in
|
|
54
|
+
guard let json = parseJSONBody(body),
|
|
55
|
+
let text = json["text"] as? String else {
|
|
56
|
+
return (400, jsonResponse(["success": false, "error": "Missing text"]))
|
|
57
|
+
}
|
|
58
|
+
DispatchQueue.main.sync {
|
|
59
|
+
app.typeText(text)
|
|
60
|
+
}
|
|
61
|
+
return (200, jsonResponse(["success": true]))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
router.register(method: "POST", path: "/find") { body in
|
|
65
|
+
guard let json = parseJSONBody(body),
|
|
66
|
+
let text = json["text"] as? String, !text.isEmpty else {
|
|
67
|
+
return (400, jsonResponse(["success": false, "error": "Missing text"]))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let result: (Bool, [String: Any]) = DispatchQueue.main.sync {
|
|
71
|
+
let queries: [XCUIElementQuery] = [
|
|
72
|
+
app.staticTexts,
|
|
73
|
+
app.buttons,
|
|
74
|
+
app.links,
|
|
75
|
+
app.otherElements,
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
for query in queries {
|
|
79
|
+
let match = query[text]
|
|
80
|
+
if match.exists {
|
|
81
|
+
let frame = match.frame
|
|
82
|
+
return (true, [
|
|
83
|
+
"success": true,
|
|
84
|
+
"frame": [
|
|
85
|
+
"x": frame.origin.x,
|
|
86
|
+
"y": frame.origin.y,
|
|
87
|
+
"width": frame.size.width,
|
|
88
|
+
"height": frame.size.height,
|
|
89
|
+
],
|
|
90
|
+
])
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
for query in queries {
|
|
95
|
+
let predicate = NSPredicate(format: "label CONTAINS[c] %@", text)
|
|
96
|
+
let matches = query.matching(predicate)
|
|
97
|
+
if matches.count > 0 {
|
|
98
|
+
let match = matches.firstMatch
|
|
99
|
+
let frame = match.frame
|
|
100
|
+
return (true, [
|
|
101
|
+
"success": true,
|
|
102
|
+
"frame": [
|
|
103
|
+
"x": frame.origin.x,
|
|
104
|
+
"y": frame.origin.y,
|
|
105
|
+
"width": frame.size.width,
|
|
106
|
+
"height": frame.size.height,
|
|
107
|
+
],
|
|
108
|
+
])
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return (false, ["success": false, "error": "Element not found: \(text)"])
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return (result.0 ? 200 : 404, jsonResponse(result.1))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
router.register(method: "POST", path: "/keyEvent") { body in
|
|
119
|
+
guard let json = parseJSONBody(body),
|
|
120
|
+
let key = json["key"] as? String else {
|
|
121
|
+
return (400, jsonResponse(["success": false, "error": "Missing key"]))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let button: XCUIDevice.Button?
|
|
125
|
+
switch key.lowercased() {
|
|
126
|
+
case "home":
|
|
127
|
+
button = .home
|
|
128
|
+
default:
|
|
129
|
+
button = nil
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
guard let deviceButton = button else {
|
|
133
|
+
return (400, jsonResponse(["success": false, "error": "Unknown key: \(key)"]))
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
DispatchQueue.main.sync {
|
|
137
|
+
XCUIDevice.shared.press(deviceButton)
|
|
138
|
+
}
|
|
139
|
+
return (200, jsonResponse(["success": true]))
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
typealias RouteHandler = (Data?) -> (Int, Data)
|
|
4
|
+
|
|
5
|
+
final class Router {
|
|
6
|
+
private var routes: [String: RouteHandler] = [:]
|
|
7
|
+
private let lock = NSLock()
|
|
8
|
+
|
|
9
|
+
func register(method: String, path: String, handler: @escaping RouteHandler) {
|
|
10
|
+
let key = routeKey(method: method, path: path)
|
|
11
|
+
lock.lock()
|
|
12
|
+
routes[key] = handler
|
|
13
|
+
lock.unlock()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
func handle(method: String, path: String, body: Data?) -> (Int, Data) {
|
|
17
|
+
let key = routeKey(method: method, path: path)
|
|
18
|
+
lock.lock()
|
|
19
|
+
let handler = routes[key]
|
|
20
|
+
lock.unlock()
|
|
21
|
+
|
|
22
|
+
guard let handler = handler else {
|
|
23
|
+
return (404, Router.jsonResponse(["error": "Not found"]))
|
|
24
|
+
}
|
|
25
|
+
return handler(body)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private func routeKey(method: String, path: String) -> String {
|
|
29
|
+
"\(method.uppercased()) \(path)"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static func jsonResponse(_ dict: [String: Any]) -> Data {
|
|
33
|
+
(try? JSONSerialization.data(withJSONObject: dict, options: [])) ?? Data("{}".utf8)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
func jsonResponse(_ dict: [String: Any]) -> Data {
|
|
38
|
+
Router.jsonResponse(dict)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func parseJSONBody(_ body: Data?) -> [String: Any]? {
|
|
42
|
+
guard let body = body,
|
|
43
|
+
let obj = try? JSONSerialization.jsonObject(with: body) as? [String: Any] else {
|
|
44
|
+
return nil
|
|
45
|
+
}
|
|
46
|
+
return obj
|
|
47
|
+
}
|
|
Binary file
|
package/ios-companion/prebuilt/Debug-iphonesimulator/DriftxCompanion.app/DriftxCompanion.debug.dylib
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
APPL????
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,168 @@
|
|
|
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>files</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>Info.plist</key>
|
|
8
|
+
<data>
|
|
9
|
+
lxB5oLSwSvqYXv+kdciJ2r2Z/vk=
|
|
10
|
+
</data>
|
|
11
|
+
<key>Modules/Testing.swiftcrossimport/Foundation.swiftoverlay</key>
|
|
12
|
+
<data>
|
|
13
|
+
YTs8xm0XTk+De36jTobLiYDGRzE=
|
|
14
|
+
</data>
|
|
15
|
+
<key>Modules/Testing.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
|
|
16
|
+
<data>
|
|
17
|
+
FJgnhzgKiX5lquI3u6PYvEUA1gk=
|
|
18
|
+
</data>
|
|
19
|
+
<key>Modules/Testing.swiftmodule/arm64-apple-ios-simulator.swiftinterface</key>
|
|
20
|
+
<data>
|
|
21
|
+
hmssl+LbRFbq+l15pJrsY8QIwjA=
|
|
22
|
+
</data>
|
|
23
|
+
<key>Modules/Testing.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
|
24
|
+
<data>
|
|
25
|
+
T5KCwCY0ClcKPkpDLsgIpWtncVU=
|
|
26
|
+
</data>
|
|
27
|
+
<key>Modules/Testing.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
|
|
28
|
+
<data>
|
|
29
|
+
vlvfqNEcW76pCg0WUmpNHb1ogAI=
|
|
30
|
+
</data>
|
|
31
|
+
<key>version.plist</key>
|
|
32
|
+
<data>
|
|
33
|
+
UKZHpwJYM1oHWth3RENO38S/hAk=
|
|
34
|
+
</data>
|
|
35
|
+
</dict>
|
|
36
|
+
<key>files2</key>
|
|
37
|
+
<dict>
|
|
38
|
+
<key>Modules/Testing.swiftcrossimport/Foundation.swiftoverlay</key>
|
|
39
|
+
<dict>
|
|
40
|
+
<key>hash2</key>
|
|
41
|
+
<data>
|
|
42
|
+
zXQFaqVc3q2xEVpQ0j8FbSpWomb4cEKThbS+u0bNRqA=
|
|
43
|
+
</data>
|
|
44
|
+
</dict>
|
|
45
|
+
<key>Modules/Testing.swiftmodule/arm64-apple-ios-simulator.swiftdoc</key>
|
|
46
|
+
<dict>
|
|
47
|
+
<key>hash2</key>
|
|
48
|
+
<data>
|
|
49
|
+
jD9DfdV3UfXNyZgwMq6gZb3bD7WzxfD1zB6WwK/Toxs=
|
|
50
|
+
</data>
|
|
51
|
+
</dict>
|
|
52
|
+
<key>Modules/Testing.swiftmodule/arm64-apple-ios-simulator.swiftinterface</key>
|
|
53
|
+
<dict>
|
|
54
|
+
<key>hash2</key>
|
|
55
|
+
<data>
|
|
56
|
+
u7INua8w8TKpND0tBvHsTE2rNCXqyL80iZYNh9jEjIo=
|
|
57
|
+
</data>
|
|
58
|
+
</dict>
|
|
59
|
+
<key>Modules/Testing.swiftmodule/x86_64-apple-ios-simulator.swiftdoc</key>
|
|
60
|
+
<dict>
|
|
61
|
+
<key>hash2</key>
|
|
62
|
+
<data>
|
|
63
|
+
A4zfGU0RRcwKPRkRrFAbitDtCyIVvtv9c0JYEHYXD9s=
|
|
64
|
+
</data>
|
|
65
|
+
</dict>
|
|
66
|
+
<key>Modules/Testing.swiftmodule/x86_64-apple-ios-simulator.swiftinterface</key>
|
|
67
|
+
<dict>
|
|
68
|
+
<key>hash2</key>
|
|
69
|
+
<data>
|
|
70
|
+
0xDtFiKqRf8bI9+m3Ia6Ohd2Bcb0xbgRO20lr/6DcXQ=
|
|
71
|
+
</data>
|
|
72
|
+
</dict>
|
|
73
|
+
<key>version.plist</key>
|
|
74
|
+
<dict>
|
|
75
|
+
<key>hash2</key>
|
|
76
|
+
<data>
|
|
77
|
+
my0P7TCuxHFpQDCTUZvZvZe27VSXLxkFex01dT35YeU=
|
|
78
|
+
</data>
|
|
79
|
+
</dict>
|
|
80
|
+
</dict>
|
|
81
|
+
<key>rules</key>
|
|
82
|
+
<dict>
|
|
83
|
+
<key>^.*</key>
|
|
84
|
+
<true/>
|
|
85
|
+
<key>^.*\.lproj/</key>
|
|
86
|
+
<dict>
|
|
87
|
+
<key>optional</key>
|
|
88
|
+
<true/>
|
|
89
|
+
<key>weight</key>
|
|
90
|
+
<real>1000</real>
|
|
91
|
+
</dict>
|
|
92
|
+
<key>^.*\.lproj/locversion.plist$</key>
|
|
93
|
+
<dict>
|
|
94
|
+
<key>omit</key>
|
|
95
|
+
<true/>
|
|
96
|
+
<key>weight</key>
|
|
97
|
+
<real>1100</real>
|
|
98
|
+
</dict>
|
|
99
|
+
<key>^Base\.lproj/</key>
|
|
100
|
+
<dict>
|
|
101
|
+
<key>weight</key>
|
|
102
|
+
<real>1010</real>
|
|
103
|
+
</dict>
|
|
104
|
+
<key>^version.plist$</key>
|
|
105
|
+
<true/>
|
|
106
|
+
</dict>
|
|
107
|
+
<key>rules2</key>
|
|
108
|
+
<dict>
|
|
109
|
+
<key>.*\.dSYM($|/)</key>
|
|
110
|
+
<dict>
|
|
111
|
+
<key>weight</key>
|
|
112
|
+
<real>11</real>
|
|
113
|
+
</dict>
|
|
114
|
+
<key>^(.*/)?\.DS_Store$</key>
|
|
115
|
+
<dict>
|
|
116
|
+
<key>omit</key>
|
|
117
|
+
<true/>
|
|
118
|
+
<key>weight</key>
|
|
119
|
+
<real>2000</real>
|
|
120
|
+
</dict>
|
|
121
|
+
<key>^.*</key>
|
|
122
|
+
<true/>
|
|
123
|
+
<key>^.*\.lproj/</key>
|
|
124
|
+
<dict>
|
|
125
|
+
<key>optional</key>
|
|
126
|
+
<true/>
|
|
127
|
+
<key>weight</key>
|
|
128
|
+
<real>1000</real>
|
|
129
|
+
</dict>
|
|
130
|
+
<key>^.*\.lproj/locversion.plist$</key>
|
|
131
|
+
<dict>
|
|
132
|
+
<key>omit</key>
|
|
133
|
+
<true/>
|
|
134
|
+
<key>weight</key>
|
|
135
|
+
<real>1100</real>
|
|
136
|
+
</dict>
|
|
137
|
+
<key>^Base\.lproj/</key>
|
|
138
|
+
<dict>
|
|
139
|
+
<key>weight</key>
|
|
140
|
+
<real>1010</real>
|
|
141
|
+
</dict>
|
|
142
|
+
<key>^Info\.plist$</key>
|
|
143
|
+
<dict>
|
|
144
|
+
<key>omit</key>
|
|
145
|
+
<true/>
|
|
146
|
+
<key>weight</key>
|
|
147
|
+
<real>20</real>
|
|
148
|
+
</dict>
|
|
149
|
+
<key>^PkgInfo$</key>
|
|
150
|
+
<dict>
|
|
151
|
+
<key>omit</key>
|
|
152
|
+
<true/>
|
|
153
|
+
<key>weight</key>
|
|
154
|
+
<real>20</real>
|
|
155
|
+
</dict>
|
|
156
|
+
<key>^embedded\.provisionprofile$</key>
|
|
157
|
+
<dict>
|
|
158
|
+
<key>weight</key>
|
|
159
|
+
<real>20</real>
|
|
160
|
+
</dict>
|
|
161
|
+
<key>^version\.plist$</key>
|
|
162
|
+
<dict>
|
|
163
|
+
<key>weight</key>
|
|
164
|
+
<real>20</real>
|
|
165
|
+
</dict>
|
|
166
|
+
</dict>
|
|
167
|
+
</dict>
|
|
168
|
+
</plist>
|
|
@@ -0,0 +1,18 @@
|
|
|
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>BuildAliasOf</key>
|
|
6
|
+
<string>Citrine</string>
|
|
7
|
+
<key>BuildVersion</key>
|
|
8
|
+
<string>2</string>
|
|
9
|
+
<key>CFBundleShortVersionString</key>
|
|
10
|
+
<string>1.0</string>
|
|
11
|
+
<key>CFBundleVersion</key>
|
|
12
|
+
<string>1085</string>
|
|
13
|
+
<key>ProjectName</key>
|
|
14
|
+
<string>Citrine_iOS_Sim</string>
|
|
15
|
+
<key>SourceVersion</key>
|
|
16
|
+
<string>1085000000000000</string>
|
|
17
|
+
</dict>
|
|
18
|
+
</plist>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,113 @@
|
|
|
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>files</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>Info.plist</key>
|
|
8
|
+
<data>
|
|
9
|
+
gjUskOFiGiPbBpPvJRIodZ7dvBw=
|
|
10
|
+
</data>
|
|
11
|
+
<key>version.plist</key>
|
|
12
|
+
<data>
|
|
13
|
+
OcHVp7Cjygj8YmKg7UmkGH+41W4=
|
|
14
|
+
</data>
|
|
15
|
+
</dict>
|
|
16
|
+
<key>files2</key>
|
|
17
|
+
<dict>
|
|
18
|
+
<key>version.plist</key>
|
|
19
|
+
<dict>
|
|
20
|
+
<key>hash2</key>
|
|
21
|
+
<data>
|
|
22
|
+
0gyv66SuXc34bhL1M8cUPjPYaTwbZn8WldhEyQ69bK0=
|
|
23
|
+
</data>
|
|
24
|
+
</dict>
|
|
25
|
+
</dict>
|
|
26
|
+
<key>rules</key>
|
|
27
|
+
<dict>
|
|
28
|
+
<key>^.*</key>
|
|
29
|
+
<true/>
|
|
30
|
+
<key>^.*\.lproj/</key>
|
|
31
|
+
<dict>
|
|
32
|
+
<key>optional</key>
|
|
33
|
+
<true/>
|
|
34
|
+
<key>weight</key>
|
|
35
|
+
<real>1000</real>
|
|
36
|
+
</dict>
|
|
37
|
+
<key>^.*\.lproj/locversion.plist$</key>
|
|
38
|
+
<dict>
|
|
39
|
+
<key>omit</key>
|
|
40
|
+
<true/>
|
|
41
|
+
<key>weight</key>
|
|
42
|
+
<real>1100</real>
|
|
43
|
+
</dict>
|
|
44
|
+
<key>^Base\.lproj/</key>
|
|
45
|
+
<dict>
|
|
46
|
+
<key>weight</key>
|
|
47
|
+
<real>1010</real>
|
|
48
|
+
</dict>
|
|
49
|
+
<key>^version.plist$</key>
|
|
50
|
+
<true/>
|
|
51
|
+
</dict>
|
|
52
|
+
<key>rules2</key>
|
|
53
|
+
<dict>
|
|
54
|
+
<key>.*\.dSYM($|/)</key>
|
|
55
|
+
<dict>
|
|
56
|
+
<key>weight</key>
|
|
57
|
+
<real>11</real>
|
|
58
|
+
</dict>
|
|
59
|
+
<key>^(.*/)?\.DS_Store$</key>
|
|
60
|
+
<dict>
|
|
61
|
+
<key>omit</key>
|
|
62
|
+
<true/>
|
|
63
|
+
<key>weight</key>
|
|
64
|
+
<real>2000</real>
|
|
65
|
+
</dict>
|
|
66
|
+
<key>^.*</key>
|
|
67
|
+
<true/>
|
|
68
|
+
<key>^.*\.lproj/</key>
|
|
69
|
+
<dict>
|
|
70
|
+
<key>optional</key>
|
|
71
|
+
<true/>
|
|
72
|
+
<key>weight</key>
|
|
73
|
+
<real>1000</real>
|
|
74
|
+
</dict>
|
|
75
|
+
<key>^.*\.lproj/locversion.plist$</key>
|
|
76
|
+
<dict>
|
|
77
|
+
<key>omit</key>
|
|
78
|
+
<true/>
|
|
79
|
+
<key>weight</key>
|
|
80
|
+
<real>1100</real>
|
|
81
|
+
</dict>
|
|
82
|
+
<key>^Base\.lproj/</key>
|
|
83
|
+
<dict>
|
|
84
|
+
<key>weight</key>
|
|
85
|
+
<real>1010</real>
|
|
86
|
+
</dict>
|
|
87
|
+
<key>^Info\.plist$</key>
|
|
88
|
+
<dict>
|
|
89
|
+
<key>omit</key>
|
|
90
|
+
<true/>
|
|
91
|
+
<key>weight</key>
|
|
92
|
+
<real>20</real>
|
|
93
|
+
</dict>
|
|
94
|
+
<key>^PkgInfo$</key>
|
|
95
|
+
<dict>
|
|
96
|
+
<key>omit</key>
|
|
97
|
+
<true/>
|
|
98
|
+
<key>weight</key>
|
|
99
|
+
<real>20</real>
|
|
100
|
+
</dict>
|
|
101
|
+
<key>^embedded\.provisionprofile$</key>
|
|
102
|
+
<dict>
|
|
103
|
+
<key>weight</key>
|
|
104
|
+
<real>20</real>
|
|
105
|
+
</dict>
|
|
106
|
+
<key>^version\.plist$</key>
|
|
107
|
+
<dict>
|
|
108
|
+
<key>weight</key>
|
|
109
|
+
<real>20</real>
|
|
110
|
+
</dict>
|
|
111
|
+
</dict>
|
|
112
|
+
</dict>
|
|
113
|
+
</plist>
|