@syncular/server 0.9.0 → 0.11.0
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 +67 -3
- package/dist/context.d.ts +8 -1
- package/dist/d1-storage.d.ts +10 -1
- package/dist/d1-storage.js +0 -0
- package/dist/postgres-storage.js +60 -0
- package/dist/push.js +181 -25
- package/dist/realtime.d.ts +3 -1
- package/dist/realtime.js +3 -0
- package/dist/sqlite-storage.js +22 -0
- package/dist/storage.d.ts +18 -0
- package/dist/validate.d.ts +56 -1
- package/dist/validate.js +15 -0
- package/package.json +2 -2
- package/src/context.ts +8 -1
- package/src/d1-storage.ts +0 -0
- package/src/postgres-storage.ts +76 -0
- package/src/push.ts +273 -27
- package/src/realtime.ts +6 -1
- package/src/sqlite-storage.ts +35 -0
- package/src/storage.ts +22 -0
- package/src/validate.ts +79 -0
package/src/validate.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
type RejectionDetails,
|
|
19
19
|
type RowColumn,
|
|
20
20
|
type RowValue,
|
|
21
|
+
type ScopeMap,
|
|
21
22
|
} from '@syncular/core';
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -64,6 +65,63 @@ export interface ValidateOperation {
|
|
|
64
65
|
readonly stored: ValidateRow | undefined;
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
/**
|
|
69
|
+
* One authorized, decoded operation presented to the whole-commit validator.
|
|
70
|
+
* `row` is the final candidate row after scope stripping and CRDT merge;
|
|
71
|
+
* `stored` is the state observed immediately before this operation. Multiple
|
|
72
|
+
* operations targeting one row therefore retain their sequential evidence.
|
|
73
|
+
*/
|
|
74
|
+
export interface ValidateCommitOperation extends ValidateOperation {
|
|
75
|
+
readonly opIndex: number;
|
|
76
|
+
readonly storedServerVersion?: number;
|
|
77
|
+
readonly nextServerVersion?: number;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** One candidate-state row read from inside the still-open commit transaction. */
|
|
81
|
+
export interface CommitValidationRow {
|
|
82
|
+
readonly row: ValidateRow;
|
|
83
|
+
readonly serverVersion: number;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface CommitValidationScanInput {
|
|
87
|
+
readonly table: string;
|
|
88
|
+
/** Exact scope filter, using the same AND-across-keys semantics as sync. */
|
|
89
|
+
readonly scopeFilter: ScopeMap;
|
|
90
|
+
readonly afterRowId?: string | null;
|
|
91
|
+
/** Bounded per call by the server to 1..1,000; defaults to 100. */
|
|
92
|
+
readonly limit?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Candidate-state reads bound to the same storage transaction as the commit.
|
|
97
|
+
* Reads observe every staged sibling operation and no uncommitted competing
|
|
98
|
+
* transaction when the storage's commit-validation lock contract is honored.
|
|
99
|
+
*/
|
|
100
|
+
export interface CommitValidationReader {
|
|
101
|
+
getRow(
|
|
102
|
+
table: string,
|
|
103
|
+
rowId: string,
|
|
104
|
+
): Promise<CommitValidationRow | undefined>;
|
|
105
|
+
scanRows(input: CommitValidationScanInput): Promise<CommitValidationRow[]>;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface ValidateCommitInput {
|
|
109
|
+
readonly clientId: string;
|
|
110
|
+
readonly clientCommitId: string;
|
|
111
|
+
readonly actorId: string;
|
|
112
|
+
readonly partition: string;
|
|
113
|
+
readonly operations: readonly ValidateCommitOperation[];
|
|
114
|
+
readonly read: CommitValidationReader;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Runs once after every operation passed protocol/scope/row validation and was
|
|
119
|
+
* staged, but before commit-log/idempotency append and transaction commit.
|
|
120
|
+
*/
|
|
121
|
+
export type CommitValidator = (
|
|
122
|
+
input: ValidateCommitInput,
|
|
123
|
+
) => void | Promise<void>;
|
|
124
|
+
|
|
67
125
|
/** Ambient context a validator may consult (§6.7). */
|
|
68
126
|
export interface ValidateContext {
|
|
69
127
|
/** Host-authenticated actor (§1.1) performing the write. */
|
|
@@ -122,6 +180,27 @@ export class ValidationRejection extends Error {
|
|
|
122
180
|
}
|
|
123
181
|
}
|
|
124
182
|
|
|
183
|
+
/**
|
|
184
|
+
* A whole-commit rejection attributed to one operation for the existing
|
|
185
|
+
* per-operation PUSH_RESULT envelope. The validator may still describe
|
|
186
|
+
* multiple affected fields in `details.fieldPaths`.
|
|
187
|
+
*/
|
|
188
|
+
export class CommitValidationRejection extends ValidationRejection {
|
|
189
|
+
constructor(
|
|
190
|
+
readonly opIndex: number,
|
|
191
|
+
code: string,
|
|
192
|
+
message?: string,
|
|
193
|
+
details?: RejectionDetails,
|
|
194
|
+
) {
|
|
195
|
+
super(code, message, details);
|
|
196
|
+
if (!Number.isSafeInteger(opIndex) || opIndex < 0) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
'CommitValidationRejection opIndex must be a non-negative safe integer',
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
125
204
|
/** Build the column-keyed row object a validator inspects (§6.7). */
|
|
126
205
|
export function toValidateRow(
|
|
127
206
|
columns: readonly RowColumn[],
|