@independo/capacitor-inderun 1.0.0 → 1.1.0-dev.1
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/Package.swift +5 -1
- package/README.md +79 -5
- package/android/build.gradle.kts +5 -5
- package/android/src/main/kotlin/app/independo/inderun/capacitor/IndeRunCapacitorPlugin.kt +119 -0
- package/android/src/main/kotlin/app/independo/inderun/capacitor/IndeRunSerializer.kt +106 -1
- package/android/src/main/kotlin/app/independo/inderun/capacitor/IndeRunStreamRegistry.kt +118 -0
- package/android/src/test/kotlin/app/independo/inderun/capacitor/IndeRunSerializerStreamTest.kt +226 -0
- package/android/src/test/kotlin/app/independo/inderun/capacitor/IndeRunStreamRegistryTest.kt +163 -0
- package/dist/definitions.d.ts +54 -1
- package/dist/definitions.d.ts.map +1 -1
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +36 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -13
- package/dist/streaming.d.ts +17 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +303 -0
- package/dist/web.d.ts +17 -2
- package/dist/web.d.ts.map +1 -1
- package/dist/web.js +70 -0
- package/ios/Sources/IndeRunCapacitorPlugin/IndeRunCapacitorBridge.swift +134 -0
- package/ios/Sources/IndeRunCapacitorPlugin/IndeRunCapacitorPlugin.swift +70 -1
- package/ios/Sources/IndeRunCapacitorPlugin/IndeRunCapacitorStreamRegistry.swift +121 -0
- package/ios/Tests/IndeRunCapacitorTests/IndeRunCapacitorBridgeTests.swift +31 -1
- package/ios/Tests/IndeRunCapacitorTests/IndeRunCapacitorStreamCodecTests.swift +178 -0
- package/ios/Tests/IndeRunCapacitorTests/IndeRunCapacitorStreamPumpTests.swift +215 -0
- package/ios/Tests/IndeRunCapacitorTests/IndeRunCapacitorStreamRegistryTests.swift +154 -0
- package/package.json +3 -3
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
import Foundation
|
|
3
|
+
import IndeRunContracts
|
|
4
|
+
import IndeRunCore
|
|
5
|
+
@testable import IndeRunCapacitorPlugin
|
|
6
|
+
|
|
7
|
+
/// Records the cancel calls a fake `StreamRun` receives, so a test can assert both
|
|
8
|
+
/// that a cancel arrived and what reason it carried.
|
|
9
|
+
private final class CancelRecorder: @unchecked Sendable {
|
|
10
|
+
private let lock = NSLock()
|
|
11
|
+
private var calls: [String?] = []
|
|
12
|
+
|
|
13
|
+
func record(_ reason: String?) {
|
|
14
|
+
lock.lock()
|
|
15
|
+
defer { lock.unlock() }
|
|
16
|
+
calls.append(reason)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var count: Int {
|
|
20
|
+
lock.lock()
|
|
21
|
+
defer { lock.unlock() }
|
|
22
|
+
return calls.count
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var reasons: [String?] {
|
|
26
|
+
lock.lock()
|
|
27
|
+
defer { lock.unlock() }
|
|
28
|
+
return calls
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
final class IndeRunCapacitorStreamRegistryTests: XCTestCase {
|
|
33
|
+
|
|
34
|
+
private func makeRun(recorder: CancelRecorder) -> StreamRun {
|
|
35
|
+
let (events, continuation) = AsyncThrowingStream<StreamEvent, Error>.makeStream()
|
|
36
|
+
continuation.finish()
|
|
37
|
+
return StreamRun(
|
|
38
|
+
handle: StreamRunHandle(
|
|
39
|
+
providerId: nil,
|
|
40
|
+
runId: "run_1",
|
|
41
|
+
schemaVersion: .the10,
|
|
42
|
+
startedAt: 1_700_000_000_000
|
|
43
|
+
),
|
|
44
|
+
events: events,
|
|
45
|
+
cancel: { reason in recorder.record(reason) }
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
func testAttachesAndFinishesByStreamId() {
|
|
50
|
+
let registry = StreamRegistry()
|
|
51
|
+
let recorder = CancelRecorder()
|
|
52
|
+
|
|
53
|
+
registry.open(streamId: "s1")
|
|
54
|
+
XCTAssertEqual(registry.attach(streamId: "s1", run: makeRun(recorder: recorder)), .attached)
|
|
55
|
+
XCTAssertEqual(registry.activeCount, 1)
|
|
56
|
+
|
|
57
|
+
registry.finish(streamId: "s1")
|
|
58
|
+
XCTAssertEqual(registry.activeCount, 0)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/// A cancel can beat the engine's route selection. It must be held and applied
|
|
62
|
+
/// when the run finally attaches, not dropped.
|
|
63
|
+
func testCancelBeforeAttachIsAppliedOnAttachWithItsReason() {
|
|
64
|
+
let registry = StreamRegistry()
|
|
65
|
+
let recorder = CancelRecorder()
|
|
66
|
+
|
|
67
|
+
registry.open(streamId: "s1")
|
|
68
|
+
registry.requestCancel(streamId: "s1", reason: "user left")
|
|
69
|
+
// Nothing to cancel yet, so nothing was called.
|
|
70
|
+
XCTAssertEqual(recorder.count, 0)
|
|
71
|
+
|
|
72
|
+
let outcome = registry.attach(streamId: "s1", run: makeRun(recorder: recorder))
|
|
73
|
+
XCTAssertEqual(outcome, .cancelRequested(reason: "user left"))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
func testCancelAfterFinishIsANoOp() {
|
|
77
|
+
let registry = StreamRegistry()
|
|
78
|
+
let recorder = CancelRecorder()
|
|
79
|
+
|
|
80
|
+
registry.open(streamId: "s1")
|
|
81
|
+
registry.attach(streamId: "s1", run: makeRun(recorder: recorder))
|
|
82
|
+
registry.finish(streamId: "s1")
|
|
83
|
+
|
|
84
|
+
registry.requestCancel(streamId: "s1", reason: "too late")
|
|
85
|
+
XCTAssertEqual(recorder.count, 0)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
func testCancelForAnUnknownStreamIdIsANoOp() {
|
|
89
|
+
let registry = StreamRegistry()
|
|
90
|
+
registry.requestCancel(streamId: "never_opened", reason: nil)
|
|
91
|
+
XCTAssertEqual(registry.activeCount, 0)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
func testRepeatedCancelCancelsTheRunExactlyOnce() {
|
|
95
|
+
let registry = StreamRegistry()
|
|
96
|
+
let recorder = CancelRecorder()
|
|
97
|
+
|
|
98
|
+
registry.open(streamId: "s1")
|
|
99
|
+
registry.attach(streamId: "s1", run: makeRun(recorder: recorder))
|
|
100
|
+
|
|
101
|
+
registry.requestCancel(streamId: "s1", reason: "first")
|
|
102
|
+
registry.requestCancel(streamId: "s1", reason: "second")
|
|
103
|
+
|
|
104
|
+
XCTAssertEqual(recorder.reasons, ["first"])
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
func testConcurrentStreamsAreIsolated() {
|
|
108
|
+
let registry = StreamRegistry()
|
|
109
|
+
let first = CancelRecorder()
|
|
110
|
+
let second = CancelRecorder()
|
|
111
|
+
|
|
112
|
+
registry.open(streamId: "s1")
|
|
113
|
+
registry.open(streamId: "s2")
|
|
114
|
+
registry.attach(streamId: "s1", run: makeRun(recorder: first))
|
|
115
|
+
registry.attach(streamId: "s2", run: makeRun(recorder: second))
|
|
116
|
+
|
|
117
|
+
registry.requestCancel(streamId: "s1", reason: "only the first")
|
|
118
|
+
|
|
119
|
+
XCTAssertEqual(first.reasons, ["only the first"])
|
|
120
|
+
XCTAssertEqual(second.count, 0)
|
|
121
|
+
XCTAssertEqual(registry.activeCount, 2)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
func testCancelAllCancelsEveryRunOnceAndEmptiesTheRegistry() {
|
|
125
|
+
let registry = StreamRegistry()
|
|
126
|
+
let first = CancelRecorder()
|
|
127
|
+
let second = CancelRecorder()
|
|
128
|
+
|
|
129
|
+
registry.open(streamId: "s1")
|
|
130
|
+
registry.open(streamId: "s2")
|
|
131
|
+
registry.attach(streamId: "s1", run: makeRun(recorder: first))
|
|
132
|
+
registry.attach(streamId: "s2", run: makeRun(recorder: second))
|
|
133
|
+
|
|
134
|
+
registry.cancelAll(reason: "torn down")
|
|
135
|
+
|
|
136
|
+
XCTAssertEqual(first.reasons, ["torn down"])
|
|
137
|
+
XCTAssertEqual(second.reasons, ["torn down"])
|
|
138
|
+
XCTAssertEqual(registry.activeCount, 0)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
func testAttachAfterTeardownReportsCancelRequested() {
|
|
142
|
+
let registry = StreamRegistry()
|
|
143
|
+
let recorder = CancelRecorder()
|
|
144
|
+
|
|
145
|
+
registry.open(streamId: "s1")
|
|
146
|
+
registry.cancelAll(reason: "torn down")
|
|
147
|
+
|
|
148
|
+
// The entry is gone, so the run that arrives late must be cancelled by its caller.
|
|
149
|
+
XCTAssertEqual(
|
|
150
|
+
registry.attach(streamId: "s1", run: makeRun(recorder: recorder)),
|
|
151
|
+
.cancelRequested(reason: nil)
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@independo/capacitor-inderun",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.1.0-dev.1",
|
|
4
4
|
"description": "Thin Capacitor bridge for IndeRun across web, iOS, and Android.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/independo-gmbh/capacitor-inderun#readme",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@capacitor/core": "^8.0.0",
|
|
61
|
-
"@independo/inderun-contracts": "
|
|
62
|
-
"@independo/inderun-web": "
|
|
61
|
+
"@independo/inderun-contracts": "0.3.0-dev.14",
|
|
62
|
+
"@independo/inderun-web": "0.3.0-dev.14"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@saithodev/semantic-release-backmerge": "^4.0.1",
|