@trainstar/synchro-react-native 0.3.1 → 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 +307 -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 +116 -3
- 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/e2e/corpus-harness.d.ts.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/example/src/timeouts.d.ts +2 -0
- package/lib/typescript/example/src/timeouts.d.ts.map +1 -0
- 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 +45 -2
- 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 +129 -1
- package/src/errors.ts +30 -0
- package/src/index.ts +7 -0
- package/src/inspection.ts +44 -2
- package/src/types.ts +51 -2
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;
|
|
@@ -127,6 +130,7 @@ const LOCAL_MUTATION_STATUSES = [
|
|
|
127
130
|
'cancelled_before_send',
|
|
128
131
|
'blocked_by_predecessor',
|
|
129
132
|
'server_rejected',
|
|
133
|
+
'exceeds_push_limit',
|
|
130
134
|
] as const;
|
|
131
135
|
|
|
132
136
|
const TRANSPORT_OPERATION_CLASSES: readonly TransportOperationClass[] = [
|
|
@@ -437,6 +441,40 @@ function parsePendingMutationInspection(
|
|
|
437
441
|
};
|
|
438
442
|
}
|
|
439
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
|
+
|
|
440
478
|
function parseRejectedMutationInspection(
|
|
441
479
|
value: unknown,
|
|
442
480
|
index: number
|
|
@@ -465,6 +503,39 @@ function parseRejectedMutationInspection(
|
|
|
465
503
|
};
|
|
466
504
|
}
|
|
467
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
|
+
|
|
468
539
|
function parseScopeStateInspection(value: unknown, index: number): ScopeStateInspection {
|
|
469
540
|
const name = `scope state at index ${index}`;
|
|
470
541
|
if (!isRecord(value)) {
|
|
@@ -801,10 +872,28 @@ export class SynchroClient {
|
|
|
801
872
|
|
|
802
873
|
async writeTransaction<T>(
|
|
803
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>
|
|
804
893
|
): Promise<T> {
|
|
805
894
|
let txID: string;
|
|
806
895
|
try {
|
|
807
|
-
txID = await
|
|
896
|
+
txID = await begin();
|
|
808
897
|
} catch (error) {
|
|
809
898
|
throw mapNativeError(error);
|
|
810
899
|
}
|
|
@@ -1024,6 +1113,11 @@ export class SynchroClient {
|
|
|
1024
1113
|
}
|
|
1025
1114
|
}
|
|
1026
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
|
+
*/
|
|
1027
1121
|
async inspectPendingMutations(): Promise<PendingMutationInspection[]> {
|
|
1028
1122
|
try {
|
|
1029
1123
|
return parseNativeArray(
|
|
@@ -1035,6 +1129,11 @@ export class SynchroClient {
|
|
|
1035
1129
|
}
|
|
1036
1130
|
}
|
|
1037
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
|
+
*/
|
|
1038
1137
|
async inspectRetainedMutations(): Promise<PendingMutationInspection[]> {
|
|
1039
1138
|
try {
|
|
1040
1139
|
return parseNativeArray(
|
|
@@ -1046,6 +1145,23 @@ export class SynchroClient {
|
|
|
1046
1145
|
}
|
|
1047
1146
|
}
|
|
1048
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
|
+
*/
|
|
1049
1165
|
async inspectRejectedMutations(): Promise<RejectedMutationInspection[]> {
|
|
1050
1166
|
try {
|
|
1051
1167
|
return parseNativeArray(
|
|
@@ -1057,6 +1173,18 @@ export class SynchroClient {
|
|
|
1057
1173
|
}
|
|
1058
1174
|
}
|
|
1059
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
|
+
|
|
1060
1188
|
async clearRejectedMutations(): Promise<void> {
|
|
1061
1189
|
try {
|
|
1062
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
|
@@ -173,7 +173,8 @@ export type LocalMutationStatus =
|
|
|
173
173
|
| 'superseded_before_send'
|
|
174
174
|
| 'cancelled_before_send'
|
|
175
175
|
| 'blocked_by_predecessor'
|
|
176
|
-
| 'server_rejected'
|
|
176
|
+
| 'server_rejected'
|
|
177
|
+
| 'exceeds_push_limit';
|
|
177
178
|
|
|
178
179
|
export type MutationStatus = 'applied' | 'conflict' | 'rejected_terminal';
|
|
179
180
|
|
|
@@ -185,7 +186,8 @@ export type MutationRejectionCode =
|
|
|
185
186
|
| 'schema_incompatible'
|
|
186
187
|
| 'policy_rejected'
|
|
187
188
|
| 'validation_failed'
|
|
188
|
-
| 'table_not_synced'
|
|
189
|
+
| 'table_not_synced'
|
|
190
|
+
| 'atomic_batch_rejected';
|
|
189
191
|
|
|
190
192
|
export interface SchemaRef {
|
|
191
193
|
version: number;
|
|
@@ -198,6 +200,7 @@ export interface AuthoredMutationField {
|
|
|
198
200
|
value: JSONValue;
|
|
199
201
|
}
|
|
200
202
|
|
|
203
|
+
/** A retained mutation with its complete ledger binding and authored values. */
|
|
201
204
|
export interface PendingMutationInspection {
|
|
202
205
|
mutationID: string;
|
|
203
206
|
localOrder: number;
|
|
@@ -219,6 +222,29 @@ export interface PendingMutationInspection {
|
|
|
219
222
|
authoredFields: AuthoredMutationField[];
|
|
220
223
|
}
|
|
221
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. */
|
|
222
248
|
export interface RejectedMutationInspection {
|
|
223
249
|
mutationID: string;
|
|
224
250
|
tableName: string;
|
|
@@ -234,6 +260,29 @@ export interface RejectedMutationInspection {
|
|
|
234
260
|
updatedAt: string;
|
|
235
261
|
}
|
|
236
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
|
+
|
|
237
286
|
export interface ScopeStateInspection {
|
|
238
287
|
scopeID: string;
|
|
239
288
|
cursor: string | null;
|