@trainstar/synchro-react-native 0.3.2 → 0.4.0-rc.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/README.md +58 -4
- package/SynchroReactNative.podspec +6 -0
- package/android/build.gradle +5 -1
- package/android/src/androidTest/kotlin/com/trainstar/synchro/rn/SynchroModuleTransactionTest.kt +591 -0
- package/android/src/androidTest/kotlin/com/trainstar/synchro/rn/TransactionSessionTest.kt +314 -0
- package/android/src/main/kotlin/com/trainstar/synchro/rn/SynchroModule.kt +306 -110
- package/ios/SynchroModule.mm +27 -4
- package/ios/SynchroModule.swift +228 -84
- package/ios-tests/SynchroModuleTransactionTests.swift +707 -0
- package/ios-tests/TransactionSessionTests.swift +66 -0
- package/lib/module/NativeSynchro.js.map +1 -1
- package/lib/module/SynchroClient.js +115 -2
- package/lib/module/SynchroClient.js.map +1 -1
- package/lib/module/errors.js +15 -1
- package/lib/module/errors.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/inspection.js +31 -3
- package/lib/module/inspection.js.map +1 -1
- package/lib/module/types.js +18 -0
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/example/src/conformance/runner.d.ts +1 -0
- package/lib/typescript/example/src/conformance/runner.d.ts.map +1 -1
- package/lib/typescript/src/NativeSynchro.d.ts +7 -1
- package/lib/typescript/src/NativeSynchro.d.ts.map +1 -1
- package/lib/typescript/src/SynchroClient.d.ts +29 -1
- package/lib/typescript/src/SynchroClient.d.ts.map +1 -1
- package/lib/typescript/src/errors.d.ts +7 -1
- package/lib/typescript/src/errors.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/inspection.d.ts +13 -2
- package/lib/typescript/src/inspection.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +44 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/NativeSynchro.ts +6 -1
- package/src/SynchroClient.ts +128 -1
- package/src/errors.ts +30 -0
- package/src/index.ts +7 -0
- package/src/inspection.ts +44 -2
- package/src/types.ts +49 -1
package/src/SynchroClient.ts
CHANGED
|
@@ -28,6 +28,8 @@ import type {
|
|
|
28
28
|
MutationRejectionCode,
|
|
29
29
|
PendingMutationInspection,
|
|
30
30
|
RejectedMutationInspection,
|
|
31
|
+
RetainedMutationInspection,
|
|
32
|
+
RetainedRejectionInspection,
|
|
31
33
|
ClientStateInspection,
|
|
32
34
|
ScopeStateInspection,
|
|
33
35
|
ScopeRowInspection,
|
|
@@ -117,6 +119,7 @@ const MUTATION_REJECTION_CODES: readonly MutationRejectionCode[] = [
|
|
|
117
119
|
'policy_rejected',
|
|
118
120
|
'validation_failed',
|
|
119
121
|
'table_not_synced',
|
|
122
|
+
'atomic_batch_rejected',
|
|
120
123
|
];
|
|
121
124
|
|
|
122
125
|
const MUTATION_OPERATIONS = ['insert', 'upsert', 'update', 'delete'] as const;
|
|
@@ -438,6 +441,40 @@ function parsePendingMutationInspection(
|
|
|
438
441
|
};
|
|
439
442
|
}
|
|
440
443
|
|
|
444
|
+
export function parseRetainedMutationInspection(
|
|
445
|
+
value: unknown,
|
|
446
|
+
index: number
|
|
447
|
+
): RetainedMutationInspection {
|
|
448
|
+
const name = `pending mutation at index ${index}`;
|
|
449
|
+
if (!isRecord(value)) {
|
|
450
|
+
throw new InvalidResponseError(`Native bridge returned an invalid ${name}`);
|
|
451
|
+
}
|
|
452
|
+
if (value.representation === 'current') {
|
|
453
|
+
return { representation: 'current', ...parsePendingMutationInspection(value, index) };
|
|
454
|
+
}
|
|
455
|
+
if (value.representation !== 'legacy') {
|
|
456
|
+
throw new InvalidResponseError(`Native bridge returned an invalid ${name} representation`);
|
|
457
|
+
}
|
|
458
|
+
if (!MUTATION_OPERATIONS.includes(value.operation as never)) {
|
|
459
|
+
throw new InvalidResponseError(`Native bridge returned an invalid ${name} operation`);
|
|
460
|
+
}
|
|
461
|
+
if (!LOCAL_MUTATION_STATUSES.includes(value.status as never)) {
|
|
462
|
+
throw new InvalidResponseError(`Native bridge returned an invalid ${name} status`);
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
representation: 'legacy',
|
|
466
|
+
mutationID: requiredString(value.mutationID, `${name} ID`),
|
|
467
|
+
localOrder: requiredSafeInteger(value.localOrder, `${name} local order`),
|
|
468
|
+
tableName: requiredString(value.tableName, `${name} table name`),
|
|
469
|
+
recordID: requiredString(value.recordID, `${name} record ID`),
|
|
470
|
+
operation: value.operation as PendingMutationInspection['operation'],
|
|
471
|
+
baseVersion: nullableString(value.baseVersion, `${name} base version`),
|
|
472
|
+
clientVersion: requiredString(value.clientVersion, `${name} client version`),
|
|
473
|
+
status: value.status as PendingMutationInspection['status'],
|
|
474
|
+
sourceKind: requiredString(value.sourceKind, `${name} source kind`),
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
441
478
|
function parseRejectedMutationInspection(
|
|
442
479
|
value: unknown,
|
|
443
480
|
index: number
|
|
@@ -466,6 +503,39 @@ function parseRejectedMutationInspection(
|
|
|
466
503
|
};
|
|
467
504
|
}
|
|
468
505
|
|
|
506
|
+
export function parseRetainedRejectionInspection(
|
|
507
|
+
value: unknown,
|
|
508
|
+
index: number
|
|
509
|
+
): RetainedRejectionInspection {
|
|
510
|
+
const name = `rejected mutation at index ${index}`;
|
|
511
|
+
if (!isRecord(value)) {
|
|
512
|
+
throw new InvalidResponseError(`Native bridge returned an invalid ${name}`);
|
|
513
|
+
}
|
|
514
|
+
if (value.representation === 'current') {
|
|
515
|
+
return { representation: 'current', ...parseRejectedMutationInspection(value, index) };
|
|
516
|
+
}
|
|
517
|
+
if (value.representation !== 'legacy') {
|
|
518
|
+
throw new InvalidResponseError(`Native bridge returned an invalid ${name} representation`);
|
|
519
|
+
}
|
|
520
|
+
const code = parseRejectionCode(value.code);
|
|
521
|
+
if (code === null) {
|
|
522
|
+
throw new InvalidResponseError(`Native bridge returned a missing ${name} code`);
|
|
523
|
+
}
|
|
524
|
+
return {
|
|
525
|
+
representation: 'legacy',
|
|
526
|
+
mutationID: requiredString(value.mutationID, `${name} ID`),
|
|
527
|
+
tableName: requiredString(value.tableName, `${name} table name`),
|
|
528
|
+
recordID: requiredString(value.recordID, `${name} record ID`),
|
|
529
|
+
status: parseMutationStatus(value.status),
|
|
530
|
+
code,
|
|
531
|
+
message: nullableString(value.message, `${name} message`),
|
|
532
|
+
serverRowJSON: nullableString(value.serverRowJSON, `${name} server row JSON`),
|
|
533
|
+
serverVersion: nullableString(value.serverVersion, `${name} server version`),
|
|
534
|
+
createdAt: requiredString(value.createdAt, `${name} creation time`),
|
|
535
|
+
updatedAt: requiredString(value.updatedAt, `${name} update time`),
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
|
|
469
539
|
function parseScopeStateInspection(value: unknown, index: number): ScopeStateInspection {
|
|
470
540
|
const name = `scope state at index ${index}`;
|
|
471
541
|
if (!isRecord(value)) {
|
|
@@ -802,10 +872,28 @@ export class SynchroClient {
|
|
|
802
872
|
|
|
803
873
|
async writeTransaction<T>(
|
|
804
874
|
callback: (tx: Transaction) => Promise<T>
|
|
875
|
+
): Promise<T> {
|
|
876
|
+
return this.runWriteTransaction(() => this.native.beginWriteTransaction(), callback);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Runs a write transaction whose synced mutations the server applies all
|
|
881
|
+
* together or not at all. The native SDK owns the group. An invalid group
|
|
882
|
+
* rolls back and rejects with `AtomicGroupInvalidError`.
|
|
883
|
+
*/
|
|
884
|
+
async atomicWriteTransaction<T>(
|
|
885
|
+
callback: (tx: Transaction) => Promise<T>
|
|
886
|
+
): Promise<T> {
|
|
887
|
+
return this.runWriteTransaction(() => this.native.beginAtomicWriteTransaction(), callback);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
private async runWriteTransaction<T>(
|
|
891
|
+
begin: () => Promise<string>,
|
|
892
|
+
callback: (tx: Transaction) => Promise<T>
|
|
805
893
|
): Promise<T> {
|
|
806
894
|
let txID: string;
|
|
807
895
|
try {
|
|
808
|
-
txID = await
|
|
896
|
+
txID = await begin();
|
|
809
897
|
} catch (error) {
|
|
810
898
|
throw mapNativeError(error);
|
|
811
899
|
}
|
|
@@ -1025,6 +1113,11 @@ export class SynchroClient {
|
|
|
1025
1113
|
}
|
|
1026
1114
|
}
|
|
1027
1115
|
|
|
1116
|
+
/**
|
|
1117
|
+
* Returns the unresolved queue records.
|
|
1118
|
+
* @deprecated Use {@link SynchroClient.inspectRetainedMutationRecords}. This method keeps its
|
|
1119
|
+
* published behavior. It rejects when the native queue holds a legacy import.
|
|
1120
|
+
*/
|
|
1028
1121
|
async inspectPendingMutations(): Promise<PendingMutationInspection[]> {
|
|
1029
1122
|
try {
|
|
1030
1123
|
return parseNativeArray(
|
|
@@ -1036,6 +1129,11 @@ export class SynchroClient {
|
|
|
1036
1129
|
}
|
|
1037
1130
|
}
|
|
1038
1131
|
|
|
1132
|
+
/**
|
|
1133
|
+
* Returns every retained queue record, including local terminal states.
|
|
1134
|
+
* @deprecated Use {@link SynchroClient.inspectRetainedMutationRecords}. This method keeps its
|
|
1135
|
+
* published behavior. It rejects when the native queue holds a legacy import.
|
|
1136
|
+
*/
|
|
1039
1137
|
async inspectRetainedMutations(): Promise<PendingMutationInspection[]> {
|
|
1040
1138
|
try {
|
|
1041
1139
|
return parseNativeArray(
|
|
@@ -1047,6 +1145,23 @@ export class SynchroClient {
|
|
|
1047
1145
|
}
|
|
1048
1146
|
}
|
|
1049
1147
|
|
|
1148
|
+
/** Returns every retained queue record in its stored representation. */
|
|
1149
|
+
async inspectRetainedMutationRecords(): Promise<RetainedMutationInspection[]> {
|
|
1150
|
+
try {
|
|
1151
|
+
return parseNativeArray(
|
|
1152
|
+
await this.native.inspectRetainedMutationRecords(),
|
|
1153
|
+
'retained mutation inspection'
|
|
1154
|
+
).map(parseRetainedMutationInspection);
|
|
1155
|
+
} catch (error) {
|
|
1156
|
+
throw mapNativeError(error);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* Returns the retained terminal outcomes.
|
|
1162
|
+
* @deprecated Use {@link SynchroClient.inspectRejectedMutationRecords}. This method keeps its
|
|
1163
|
+
* published behavior. It rejects when a legacy rejection is present.
|
|
1164
|
+
*/
|
|
1050
1165
|
async inspectRejectedMutations(): Promise<RejectedMutationInspection[]> {
|
|
1051
1166
|
try {
|
|
1052
1167
|
return parseNativeArray(
|
|
@@ -1058,6 +1173,18 @@ export class SynchroClient {
|
|
|
1058
1173
|
}
|
|
1059
1174
|
}
|
|
1060
1175
|
|
|
1176
|
+
/** Returns the retained terminal outcomes in their stored representation. */
|
|
1177
|
+
async inspectRejectedMutationRecords(): Promise<RetainedRejectionInspection[]> {
|
|
1178
|
+
try {
|
|
1179
|
+
return parseNativeArray(
|
|
1180
|
+
await this.native.inspectRejectedMutationRecords(),
|
|
1181
|
+
'rejected mutation inspection'
|
|
1182
|
+
).map(parseRetainedRejectionInspection);
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
throw mapNativeError(error);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1061
1188
|
async clearRejectedMutations(): Promise<void> {
|
|
1062
1189
|
try {
|
|
1063
1190
|
await this.native.clearRejectedMutations();
|
package/src/errors.ts
CHANGED
|
@@ -33,6 +33,7 @@ export const NATIVE_ERROR_CODES = [
|
|
|
33
33
|
'TRANSACTION_TIMEOUT',
|
|
34
34
|
'INVALID_CONFIG',
|
|
35
35
|
'CLIENT_ALREADY_ACTIVE',
|
|
36
|
+
'atomic_group_invalid',
|
|
36
37
|
'UNKNOWN',
|
|
37
38
|
] as const;
|
|
38
39
|
|
|
@@ -233,6 +234,25 @@ export class TransactionTimeoutError extends SynchroError {
|
|
|
233
234
|
}
|
|
234
235
|
}
|
|
235
236
|
|
|
237
|
+
export const ATOMIC_GROUP_INVALID_REASONS = [
|
|
238
|
+
'deleteFollowedByWrite',
|
|
239
|
+
'tooManyMutations',
|
|
240
|
+
'mutationTooLarge',
|
|
241
|
+
'requestTooLarge',
|
|
242
|
+
] as const;
|
|
243
|
+
|
|
244
|
+
export type AtomicGroupInvalidReason = (typeof ATOMIC_GROUP_INVALID_REASONS)[number];
|
|
245
|
+
|
|
246
|
+
export class AtomicGroupInvalidError extends SynchroError {
|
|
247
|
+
readonly reason: AtomicGroupInvalidReason;
|
|
248
|
+
|
|
249
|
+
constructor(reason: AtomicGroupInvalidReason) {
|
|
250
|
+
super('atomic_group_invalid', `Atomic write group is invalid: ${reason}`);
|
|
251
|
+
this.name = 'AtomicGroupInvalidError';
|
|
252
|
+
this.reason = reason;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
236
256
|
interface NativeErrorLike {
|
|
237
257
|
code?: string;
|
|
238
258
|
message?: string;
|
|
@@ -439,6 +459,16 @@ export function mapNativeError(error: unknown): SynchroError {
|
|
|
439
459
|
return new TransactionTimeoutError();
|
|
440
460
|
case 'INVALID_CONFIG':
|
|
441
461
|
return new SynchroError('INVALID_CONFIG', message);
|
|
462
|
+
case 'atomic_group_invalid':
|
|
463
|
+
try {
|
|
464
|
+
return new AtomicGroupInvalidError(
|
|
465
|
+
requiredEnum(userInfo.reason, ATOMIC_GROUP_INVALID_REASONS, 'atomic group invalid reason')
|
|
466
|
+
);
|
|
467
|
+
} catch (parseError) {
|
|
468
|
+
return parseError instanceof SynchroError
|
|
469
|
+
? parseError
|
|
470
|
+
: new InvalidResponseError('Native bridge returned invalid atomic group details');
|
|
471
|
+
}
|
|
442
472
|
default:
|
|
443
473
|
return new SynchroError('UNKNOWN', message);
|
|
444
474
|
}
|
package/src/index.ts
CHANGED
|
@@ -30,7 +30,11 @@ export type {
|
|
|
30
30
|
SchemaRef,
|
|
31
31
|
AuthoredMutationField,
|
|
32
32
|
PendingMutationInspection,
|
|
33
|
+
LegacyMutationInspection,
|
|
34
|
+
RetainedMutationInspection,
|
|
33
35
|
RejectedMutationInspection,
|
|
36
|
+
LegacyRejectionInspection,
|
|
37
|
+
RetainedRejectionInspection,
|
|
34
38
|
SchemaAction,
|
|
35
39
|
SyncSchemaEvent,
|
|
36
40
|
SyncMutationEvent,
|
|
@@ -71,6 +75,8 @@ export {
|
|
|
71
75
|
AlreadyStartedError,
|
|
72
76
|
NotStartedError,
|
|
73
77
|
TransactionTimeoutError,
|
|
78
|
+
AtomicGroupInvalidError,
|
|
79
|
+
ATOMIC_GROUP_INVALID_REASONS,
|
|
74
80
|
NATIVE_ERROR_CODES,
|
|
75
81
|
mapNativeError,
|
|
76
82
|
} from './errors';
|
|
@@ -78,5 +84,6 @@ export {
|
|
|
78
84
|
export type {
|
|
79
85
|
NativeErrorCode,
|
|
80
86
|
SchemaUnsupportedReason,
|
|
87
|
+
AtomicGroupInvalidReason,
|
|
81
88
|
PushRejectedMutation,
|
|
82
89
|
} from './errors';
|
package/src/inspection.ts
CHANGED
|
@@ -2,12 +2,19 @@ import {
|
|
|
2
2
|
configureInspection,
|
|
3
3
|
nativeForInspection,
|
|
4
4
|
parseClientStateInspection,
|
|
5
|
+
parseRetainedMutationInspection,
|
|
6
|
+
parseRetainedRejectionInspection,
|
|
5
7
|
parseTransportObservationSnapshot,
|
|
6
8
|
SynchroClient,
|
|
7
9
|
} from './SynchroClient';
|
|
8
10
|
import { InvalidResponseError, mapNativeError } from './errors';
|
|
11
|
+
import { assertValidSQLiteBindParams } from './sqliteValues';
|
|
9
12
|
import type {
|
|
10
13
|
ClientStateInspection,
|
|
14
|
+
RetainedMutationInspection,
|
|
15
|
+
RetainedRejectionInspection,
|
|
16
|
+
Row,
|
|
17
|
+
SQLStatement,
|
|
11
18
|
TransportObservationSnapshot,
|
|
12
19
|
TransportOperationClass,
|
|
13
20
|
} from './types';
|
|
@@ -45,6 +52,18 @@ export interface DurableStateInspection {
|
|
|
45
52
|
}>;
|
|
46
53
|
}
|
|
47
54
|
|
|
55
|
+
/**
|
|
56
|
+
* One read-only snapshot of client state and retained details. A detail list is
|
|
57
|
+
* null when its record count exceeds the native capture bound. `applicationRows`
|
|
58
|
+
* holds the rows that the requested read statements returned inside the snapshot.
|
|
59
|
+
*/
|
|
60
|
+
export interface ClientStateSnapshotInspection {
|
|
61
|
+
clientState: ClientStateInspection;
|
|
62
|
+
retainedMutations: RetainedMutationInspection[] | null;
|
|
63
|
+
rejectedMutations: RetainedRejectionInspection[] | null;
|
|
64
|
+
applicationRows: Row[];
|
|
65
|
+
}
|
|
66
|
+
|
|
48
67
|
export interface SynchroInspectionOptions {
|
|
49
68
|
transportObservationCapacity?: number;
|
|
50
69
|
requireNewDatabase?: boolean;
|
|
@@ -62,9 +81,22 @@ export class SynchroInspection {
|
|
|
62
81
|
);
|
|
63
82
|
}
|
|
64
83
|
|
|
65
|
-
async
|
|
84
|
+
async captureSnapshot(rowStatements: SQLStatement[] = []): Promise<ClientStateSnapshotInspection> {
|
|
66
85
|
try {
|
|
67
|
-
|
|
86
|
+
const statements = rowStatements.map((statement) => ({
|
|
87
|
+
sql: statement.sql,
|
|
88
|
+
params: assertValidSQLiteBindParams(statement.params ?? []),
|
|
89
|
+
}));
|
|
90
|
+
const result = await nativeForInspection(this.client).inspectClientStateSnapshot(statements);
|
|
91
|
+
const snapshot = requireRecord(parseJSON(result.inspection), 'client state snapshot');
|
|
92
|
+
return {
|
|
93
|
+
clientState: parseClientStateInspection(snapshot.client_state),
|
|
94
|
+
retainedMutations:
|
|
95
|
+
nullableArray(snapshot.retained_mutations, 'retained mutations')?.map(parseRetainedMutationInspection) ?? null,
|
|
96
|
+
rejectedMutations:
|
|
97
|
+
nullableArray(snapshot.rejected_mutations, 'rejected mutations')?.map(parseRetainedRejectionInspection) ?? null,
|
|
98
|
+
applicationRows: [...result.applicationRows] as Row[],
|
|
99
|
+
};
|
|
68
100
|
} catch (error) {
|
|
69
101
|
throw mapNativeError(error);
|
|
70
102
|
}
|
|
@@ -187,6 +219,16 @@ function parseDurableState(value: unknown): DurableStateInspection {
|
|
|
187
219
|
return proof as unknown as DurableStateInspection;
|
|
188
220
|
}
|
|
189
221
|
|
|
222
|
+
function nullableArray(value: unknown, name: string): unknown[] | null {
|
|
223
|
+
if (value === null) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
if (!Array.isArray(value)) {
|
|
227
|
+
throw new InvalidResponseError(`Native bridge returned invalid ${name}`);
|
|
228
|
+
}
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
231
|
+
|
|
190
232
|
function requireRecord(value: unknown, name: string): Record<string, unknown> {
|
|
191
233
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
192
234
|
throw new InvalidResponseError(`Native bridge returned invalid ${name}`);
|
package/src/types.ts
CHANGED
|
@@ -186,7 +186,8 @@ export type MutationRejectionCode =
|
|
|
186
186
|
| 'schema_incompatible'
|
|
187
187
|
| 'policy_rejected'
|
|
188
188
|
| 'validation_failed'
|
|
189
|
-
| 'table_not_synced'
|
|
189
|
+
| 'table_not_synced'
|
|
190
|
+
| 'atomic_batch_rejected';
|
|
190
191
|
|
|
191
192
|
export interface SchemaRef {
|
|
192
193
|
version: number;
|
|
@@ -199,6 +200,7 @@ export interface AuthoredMutationField {
|
|
|
199
200
|
value: JSONValue;
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
/** A retained mutation with its complete ledger binding and authored values. */
|
|
202
204
|
export interface PendingMutationInspection {
|
|
203
205
|
mutationID: string;
|
|
204
206
|
localOrder: number;
|
|
@@ -220,6 +222,29 @@ export interface PendingMutationInspection {
|
|
|
220
222
|
authoredFields: AuthoredMutationField[];
|
|
221
223
|
}
|
|
222
224
|
|
|
225
|
+
/**
|
|
226
|
+
* A retained mutation that a queue from before the mutation ledger imported.
|
|
227
|
+
* It has only the fields that the old queue stored.
|
|
228
|
+
*/
|
|
229
|
+
export interface LegacyMutationInspection {
|
|
230
|
+
representation: 'legacy';
|
|
231
|
+
mutationID: string;
|
|
232
|
+
localOrder: number;
|
|
233
|
+
tableName: string;
|
|
234
|
+
recordID: string;
|
|
235
|
+
operation: MutationOperation;
|
|
236
|
+
baseVersion: string | null;
|
|
237
|
+
clientVersion: string;
|
|
238
|
+
status: LocalMutationStatus;
|
|
239
|
+
sourceKind: string;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** One retained mutation in its stored representation. */
|
|
243
|
+
export type RetainedMutationInspection =
|
|
244
|
+
| (PendingMutationInspection & { representation: 'current' })
|
|
245
|
+
| LegacyMutationInspection;
|
|
246
|
+
|
|
247
|
+
/** A retained rejection with its exact mutation and rejection JSON. */
|
|
223
248
|
export interface RejectedMutationInspection {
|
|
224
249
|
mutationID: string;
|
|
225
250
|
tableName: string;
|
|
@@ -235,6 +260,29 @@ export interface RejectedMutationInspection {
|
|
|
235
260
|
updatedAt: string;
|
|
236
261
|
}
|
|
237
262
|
|
|
263
|
+
/**
|
|
264
|
+
* A retained rejection that a database from before the mutation ledger stored.
|
|
265
|
+
* It has only the fields that the old rejection table stored.
|
|
266
|
+
*/
|
|
267
|
+
export interface LegacyRejectionInspection {
|
|
268
|
+
representation: 'legacy';
|
|
269
|
+
mutationID: string;
|
|
270
|
+
tableName: string;
|
|
271
|
+
recordID: string;
|
|
272
|
+
status: MutationStatus;
|
|
273
|
+
code: MutationRejectionCode;
|
|
274
|
+
message: string | null;
|
|
275
|
+
serverRowJSON: string | null;
|
|
276
|
+
serverVersion: string | null;
|
|
277
|
+
createdAt: string;
|
|
278
|
+
updatedAt: string;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/** One retained rejection in its stored representation. */
|
|
282
|
+
export type RetainedRejectionInspection =
|
|
283
|
+
| (RejectedMutationInspection & { representation: 'current' })
|
|
284
|
+
| LegacyRejectionInspection;
|
|
285
|
+
|
|
238
286
|
export interface ScopeStateInspection {
|
|
239
287
|
scopeID: string;
|
|
240
288
|
cursor: string | null;
|