@trainstar/synchro-react-native 0.4.0-rc.2 → 0.4.0-rc.4
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/README.md +40 -10
- package/SynchroReactNative.podspec +3 -1
- package/android/build.gradle +8 -7
- package/android/src/androidTest/kotlin/com/trainstar/synchro/rn/SynchroModuleTransactionTest.kt +7 -10
- package/ios/SynchroModule.swift +953 -713
- package/ios/SynchroOwnership.swift +173 -0
- package/ios-test-host/{main.m → AppDelegate.m} +0 -7
- package/ios-test-host/main.swift +12 -0
- package/ios-tests/SynchroModuleTransactionTests.swift +320 -35
- package/ios-tests/TransactionSessionTests.swift +167 -12
- package/lib/module/NativeSynchro.js.map +1 -1
- package/lib/typescript/src/NativeSynchro.d.ts +13 -14
- package/lib/typescript/src/NativeSynchro.d.ts.map +1 -1
- package/package.json +12 -8
- package/src/NativeSynchro.ts +13 -17
- package/tooling-patches/apply.cjs +82 -1
- package/tooling-patches/react-native-gradle-plugin-0.82.1-kotlin-2.4.21.patch +131 -0
- package/tooling-patches/react-native-gradle-plugin-0.88.0-kotlin-2.4.21.patch +30 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@testable import SynchroReactNative
|
|
2
|
+
import os
|
|
2
3
|
import XCTest
|
|
3
4
|
|
|
4
5
|
private struct SessionError: Error, Equatable {
|
|
@@ -6,21 +7,95 @@ private struct SessionError: Error, Equatable {
|
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
/// Records the begin completions that the actual session delivers.
|
|
9
|
-
private final class BeginRecorder {
|
|
10
|
-
private
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
results.append(result)
|
|
10
|
+
private final class BeginRecorder: Sendable {
|
|
11
|
+
private struct State: Sendable {
|
|
12
|
+
var successes: [String] = []
|
|
13
|
+
var failures: [SessionError?] = []
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
private let state = OSAllocatedUnfairLock(initialState: State())
|
|
17
|
+
|
|
16
18
|
var successes: [String] {
|
|
17
|
-
|
|
19
|
+
state.withLock { $0.successes }
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
var failures: [SessionError?] {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
state.withLock { $0.failures }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func settlement() -> ReactPromiseSettlement {
|
|
27
|
+
ReactPromiseSettlement(
|
|
28
|
+
resolve: { [self] value in
|
|
29
|
+
let stringValue = value as? String
|
|
30
|
+
state.withLock { state in
|
|
31
|
+
if let stringValue {
|
|
32
|
+
state.successes.append(stringValue)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
reject: { [self] _, _, error in
|
|
37
|
+
state.withLock { $0.failures.append(error as? SessionError) }
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private final class SettlementCounter: Sendable {
|
|
44
|
+
private let countState = OSAllocatedUnfairLock(initialState: 0)
|
|
45
|
+
|
|
46
|
+
var count: Int {
|
|
47
|
+
countState.withLock { $0 }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func increment() {
|
|
51
|
+
countState.withLock { $0 += 1 }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private final class EventRecorder: NSObject, SynchroEventEmitting {
|
|
56
|
+
private struct State {
|
|
57
|
+
var name: String?
|
|
58
|
+
var body: NSDictionary?
|
|
59
|
+
var deliveredOnMain = false
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private let state = NSLock()
|
|
63
|
+
private var value = State()
|
|
64
|
+
let expectation: XCTestExpectation
|
|
65
|
+
|
|
66
|
+
init(expectation: XCTestExpectation) {
|
|
67
|
+
self.expectation = expectation
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func emitEvent(_ name: String, body: NSDictionary) {
|
|
71
|
+
state.lock()
|
|
72
|
+
value.name = name
|
|
73
|
+
value.body = body
|
|
74
|
+
value.deliveredOnMain = Thread.isMainThread
|
|
75
|
+
state.unlock()
|
|
76
|
+
expectation.fulfill()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
func snapshot() -> (String?, NSDictionary?, Bool) {
|
|
80
|
+
state.lock()
|
|
81
|
+
defer { state.unlock() }
|
|
82
|
+
return (value.name, value.body, value.deliveredOnMain)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private struct AuthStoreTimeout: Error {}
|
|
87
|
+
|
|
88
|
+
private func pendingAuthRequest(
|
|
89
|
+
_ store: AuthRequestStore,
|
|
90
|
+
id: String,
|
|
91
|
+
insertion: CheckedContinuation<Bool, Never>
|
|
92
|
+
) async throws -> String {
|
|
93
|
+
try await withCheckedThrowingContinuation { continuation in
|
|
94
|
+
let inserted = store.insert(continuation, for: id)
|
|
95
|
+
insertion.resume(returning: inserted)
|
|
96
|
+
guard inserted else {
|
|
97
|
+
continuation.resume(throwing: AuthStoreTimeout())
|
|
98
|
+
return
|
|
24
99
|
}
|
|
25
100
|
}
|
|
26
101
|
}
|
|
@@ -29,7 +104,7 @@ private final class BeginRecorder {
|
|
|
29
104
|
final class TransactionSessionTests: XCTestCase {
|
|
30
105
|
func testFailureBeforeCallbackRejectsStoredBeginOnce() {
|
|
31
106
|
let begin = BeginRecorder()
|
|
32
|
-
let session = TransactionSession(isWrite: true,
|
|
107
|
+
let session = TransactionSession(isWrite: true, beginSettlement: begin.settlement())
|
|
33
108
|
|
|
34
109
|
session.rejectBegin(SessionError(name: "acquisition"))
|
|
35
110
|
session.rejectBegin(SessionError(name: "later failure"))
|
|
@@ -40,7 +115,7 @@ final class TransactionSessionTests: XCTestCase {
|
|
|
40
115
|
|
|
41
116
|
func testAbortBeforeBeginAcceptanceRejectsBeginAndUnwindsCallback() {
|
|
42
117
|
let begin = BeginRecorder()
|
|
43
|
-
let session = TransactionSession(isWrite: true,
|
|
118
|
+
let session = TransactionSession(isWrite: true, beginSettlement: begin.settlement())
|
|
44
119
|
|
|
45
120
|
session.abort(SessionError(name: "close"))
|
|
46
121
|
XCTAssertThrowsError(try session.acceptBegin("abort-before-begin")) { error in
|
|
@@ -54,7 +129,7 @@ final class TransactionSessionTests: XCTestCase {
|
|
|
54
129
|
|
|
55
130
|
func testAcceptedBeginIsNotSettledAgainByLaterFailure() throws {
|
|
56
131
|
let begin = BeginRecorder()
|
|
57
|
-
let session = TransactionSession(isWrite: true,
|
|
132
|
+
let session = TransactionSession(isWrite: true, beginSettlement: begin.settlement())
|
|
58
133
|
|
|
59
134
|
try session.acceptBegin("accepted")
|
|
60
135
|
session.abort(SessionError(name: "close"))
|
|
@@ -63,4 +138,84 @@ final class TransactionSessionTests: XCTestCase {
|
|
|
63
138
|
XCTAssertEqual(begin.successes, ["accepted"])
|
|
64
139
|
XCTAssertEqual(begin.failures, [])
|
|
65
140
|
}
|
|
141
|
+
|
|
142
|
+
func testPromiseSettlementRaceInvokesOneBlock() {
|
|
143
|
+
let counter = SettlementCounter()
|
|
144
|
+
let settlement = ReactPromiseSettlement(
|
|
145
|
+
resolve: { _ in counter.increment() },
|
|
146
|
+
reject: { _, _, _ in counter.increment() }
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
DispatchQueue.concurrentPerform(iterations: 100) { index in
|
|
150
|
+
if index.isMultiple(of: 2) {
|
|
151
|
+
settlement.resolve(.void)
|
|
152
|
+
} else {
|
|
153
|
+
settlement.reject("TEST", "test", nil)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
XCTAssertEqual(counter.count, 1)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
func testPromiseSettlementUnlocksBeforeReentrantInvocation() {
|
|
161
|
+
let counter = SettlementCounter()
|
|
162
|
+
let holder = OSAllocatedUnfairLock<ReactPromiseSettlement?>(initialState: nil)
|
|
163
|
+
let settlement = ReactPromiseSettlement(
|
|
164
|
+
resolve: { _ in
|
|
165
|
+
counter.increment()
|
|
166
|
+
holder.withLock { $0 }?.reject("REENTRANT", "reentrant", nil)
|
|
167
|
+
},
|
|
168
|
+
reject: { _, _, _ in counter.increment() }
|
|
169
|
+
)
|
|
170
|
+
holder.withLock { $0 = settlement }
|
|
171
|
+
|
|
172
|
+
settlement.resolve(.void)
|
|
173
|
+
|
|
174
|
+
XCTAssertEqual(counter.count, 1)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
func testEventTargetIsWeakAndDeliversOnMain() {
|
|
178
|
+
let event = expectation(description: "event")
|
|
179
|
+
let target = ReactEventTarget()
|
|
180
|
+
var recorder: EventRecorder? = EventRecorder(expectation: event)
|
|
181
|
+
target.setDelegate(recorder)
|
|
182
|
+
|
|
183
|
+
target.emit("onTest", body: .object(["value": .string("ok")]))
|
|
184
|
+
wait(for: [event], timeout: 1)
|
|
185
|
+
|
|
186
|
+
let snapshot = recorder?.snapshot()
|
|
187
|
+
XCTAssertEqual(snapshot?.0, "onTest")
|
|
188
|
+
XCTAssertEqual(snapshot?.1?["value"] as? String, "ok")
|
|
189
|
+
XCTAssertEqual(snapshot?.2, true)
|
|
190
|
+
|
|
191
|
+
weak let weakRecorder = recorder
|
|
192
|
+
recorder = nil
|
|
193
|
+
XCTAssertNil(weakRecorder)
|
|
194
|
+
XCTAssertNil(target.currentDelegate)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
func testAuthStoreCloseRejectsPendingAndIgnoresLateCompletion() async throws {
|
|
198
|
+
let store = AuthRequestStore()
|
|
199
|
+
store.activate()
|
|
200
|
+
var pendingTask: Task<String, Error>?
|
|
201
|
+
let inserted = await withCheckedContinuation { insertion in
|
|
202
|
+
pendingTask = Task {
|
|
203
|
+
try await pendingAuthRequest(store, id: "request", insertion: insertion)
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
XCTAssertTrue(inserted)
|
|
207
|
+
XCTAssertEqual(store.count, 1)
|
|
208
|
+
let task = try XCTUnwrap(pendingTask)
|
|
209
|
+
|
|
210
|
+
store.cancelAll()
|
|
211
|
+
store.resolve("request", token: "late")
|
|
212
|
+
|
|
213
|
+
do {
|
|
214
|
+
_ = try await task.value
|
|
215
|
+
XCTFail("Expected close to reject the request")
|
|
216
|
+
} catch {
|
|
217
|
+
XCTAssertEqual((error as NSError).domain, "SynchroModule")
|
|
218
|
+
}
|
|
219
|
+
XCTAssertEqual(store.count, 0)
|
|
220
|
+
}
|
|
66
221
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSynchro.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeSynchro.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAElD;AACA;AACA;;AAgLA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,eAAe,CAAC","ignoreList":[]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { TurboModule } from 'react-native';
|
|
2
|
-
|
|
3
|
-
type
|
|
4
|
-
type NativeRow = UnsafeObject;
|
|
1
|
+
import type { CodegenTypes, TurboModule } from 'react-native';
|
|
2
|
+
type NativeSQLiteBindValue = string | number | boolean | null | CodegenTypes.UnsafeObject;
|
|
3
|
+
type NativeRow = CodegenTypes.UnsafeObject;
|
|
5
4
|
type NativeSQLStatement = {
|
|
6
5
|
sql: string;
|
|
7
6
|
params: ReadonlyArray<NativeSQLiteBindValue>;
|
|
@@ -10,7 +9,7 @@ type StatusEvent = {
|
|
|
10
9
|
status: string;
|
|
11
10
|
retryAt: string | null;
|
|
12
11
|
operation: string | null;
|
|
13
|
-
failure: UnsafeObject | null;
|
|
12
|
+
failure: CodegenTypes.UnsafeObject | null;
|
|
14
13
|
};
|
|
15
14
|
type ConflictEvent = {
|
|
16
15
|
table: string;
|
|
@@ -25,8 +24,8 @@ type SyncEvent = {
|
|
|
25
24
|
operation: string | null;
|
|
26
25
|
attempt: number | null;
|
|
27
26
|
retryAt: string | null;
|
|
28
|
-
source: UnsafeObject | null;
|
|
29
|
-
target: UnsafeObject | null;
|
|
27
|
+
source: CodegenTypes.UnsafeObject | null;
|
|
28
|
+
target: CodegenTypes.UnsafeObject | null;
|
|
30
29
|
action: string | null;
|
|
31
30
|
mutationID: string | null;
|
|
32
31
|
tableID: string | null;
|
|
@@ -34,7 +33,7 @@ type SyncEvent = {
|
|
|
34
33
|
rejectionCode: string | null;
|
|
35
34
|
scopeID: string | null;
|
|
36
35
|
rebuildID: string | null;
|
|
37
|
-
failure: UnsafeObject | null;
|
|
36
|
+
failure: CodegenTypes.UnsafeObject | null;
|
|
38
37
|
};
|
|
39
38
|
type AuthRequestEvent = {
|
|
40
39
|
requestID: string;
|
|
@@ -118,12 +117,12 @@ export interface Spec extends TurboModule {
|
|
|
118
117
|
clearRejectedMutations(): Promise<void>;
|
|
119
118
|
resolveAuthRequest(requestID: string, token: string): void;
|
|
120
119
|
rejectAuthRequest(requestID: string, error: string): void;
|
|
121
|
-
readonly onStatusChange: EventEmitter<StatusEvent>;
|
|
122
|
-
readonly onSyncEvent: EventEmitter<SyncEvent>;
|
|
123
|
-
readonly onConflict: EventEmitter<ConflictEvent>;
|
|
124
|
-
readonly onAuthRequest: EventEmitter<AuthRequestEvent>;
|
|
125
|
-
readonly onChange: EventEmitter<ChangeEvent>;
|
|
126
|
-
readonly onQueryResult: EventEmitter<QueryResultEvent>;
|
|
120
|
+
readonly onStatusChange: CodegenTypes.EventEmitter<StatusEvent>;
|
|
121
|
+
readonly onSyncEvent: CodegenTypes.EventEmitter<SyncEvent>;
|
|
122
|
+
readonly onConflict: CodegenTypes.EventEmitter<ConflictEvent>;
|
|
123
|
+
readonly onAuthRequest: CodegenTypes.EventEmitter<AuthRequestEvent>;
|
|
124
|
+
readonly onChange: CodegenTypes.EventEmitter<ChangeEvent>;
|
|
125
|
+
readonly onQueryResult: CodegenTypes.EventEmitter<QueryResultEvent>;
|
|
127
126
|
addListener(eventName: string): void;
|
|
128
127
|
removeListeners(count: number): void;
|
|
129
128
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeSynchro.d.ts","sourceRoot":"","sources":["../../../src/NativeSynchro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeSynchro.d.ts","sourceRoot":"","sources":["../../../src/NativeSynchro.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trainstar/synchro-react-native",
|
|
3
|
-
"version": "0.4.0-rc.
|
|
3
|
+
"version": "0.4.0-rc.4",
|
|
4
4
|
"description": "React Native bridge for Synchro sync SDK",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"./tooling-patches/cli-config-android-20.2.0.patch": "./tooling-patches/cli-config-android-20.2.0.patch",
|
|
21
21
|
"./tooling-patches/cli-clean-20.2.0.patch": "./tooling-patches/cli-clean-20.2.0.patch",
|
|
22
22
|
"./tooling-patches/react-native-builder-bob-0.40.18.patch": "./tooling-patches/react-native-builder-bob-0.40.18.patch",
|
|
23
|
+
"./tooling-patches/react-native-gradle-plugin-0.82.1-kotlin-2.4.21.patch": "./tooling-patches/react-native-gradle-plugin-0.82.1-kotlin-2.4.21.patch",
|
|
24
|
+
"./tooling-patches/react-native-gradle-plugin-0.88.0-kotlin-2.4.21.patch": "./tooling-patches/react-native-gradle-plugin-0.88.0-kotlin-2.4.21.patch",
|
|
23
25
|
"./tooling-patches/stream-json-1.9.1.patch": "./tooling-patches/stream-json-1.9.1.patch",
|
|
24
26
|
"./package.json": "./package.json"
|
|
25
27
|
},
|
|
@@ -76,25 +78,26 @@
|
|
|
76
78
|
"node": ">=20.19.4"
|
|
77
79
|
},
|
|
78
80
|
"devDependencies": {
|
|
79
|
-
"@react-native/babel-preset": "0.
|
|
81
|
+
"@react-native/babel-preset": "0.88.0",
|
|
82
|
+
"@react-native/jest-preset": "0.88.0",
|
|
80
83
|
"@testing-library/react-native": "^12.4.0",
|
|
81
84
|
"@types/jest": "^29.5.14",
|
|
82
|
-
"@types/react": "^19.
|
|
85
|
+
"@types/react": "^19.3.0",
|
|
83
86
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
84
87
|
"@typescript-eslint/parser": "^8.0.0",
|
|
85
88
|
"del-cli": "^6.0.0",
|
|
86
89
|
"eslint": "^9.0.0",
|
|
87
90
|
"jest": "^29.7.0",
|
|
88
|
-
"react": "19.
|
|
89
|
-
"react-native": "0.
|
|
91
|
+
"react": "19.3.0",
|
|
92
|
+
"react-native": "0.88.0",
|
|
90
93
|
"react-native-builder-bob": "^0.40.18",
|
|
91
|
-
"react-test-renderer": "
|
|
94
|
+
"react-test-renderer": "19.3.0",
|
|
92
95
|
"ts-jest": "^29.1.0",
|
|
93
96
|
"typescript": "^5.9.2"
|
|
94
97
|
},
|
|
95
98
|
"peerDependencies": {
|
|
96
99
|
"react": ">=19.1.1 <20.0.0",
|
|
97
|
-
"react-native": ">=0.82.1 <0.
|
|
100
|
+
"react-native": ">=0.82.1 <0.89.0"
|
|
98
101
|
},
|
|
99
102
|
"workspaces": [
|
|
100
103
|
"example"
|
|
@@ -102,6 +105,7 @@
|
|
|
102
105
|
"resolutions": {
|
|
103
106
|
"@react-native-community/cli-config-android@npm:20.2.0": "patch:@react-native-community/cli-config-android@npm%3A20.2.0#./tooling-patches/cli-config-android-20.2.0.patch",
|
|
104
107
|
"@react-native-community/cli-clean@npm:20.2.0": "patch:@react-native-community/cli-clean@npm%3A20.2.0#./tooling-patches/cli-clean-20.2.0.patch",
|
|
108
|
+
"@react-native/gradle-plugin@npm:0.88.0": "patch:@react-native/gradle-plugin@npm%3A0.88.0#./tooling-patches/react-native-gradle-plugin-0.88.0-kotlin-2.4.21.patch",
|
|
105
109
|
"react-native-builder-bob@npm:^0.40.18": "patch:react-native-builder-bob@npm%3A0.40.18#./tooling-patches/react-native-builder-bob-0.40.18.patch",
|
|
106
110
|
"stream-json@npm:^1.7.4": "patch:stream-json@npm%3A1.9.1#./tooling-patches/stream-json-1.9.1.patch",
|
|
107
111
|
"stream-json@npm:^1.7.5": "patch:stream-json@npm%3A1.9.1#./tooling-patches/stream-json-1.9.1.patch"
|
|
@@ -139,7 +143,7 @@
|
|
|
139
143
|
}
|
|
140
144
|
},
|
|
141
145
|
"jest": {
|
|
142
|
-
"preset": "react-native",
|
|
146
|
+
"preset": "@react-native/jest-preset",
|
|
143
147
|
"transform": {
|
|
144
148
|
"^.+\\.tsx?$": [
|
|
145
149
|
"ts-jest",
|
package/src/NativeSynchro.ts
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import type { TurboModule } from 'react-native';
|
|
2
|
-
import type {
|
|
3
|
-
EventEmitter,
|
|
4
|
-
UnsafeObject,
|
|
5
|
-
} from 'react-native/Libraries/Types/CodegenTypes';
|
|
1
|
+
import type { CodegenTypes, TurboModule } from 'react-native';
|
|
6
2
|
import { TurboModuleRegistry } from 'react-native';
|
|
7
3
|
|
|
8
4
|
// Codegen does not support a discriminated union of object and primitive
|
|
9
5
|
// parameter types. UnsafeObject keeps the TurboModule boundary representable,
|
|
10
6
|
// while the public client validates the tagged values before crossing it.
|
|
11
|
-
type NativeSQLiteBindValue = string | number | boolean | null | UnsafeObject;
|
|
12
|
-
type NativeRow = UnsafeObject;
|
|
7
|
+
type NativeSQLiteBindValue = string | number | boolean | null | CodegenTypes.UnsafeObject;
|
|
8
|
+
type NativeRow = CodegenTypes.UnsafeObject;
|
|
13
9
|
type NativeSQLStatement = {
|
|
14
10
|
sql: string;
|
|
15
11
|
params: ReadonlyArray<NativeSQLiteBindValue>;
|
|
@@ -18,7 +14,7 @@ type StatusEvent = {
|
|
|
18
14
|
status: string;
|
|
19
15
|
retryAt: string | null;
|
|
20
16
|
operation: string | null;
|
|
21
|
-
failure: UnsafeObject | null;
|
|
17
|
+
failure: CodegenTypes.UnsafeObject | null;
|
|
22
18
|
};
|
|
23
19
|
type ConflictEvent = {
|
|
24
20
|
table: string;
|
|
@@ -33,8 +29,8 @@ type SyncEvent = {
|
|
|
33
29
|
operation: string | null;
|
|
34
30
|
attempt: number | null;
|
|
35
31
|
retryAt: string | null;
|
|
36
|
-
source: UnsafeObject | null;
|
|
37
|
-
target: UnsafeObject | null;
|
|
32
|
+
source: CodegenTypes.UnsafeObject | null;
|
|
33
|
+
target: CodegenTypes.UnsafeObject | null;
|
|
38
34
|
action: string | null;
|
|
39
35
|
mutationID: string | null;
|
|
40
36
|
tableID: string | null;
|
|
@@ -42,7 +38,7 @@ type SyncEvent = {
|
|
|
42
38
|
rejectionCode: string | null;
|
|
43
39
|
scopeID: string | null;
|
|
44
40
|
rebuildID: string | null;
|
|
45
|
-
failure: UnsafeObject | null;
|
|
41
|
+
failure: CodegenTypes.UnsafeObject | null;
|
|
46
42
|
};
|
|
47
43
|
type AuthRequestEvent = { requestID: string };
|
|
48
44
|
type ChangeEvent = { observerID: string };
|
|
@@ -171,12 +167,12 @@ export interface Spec extends TurboModule {
|
|
|
171
167
|
rejectAuthRequest(requestID: string, error: string): void;
|
|
172
168
|
|
|
173
169
|
// Typed events
|
|
174
|
-
readonly onStatusChange: EventEmitter<StatusEvent>;
|
|
175
|
-
readonly onSyncEvent: EventEmitter<SyncEvent>;
|
|
176
|
-
readonly onConflict: EventEmitter<ConflictEvent>;
|
|
177
|
-
readonly onAuthRequest: EventEmitter<AuthRequestEvent>;
|
|
178
|
-
readonly onChange: EventEmitter<ChangeEvent>;
|
|
179
|
-
readonly onQueryResult: EventEmitter<QueryResultEvent>;
|
|
170
|
+
readonly onStatusChange: CodegenTypes.EventEmitter<StatusEvent>;
|
|
171
|
+
readonly onSyncEvent: CodegenTypes.EventEmitter<SyncEvent>;
|
|
172
|
+
readonly onConflict: CodegenTypes.EventEmitter<ConflictEvent>;
|
|
173
|
+
readonly onAuthRequest: CodegenTypes.EventEmitter<AuthRequestEvent>;
|
|
174
|
+
readonly onChange: CodegenTypes.EventEmitter<ChangeEvent>;
|
|
175
|
+
readonly onQueryResult: CodegenTypes.EventEmitter<QueryResultEvent>;
|
|
180
176
|
|
|
181
177
|
// NativeEventEmitter compatibility
|
|
182
178
|
addListener(eventName: string): void;
|
|
@@ -58,6 +58,69 @@ const repairs = {
|
|
|
58
58
|
preimage: '451fe8050e20bc1c4724564b2c33fb819f815848f5ad2eb529be5915bf62f2bb',
|
|
59
59
|
postimage: 'd22c16e9d4ebe97b15a3b734b70e1060a5526b907cad2b1ec3bb1004d4ed0675'
|
|
60
60
|
}]
|
|
61
|
+
}],
|
|
62
|
+
rngp: [{
|
|
63
|
+
caller: 'react-native',
|
|
64
|
+
callerVersion: '0.88.0',
|
|
65
|
+
packageName: '@react-native/gradle-plugin',
|
|
66
|
+
version: '0.88.0',
|
|
67
|
+
patch: 'react-native-gradle-plugin-0.88.0-kotlin-2.4.21.patch',
|
|
68
|
+
sources: [{
|
|
69
|
+
path: 'gradle/libs.versions.toml',
|
|
70
|
+
preimage: 'c7a028cdee90f490de9493ca9de92b61b994844836161871091c340c568f109e',
|
|
71
|
+
postimage: '44a27d41062a7c01889fac1bc7666f8235ee14060de8588d66660830f8484c7d'
|
|
72
|
+
}, {
|
|
73
|
+
path: 'react-native-gradle-plugin/build.gradle.kts',
|
|
74
|
+
preimage: '44bcf53d885c52ef9988b7147e8e522563eaf519144109f40390fc7601a6469e',
|
|
75
|
+
postimage: 'cced8bd5897896d6f00149e4704b51130e8b9468f39ab4247f9aca0f2ddcc864'
|
|
76
|
+
}, {
|
|
77
|
+
path: 'settings-plugin/build.gradle.kts',
|
|
78
|
+
preimage: '326cc1d071e500711a12134d0577059929ae3e6960e2d1bfb10e0cffea8832f2',
|
|
79
|
+
postimage: '3af9b7ea340523e24e3492db32da30943dd840c3f2e656ffdc72b7a37129a3d5'
|
|
80
|
+
}, {
|
|
81
|
+
path: 'shared-testutil/build.gradle.kts',
|
|
82
|
+
preimage: '40950ae3b3bf68b35515f022f2819c98def11f0aee67ade7ed64f04c6f033cca',
|
|
83
|
+
postimage: '2db5af783296917c76c1f410ead33ed555310917a79b3b005ee996f1ac23a6d6'
|
|
84
|
+
}, {
|
|
85
|
+
path: 'shared/build.gradle.kts',
|
|
86
|
+
preimage: '7069a997b96e4c8a733a62e00d557730ab32bde6a5dc54dbd18d86d2bc302d09',
|
|
87
|
+
postimage: '5d8d113c7849a448d1abafb8fcdb545f389133fcd3fb6c68c12089de53e24c6c'
|
|
88
|
+
}]
|
|
89
|
+
}, {
|
|
90
|
+
caller: 'react-native',
|
|
91
|
+
callerVersion: '0.82.1',
|
|
92
|
+
packageName: '@react-native/gradle-plugin',
|
|
93
|
+
version: '0.82.1',
|
|
94
|
+
patch: 'react-native-gradle-plugin-0.82.1-kotlin-2.4.21.patch',
|
|
95
|
+
sources: [{
|
|
96
|
+
path: 'gradle/libs.versions.toml',
|
|
97
|
+
preimage: 'eea932505dd9efd2d660d8d10efddbe84b74ed47456d995099af7ab5d97d6802',
|
|
98
|
+
postimage: '8a30e112ad18be9bc95f509d1cc42affd09e23dd2cfe22677cd7c7703628247f'
|
|
99
|
+
}, {
|
|
100
|
+
path: 'react-native-gradle-plugin/build.gradle.kts',
|
|
101
|
+
preimage: 'b45b3f39996d9db2b54c68cca073063c605d313aae548f633b6a00fc6df556b0',
|
|
102
|
+
postimage: 'f0b609f0c29dbd6e90de935d3d6690b5cc6dd61f314345ccb662a0baf11a5fcc'
|
|
103
|
+
}, {
|
|
104
|
+
path: 'settings-plugin/build.gradle.kts',
|
|
105
|
+
preimage: '18d28065072ad8c93656deadfbcff095a05fd6a58e25d047eb69d839e347aa97',
|
|
106
|
+
postimage: '95b2086c29bd771fd9e52d23c931897852d6669138f0939a1b26a14f67c9a41e'
|
|
107
|
+
}, {
|
|
108
|
+
path: 'shared-testutil/build.gradle.kts',
|
|
109
|
+
preimage: '8cb397c7d640a836c2edce904cf2fbf90c069a2b228b539c0243e3d7997854bf',
|
|
110
|
+
postimage: '9af52f0cdf6f76a713598db2da6c7679390625028a23a0946c27d9df580d4bdc'
|
|
111
|
+
}, {
|
|
112
|
+
path: 'shared/build.gradle.kts',
|
|
113
|
+
preimage: 'fd66179022462615f054ccf03af25bc8b9399dc6b492d75b022bf2961f0f034e',
|
|
114
|
+
postimage: '00a4789ebba1fea4cfd6e0d3ef298fda7af7a462306ede91081d01c94cd74a92'
|
|
115
|
+
}, {
|
|
116
|
+
path: 'react-native-gradle-plugin/src/main/kotlin/com/facebook/react/ReactPlugin.kt',
|
|
117
|
+
preimage: '0d8511fc8c814b40a910b894986665784ef36a977c139923e92bfc62ef4cb845',
|
|
118
|
+
postimage: '8d47cc51b9759d19a400fc015a455cd137b867c8db69b06f19e7ed4e50d30151'
|
|
119
|
+
}, {
|
|
120
|
+
path: 'react-native-gradle-plugin/src/main/kotlin/com/facebook/react/utils/AgpConfiguratorUtils.kt',
|
|
121
|
+
preimage: 'd25dbfc8d9ee685269e22cddff9f4e86691fe922074dde32e1c5662d9a406309',
|
|
122
|
+
postimage: 'd1e7e31b236484cf06521e64eadff3c85502e822c08351de7caf7a78ed51bea0'
|
|
123
|
+
}]
|
|
61
124
|
}]
|
|
62
125
|
};
|
|
63
126
|
|
|
@@ -154,10 +217,28 @@ function applyRepair(repair) {
|
|
|
154
217
|
process.stdout.write(`applied verified ${repair.packageName} ${repair.version} patch\n`);
|
|
155
218
|
}
|
|
156
219
|
|
|
220
|
+
function hasCallerIdentity(repair) {
|
|
221
|
+
try {
|
|
222
|
+
const caller = callerRoot(repair);
|
|
223
|
+
const manifest = JSON.parse(fs.readFileSync(path.join(caller, 'package.json'), 'utf8'));
|
|
224
|
+
return manifest.name === repair.caller && manifest.version === repair.callerVersion;
|
|
225
|
+
} catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function selectedRepairs(name) {
|
|
231
|
+
const candidates = repairs[name];
|
|
232
|
+
if (name !== 'rngp') return candidates;
|
|
233
|
+
const selected = candidates.filter(hasCallerIdentity);
|
|
234
|
+
if (selected.length !== 1) fail('unsupported React Native Gradle Plugin version');
|
|
235
|
+
return selected;
|
|
236
|
+
}
|
|
237
|
+
|
|
157
238
|
const name = process.argv[2] || 'cli';
|
|
158
239
|
if (!Object.prototype.hasOwnProperty.call(repairs, name)) {
|
|
159
240
|
fail('unsupported repair');
|
|
160
241
|
}
|
|
161
|
-
for (const repair of
|
|
242
|
+
for (const repair of selectedRepairs(name)) {
|
|
162
243
|
applyRepair(repair);
|
|
163
244
|
}
|