@topgunbuild/core 0.2.1 → 0.4.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/dist/index.d.mts +1597 -52
- package/dist/index.d.ts +1597 -52
- package/dist/index.js +1471 -191
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1418 -190
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
- package/LICENSE +0 -97
package/dist/index.mjs
CHANGED
|
@@ -970,6 +970,935 @@ function deserialize(data) {
|
|
|
970
970
|
return unpack(buffer);
|
|
971
971
|
}
|
|
972
972
|
|
|
973
|
+
// src/PNCounter.ts
|
|
974
|
+
var PNCounterImpl = class {
|
|
975
|
+
constructor(config) {
|
|
976
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
977
|
+
this.nodeId = config.nodeId;
|
|
978
|
+
this.state = config.initialState ?? {
|
|
979
|
+
positive: /* @__PURE__ */ new Map(),
|
|
980
|
+
negative: /* @__PURE__ */ new Map()
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Get the current counter value.
|
|
985
|
+
* Value = sum(positive) - sum(negative)
|
|
986
|
+
*/
|
|
987
|
+
get() {
|
|
988
|
+
let sum = 0;
|
|
989
|
+
for (const v of this.state.positive.values()) sum += v;
|
|
990
|
+
for (const v of this.state.negative.values()) sum -= v;
|
|
991
|
+
return sum;
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* Increment by 1 and return the new value.
|
|
995
|
+
*/
|
|
996
|
+
increment() {
|
|
997
|
+
return this.addAndGet(1);
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Decrement by 1 and return the new value.
|
|
1001
|
+
*/
|
|
1002
|
+
decrement() {
|
|
1003
|
+
return this.addAndGet(-1);
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Add a delta (positive or negative) and return the new value.
|
|
1007
|
+
* @param delta The amount to add (can be negative)
|
|
1008
|
+
*/
|
|
1009
|
+
addAndGet(delta) {
|
|
1010
|
+
if (delta === 0) return this.get();
|
|
1011
|
+
if (delta > 0) {
|
|
1012
|
+
const current = this.state.positive.get(this.nodeId) ?? 0;
|
|
1013
|
+
this.state.positive.set(this.nodeId, current + delta);
|
|
1014
|
+
} else {
|
|
1015
|
+
const current = this.state.negative.get(this.nodeId) ?? 0;
|
|
1016
|
+
this.state.negative.set(this.nodeId, current + Math.abs(delta));
|
|
1017
|
+
}
|
|
1018
|
+
const newValue = this.get();
|
|
1019
|
+
this.notifyListeners(newValue);
|
|
1020
|
+
return newValue;
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Get a copy of the current state for synchronization.
|
|
1024
|
+
*/
|
|
1025
|
+
getState() {
|
|
1026
|
+
return {
|
|
1027
|
+
positive: new Map(this.state.positive),
|
|
1028
|
+
negative: new Map(this.state.negative)
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Merge remote state into this counter.
|
|
1033
|
+
* Takes the maximum value for each node in both positive and negative counters.
|
|
1034
|
+
* This operation is commutative, associative, and idempotent (CRDT properties).
|
|
1035
|
+
*
|
|
1036
|
+
* @param remote The remote state to merge
|
|
1037
|
+
*/
|
|
1038
|
+
merge(remote) {
|
|
1039
|
+
let changed = false;
|
|
1040
|
+
for (const [nodeId, value] of remote.positive) {
|
|
1041
|
+
const current = this.state.positive.get(nodeId) ?? 0;
|
|
1042
|
+
if (value > current) {
|
|
1043
|
+
this.state.positive.set(nodeId, value);
|
|
1044
|
+
changed = true;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
for (const [nodeId, value] of remote.negative) {
|
|
1048
|
+
const current = this.state.negative.get(nodeId) ?? 0;
|
|
1049
|
+
if (value > current) {
|
|
1050
|
+
this.state.negative.set(nodeId, value);
|
|
1051
|
+
changed = true;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
if (changed) {
|
|
1055
|
+
this.notifyListeners(this.get());
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Subscribe to value changes.
|
|
1060
|
+
* The listener is immediately called with the current value.
|
|
1061
|
+
*
|
|
1062
|
+
* @param listener Callback function receiving the new value
|
|
1063
|
+
* @returns Unsubscribe function
|
|
1064
|
+
*/
|
|
1065
|
+
subscribe(listener) {
|
|
1066
|
+
this.listeners.add(listener);
|
|
1067
|
+
listener(this.get());
|
|
1068
|
+
return () => this.listeners.delete(listener);
|
|
1069
|
+
}
|
|
1070
|
+
notifyListeners(value) {
|
|
1071
|
+
for (const listener of this.listeners) {
|
|
1072
|
+
try {
|
|
1073
|
+
listener(value);
|
|
1074
|
+
} catch (e) {
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Get the node ID of this counter instance.
|
|
1080
|
+
*/
|
|
1081
|
+
getNodeId() {
|
|
1082
|
+
return this.nodeId;
|
|
1083
|
+
}
|
|
1084
|
+
// ============================================
|
|
1085
|
+
// Serialization
|
|
1086
|
+
// ============================================
|
|
1087
|
+
/**
|
|
1088
|
+
* Serialize state to binary format (msgpack).
|
|
1089
|
+
*/
|
|
1090
|
+
static serialize(state) {
|
|
1091
|
+
const obj = {
|
|
1092
|
+
p: Object.fromEntries(state.positive),
|
|
1093
|
+
n: Object.fromEntries(state.negative)
|
|
1094
|
+
};
|
|
1095
|
+
return serialize(obj);
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Deserialize binary data to state.
|
|
1099
|
+
*/
|
|
1100
|
+
static deserialize(data) {
|
|
1101
|
+
const obj = deserialize(data);
|
|
1102
|
+
return {
|
|
1103
|
+
positive: new Map(Object.entries(obj.p)),
|
|
1104
|
+
negative: new Map(Object.entries(obj.n))
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Convert state to plain object (for JSON/network).
|
|
1109
|
+
*/
|
|
1110
|
+
static stateToObject(state) {
|
|
1111
|
+
return {
|
|
1112
|
+
p: Object.fromEntries(state.positive),
|
|
1113
|
+
n: Object.fromEntries(state.negative)
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Convert plain object to state.
|
|
1118
|
+
*/
|
|
1119
|
+
static objectToState(obj) {
|
|
1120
|
+
return {
|
|
1121
|
+
positive: new Map(Object.entries(obj.p)),
|
|
1122
|
+
negative: new Map(Object.entries(obj.n))
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
};
|
|
1126
|
+
|
|
1127
|
+
// src/Ringbuffer.ts
|
|
1128
|
+
var Ringbuffer = class {
|
|
1129
|
+
// Next sequence to write
|
|
1130
|
+
constructor(capacity) {
|
|
1131
|
+
this.headSequence = 0n;
|
|
1132
|
+
// Oldest available sequence
|
|
1133
|
+
this.tailSequence = 0n;
|
|
1134
|
+
if (capacity < 1) {
|
|
1135
|
+
throw new Error("Capacity must be >= 1");
|
|
1136
|
+
}
|
|
1137
|
+
this._capacity = capacity;
|
|
1138
|
+
this.buffer = new Array(capacity);
|
|
1139
|
+
}
|
|
1140
|
+
/**
|
|
1141
|
+
* Add item to buffer, returns sequence number.
|
|
1142
|
+
*/
|
|
1143
|
+
add(item) {
|
|
1144
|
+
const sequence = this.tailSequence;
|
|
1145
|
+
const index = Number(sequence % BigInt(this._capacity));
|
|
1146
|
+
this.buffer[index] = item;
|
|
1147
|
+
this.tailSequence++;
|
|
1148
|
+
if (this.tailSequence - this.headSequence > this._capacity) {
|
|
1149
|
+
this.headSequence = this.tailSequence - BigInt(this._capacity);
|
|
1150
|
+
}
|
|
1151
|
+
return sequence;
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Read item at sequence.
|
|
1155
|
+
* Returns undefined if sequence is out of range.
|
|
1156
|
+
*/
|
|
1157
|
+
read(sequence) {
|
|
1158
|
+
if (sequence < this.headSequence || sequence >= this.tailSequence) {
|
|
1159
|
+
return void 0;
|
|
1160
|
+
}
|
|
1161
|
+
const index = Number(sequence % BigInt(this._capacity));
|
|
1162
|
+
return this.buffer[index];
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Read range of items (inclusive).
|
|
1166
|
+
* Automatically clamps to available range.
|
|
1167
|
+
*/
|
|
1168
|
+
readRange(startSeq, endSeq) {
|
|
1169
|
+
const items = [];
|
|
1170
|
+
const actualStart = startSeq < this.headSequence ? this.headSequence : startSeq;
|
|
1171
|
+
const actualEnd = endSeq >= this.tailSequence ? this.tailSequence - 1n : endSeq;
|
|
1172
|
+
for (let seq = actualStart; seq <= actualEnd; seq++) {
|
|
1173
|
+
const item = this.read(seq);
|
|
1174
|
+
if (item !== void 0) {
|
|
1175
|
+
items.push(item);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return items;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Read from sequence with limit.
|
|
1182
|
+
*/
|
|
1183
|
+
readFrom(startSeq, limit = 100) {
|
|
1184
|
+
const endSeq = startSeq + BigInt(limit) - 1n;
|
|
1185
|
+
return this.readRange(startSeq, endSeq);
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Get the oldest available sequence number.
|
|
1189
|
+
*/
|
|
1190
|
+
getHeadSequence() {
|
|
1191
|
+
return this.headSequence;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Get the next sequence number to be written.
|
|
1195
|
+
*/
|
|
1196
|
+
getTailSequence() {
|
|
1197
|
+
return this.tailSequence;
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Get the number of items currently in the buffer.
|
|
1201
|
+
*/
|
|
1202
|
+
size() {
|
|
1203
|
+
return Number(this.tailSequence - this.headSequence);
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Get the maximum capacity of the buffer.
|
|
1207
|
+
*/
|
|
1208
|
+
getCapacity() {
|
|
1209
|
+
return this._capacity;
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* Clear all items from the buffer.
|
|
1213
|
+
*/
|
|
1214
|
+
clear() {
|
|
1215
|
+
this.buffer = new Array(this._capacity);
|
|
1216
|
+
this.headSequence = 0n;
|
|
1217
|
+
this.tailSequence = 0n;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Check if a sequence is available in the buffer.
|
|
1221
|
+
*/
|
|
1222
|
+
isAvailable(sequence) {
|
|
1223
|
+
return sequence >= this.headSequence && sequence < this.tailSequence;
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Get remaining capacity before oldest entries are overwritten.
|
|
1227
|
+
*/
|
|
1228
|
+
remainingCapacity() {
|
|
1229
|
+
return this._capacity - this.size();
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
// src/EventJournal.ts
|
|
1234
|
+
var DEFAULT_EVENT_JOURNAL_CONFIG = {
|
|
1235
|
+
capacity: 1e4,
|
|
1236
|
+
ttlMs: 0,
|
|
1237
|
+
// Infinite
|
|
1238
|
+
persistent: true,
|
|
1239
|
+
includeMaps: [],
|
|
1240
|
+
excludeMaps: []
|
|
1241
|
+
};
|
|
1242
|
+
var EventJournalImpl = class {
|
|
1243
|
+
constructor(config = {}) {
|
|
1244
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
1245
|
+
this.config = { ...DEFAULT_EVENT_JOURNAL_CONFIG, ...config };
|
|
1246
|
+
this.buffer = new Ringbuffer(this.config.capacity);
|
|
1247
|
+
if (this.config.ttlMs > 0) {
|
|
1248
|
+
this.startTTLCleanup();
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Append event to journal.
|
|
1253
|
+
* Returns the event with assigned sequence number.
|
|
1254
|
+
* Returns event with sequence -1n if map is filtered out.
|
|
1255
|
+
*/
|
|
1256
|
+
append(eventData) {
|
|
1257
|
+
if (!this.shouldCapture(eventData.mapName)) {
|
|
1258
|
+
return { ...eventData, sequence: -1n };
|
|
1259
|
+
}
|
|
1260
|
+
const event = {
|
|
1261
|
+
...eventData,
|
|
1262
|
+
sequence: 0n
|
|
1263
|
+
// Will be set by buffer
|
|
1264
|
+
};
|
|
1265
|
+
const sequence = this.buffer.add(event);
|
|
1266
|
+
event.sequence = sequence;
|
|
1267
|
+
for (const listener of this.listeners) {
|
|
1268
|
+
try {
|
|
1269
|
+
listener(event);
|
|
1270
|
+
} catch (e) {
|
|
1271
|
+
console.error("EventJournal listener error:", e);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
return event;
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Read events from sequence with optional limit.
|
|
1278
|
+
*/
|
|
1279
|
+
readFrom(sequence, limit = 100) {
|
|
1280
|
+
return this.buffer.readFrom(sequence, limit);
|
|
1281
|
+
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Read events in range (inclusive).
|
|
1284
|
+
*/
|
|
1285
|
+
readRange(startSeq, endSeq) {
|
|
1286
|
+
return this.buffer.readRange(startSeq, endSeq);
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Get latest sequence number.
|
|
1290
|
+
* Returns 0n if no events have been added.
|
|
1291
|
+
*/
|
|
1292
|
+
getLatestSequence() {
|
|
1293
|
+
const tail = this.buffer.getTailSequence();
|
|
1294
|
+
return tail > 0n ? tail - 1n : 0n;
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Get oldest available sequence number.
|
|
1298
|
+
*/
|
|
1299
|
+
getOldestSequence() {
|
|
1300
|
+
return this.buffer.getHeadSequence();
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Subscribe to new events.
|
|
1304
|
+
* Optionally replay events from a specific sequence.
|
|
1305
|
+
*
|
|
1306
|
+
* @param listener Callback for each event
|
|
1307
|
+
* @param fromSequence Optional sequence to start replay from
|
|
1308
|
+
* @returns Unsubscribe function
|
|
1309
|
+
*/
|
|
1310
|
+
subscribe(listener, fromSequence) {
|
|
1311
|
+
if (fromSequence !== void 0) {
|
|
1312
|
+
const events = this.readFrom(fromSequence, this.config.capacity);
|
|
1313
|
+
for (const event of events) {
|
|
1314
|
+
try {
|
|
1315
|
+
listener(event);
|
|
1316
|
+
} catch (e) {
|
|
1317
|
+
console.error("EventJournal replay error:", e);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
this.listeners.add(listener);
|
|
1322
|
+
return () => this.listeners.delete(listener);
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* Get capacity information.
|
|
1326
|
+
*/
|
|
1327
|
+
getCapacity() {
|
|
1328
|
+
return {
|
|
1329
|
+
used: this.buffer.size(),
|
|
1330
|
+
total: this.buffer.getCapacity()
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Force compaction.
|
|
1335
|
+
* Note: The ringbuffer handles eviction automatically.
|
|
1336
|
+
* This method is provided for explicit cleanup of old events.
|
|
1337
|
+
*/
|
|
1338
|
+
async compact() {
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Check if a map should be captured.
|
|
1342
|
+
*/
|
|
1343
|
+
shouldCapture(mapName) {
|
|
1344
|
+
const { includeMaps, excludeMaps } = this.config;
|
|
1345
|
+
if (excludeMaps && excludeMaps.includes(mapName)) {
|
|
1346
|
+
return false;
|
|
1347
|
+
}
|
|
1348
|
+
if (includeMaps && includeMaps.length > 0) {
|
|
1349
|
+
return includeMaps.includes(mapName);
|
|
1350
|
+
}
|
|
1351
|
+
return true;
|
|
1352
|
+
}
|
|
1353
|
+
/**
|
|
1354
|
+
* Start TTL cleanup timer.
|
|
1355
|
+
*/
|
|
1356
|
+
startTTLCleanup() {
|
|
1357
|
+
const interval = Math.min(this.config.ttlMs, 6e4);
|
|
1358
|
+
this.ttlTimer = setInterval(() => {
|
|
1359
|
+
this.compact();
|
|
1360
|
+
}, interval);
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* Dispose resources.
|
|
1364
|
+
*/
|
|
1365
|
+
dispose() {
|
|
1366
|
+
if (this.ttlTimer) {
|
|
1367
|
+
clearInterval(this.ttlTimer);
|
|
1368
|
+
this.ttlTimer = void 0;
|
|
1369
|
+
}
|
|
1370
|
+
this.listeners.clear();
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* Get all current listeners count (for testing).
|
|
1374
|
+
*/
|
|
1375
|
+
getListenerCount() {
|
|
1376
|
+
return this.listeners.size;
|
|
1377
|
+
}
|
|
1378
|
+
/**
|
|
1379
|
+
* Get configuration (for testing).
|
|
1380
|
+
*/
|
|
1381
|
+
getConfig() {
|
|
1382
|
+
return { ...this.config };
|
|
1383
|
+
}
|
|
1384
|
+
};
|
|
1385
|
+
|
|
1386
|
+
// src/EntryProcessor.ts
|
|
1387
|
+
import { z } from "zod";
|
|
1388
|
+
var EntryProcessorDefSchema = z.object({
|
|
1389
|
+
name: z.string().min(1).max(100),
|
|
1390
|
+
code: z.string().min(1).max(1e4),
|
|
1391
|
+
// Max 10KB code
|
|
1392
|
+
args: z.unknown().optional()
|
|
1393
|
+
});
|
|
1394
|
+
var FORBIDDEN_PATTERNS = [
|
|
1395
|
+
/\beval\b/,
|
|
1396
|
+
/\bFunction\b/,
|
|
1397
|
+
/\bprocess\b/,
|
|
1398
|
+
/\bglobal\b/,
|
|
1399
|
+
/\brequire\b/,
|
|
1400
|
+
/\bimport\b/,
|
|
1401
|
+
/\bfetch\b/,
|
|
1402
|
+
/\bXMLHttpRequest\b/,
|
|
1403
|
+
/\bsetTimeout\b/,
|
|
1404
|
+
/\bsetInterval\b/,
|
|
1405
|
+
/\bsetImmediate\b/
|
|
1406
|
+
];
|
|
1407
|
+
function validateProcessorCode(code) {
|
|
1408
|
+
for (const pattern of FORBIDDEN_PATTERNS) {
|
|
1409
|
+
if (pattern.test(code)) {
|
|
1410
|
+
return {
|
|
1411
|
+
valid: false,
|
|
1412
|
+
error: `Forbidden pattern detected: ${pattern.source}`
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
return { valid: true };
|
|
1417
|
+
}
|
|
1418
|
+
var BuiltInProcessors = {
|
|
1419
|
+
/**
|
|
1420
|
+
* Increment numeric value by delta.
|
|
1421
|
+
* If value doesn't exist, starts from 0.
|
|
1422
|
+
*/
|
|
1423
|
+
INCREMENT: (delta = 1) => ({
|
|
1424
|
+
name: "builtin:increment",
|
|
1425
|
+
code: `
|
|
1426
|
+
const current = value ?? 0;
|
|
1427
|
+
const newValue = current + args;
|
|
1428
|
+
return { value: newValue, result: newValue };
|
|
1429
|
+
`,
|
|
1430
|
+
args: delta
|
|
1431
|
+
}),
|
|
1432
|
+
/**
|
|
1433
|
+
* Decrement numeric value by delta.
|
|
1434
|
+
* If value doesn't exist, starts from 0.
|
|
1435
|
+
*/
|
|
1436
|
+
DECREMENT: (delta = 1) => ({
|
|
1437
|
+
name: "builtin:decrement",
|
|
1438
|
+
code: `
|
|
1439
|
+
const current = value ?? 0;
|
|
1440
|
+
const newValue = current - args;
|
|
1441
|
+
return { value: newValue, result: newValue };
|
|
1442
|
+
`,
|
|
1443
|
+
args: delta
|
|
1444
|
+
}),
|
|
1445
|
+
/**
|
|
1446
|
+
* Decrement with floor (won't go below 0).
|
|
1447
|
+
* Returns both the new value and whether it was floored.
|
|
1448
|
+
*/
|
|
1449
|
+
DECREMENT_FLOOR: (delta = 1) => ({
|
|
1450
|
+
name: "builtin:decrement_floor",
|
|
1451
|
+
code: `
|
|
1452
|
+
const current = value ?? 0;
|
|
1453
|
+
const target = current - args;
|
|
1454
|
+
const newValue = Math.max(0, target);
|
|
1455
|
+
return {
|
|
1456
|
+
value: newValue,
|
|
1457
|
+
result: { newValue, wasFloored: target < 0 }
|
|
1458
|
+
};
|
|
1459
|
+
`,
|
|
1460
|
+
args: delta
|
|
1461
|
+
}),
|
|
1462
|
+
/**
|
|
1463
|
+
* Multiply numeric value by factor.
|
|
1464
|
+
* If value doesn't exist, starts from 1.
|
|
1465
|
+
*/
|
|
1466
|
+
MULTIPLY: (factor) => ({
|
|
1467
|
+
name: "builtin:multiply",
|
|
1468
|
+
code: `
|
|
1469
|
+
const current = value ?? 1;
|
|
1470
|
+
const newValue = current * args;
|
|
1471
|
+
return { value: newValue, result: newValue };
|
|
1472
|
+
`,
|
|
1473
|
+
args: factor
|
|
1474
|
+
}),
|
|
1475
|
+
/**
|
|
1476
|
+
* Set value only if key doesn't exist.
|
|
1477
|
+
* Returns true if value was set, false if key already existed.
|
|
1478
|
+
*/
|
|
1479
|
+
PUT_IF_ABSENT: (newValue) => ({
|
|
1480
|
+
name: "builtin:put_if_absent",
|
|
1481
|
+
code: `
|
|
1482
|
+
if (value !== undefined) {
|
|
1483
|
+
return { value, result: false };
|
|
1484
|
+
}
|
|
1485
|
+
return { value: args, result: true };
|
|
1486
|
+
`,
|
|
1487
|
+
args: newValue
|
|
1488
|
+
}),
|
|
1489
|
+
/**
|
|
1490
|
+
* Replace value only if key exists.
|
|
1491
|
+
* Returns the old value if replaced, undefined otherwise.
|
|
1492
|
+
*/
|
|
1493
|
+
REPLACE: (newValue) => ({
|
|
1494
|
+
name: "builtin:replace",
|
|
1495
|
+
code: `
|
|
1496
|
+
if (value === undefined) {
|
|
1497
|
+
return { value: undefined, result: undefined };
|
|
1498
|
+
}
|
|
1499
|
+
return { value: args, result: value };
|
|
1500
|
+
`,
|
|
1501
|
+
args: newValue
|
|
1502
|
+
}),
|
|
1503
|
+
/**
|
|
1504
|
+
* Replace value only if it matches expected value.
|
|
1505
|
+
* Returns true if replaced, false otherwise.
|
|
1506
|
+
*/
|
|
1507
|
+
REPLACE_IF_EQUALS: (expectedValue, newValue) => ({
|
|
1508
|
+
name: "builtin:replace_if_equals",
|
|
1509
|
+
code: `
|
|
1510
|
+
if (JSON.stringify(value) === JSON.stringify(args.expected)) {
|
|
1511
|
+
return { value: args.newValue, result: true };
|
|
1512
|
+
}
|
|
1513
|
+
return { value, result: false };
|
|
1514
|
+
`,
|
|
1515
|
+
args: { expected: expectedValue, newValue }
|
|
1516
|
+
}),
|
|
1517
|
+
/**
|
|
1518
|
+
* Delete entry only if value matches.
|
|
1519
|
+
* Returns true if deleted, false otherwise.
|
|
1520
|
+
*/
|
|
1521
|
+
DELETE_IF_EQUALS: (expectedValue) => ({
|
|
1522
|
+
name: "builtin:delete_if_equals",
|
|
1523
|
+
code: `
|
|
1524
|
+
if (JSON.stringify(value) === JSON.stringify(args)) {
|
|
1525
|
+
return { value: undefined, result: true };
|
|
1526
|
+
}
|
|
1527
|
+
return { value, result: false };
|
|
1528
|
+
`,
|
|
1529
|
+
args: expectedValue
|
|
1530
|
+
}),
|
|
1531
|
+
/**
|
|
1532
|
+
* Append item to array.
|
|
1533
|
+
* Creates array if it doesn't exist.
|
|
1534
|
+
* Returns new array length.
|
|
1535
|
+
*/
|
|
1536
|
+
ARRAY_PUSH: (item) => ({
|
|
1537
|
+
name: "builtin:array_push",
|
|
1538
|
+
code: `
|
|
1539
|
+
const arr = value ?? [];
|
|
1540
|
+
arr.push(args);
|
|
1541
|
+
return { value: arr, result: arr.length };
|
|
1542
|
+
`,
|
|
1543
|
+
args: item
|
|
1544
|
+
}),
|
|
1545
|
+
/**
|
|
1546
|
+
* Remove last item from array.
|
|
1547
|
+
* Returns the removed item or undefined.
|
|
1548
|
+
*/
|
|
1549
|
+
ARRAY_POP: () => ({
|
|
1550
|
+
name: "builtin:array_pop",
|
|
1551
|
+
code: `
|
|
1552
|
+
if (!value || value.length === 0) {
|
|
1553
|
+
return { value: value ?? [], result: undefined };
|
|
1554
|
+
}
|
|
1555
|
+
const removed = value.pop();
|
|
1556
|
+
return { value, result: removed };
|
|
1557
|
+
`
|
|
1558
|
+
}),
|
|
1559
|
+
/**
|
|
1560
|
+
* Remove item from array by value (first occurrence).
|
|
1561
|
+
* Returns true if item was found and removed.
|
|
1562
|
+
*/
|
|
1563
|
+
ARRAY_REMOVE: (item) => ({
|
|
1564
|
+
name: "builtin:array_remove",
|
|
1565
|
+
code: `
|
|
1566
|
+
if (!value) {
|
|
1567
|
+
return { value: [], result: false };
|
|
1568
|
+
}
|
|
1569
|
+
const idx = value.findIndex(v => JSON.stringify(v) === JSON.stringify(args));
|
|
1570
|
+
if (idx === -1) {
|
|
1571
|
+
return { value, result: false };
|
|
1572
|
+
}
|
|
1573
|
+
value.splice(idx, 1);
|
|
1574
|
+
return { value, result: true };
|
|
1575
|
+
`,
|
|
1576
|
+
args: item
|
|
1577
|
+
}),
|
|
1578
|
+
/**
|
|
1579
|
+
* Update nested property using dot notation path.
|
|
1580
|
+
* Creates intermediate objects if they don't exist.
|
|
1581
|
+
*/
|
|
1582
|
+
SET_PROPERTY: (path, propValue) => ({
|
|
1583
|
+
name: "builtin:set_property",
|
|
1584
|
+
code: `
|
|
1585
|
+
const obj = value ?? {};
|
|
1586
|
+
const parts = args.path.split('.');
|
|
1587
|
+
let current = obj;
|
|
1588
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
1589
|
+
current[parts[i]] = current[parts[i]] ?? {};
|
|
1590
|
+
current = current[parts[i]];
|
|
1591
|
+
}
|
|
1592
|
+
current[parts[parts.length - 1]] = args.value;
|
|
1593
|
+
return { value: obj, result: obj };
|
|
1594
|
+
`,
|
|
1595
|
+
args: { path, value: propValue }
|
|
1596
|
+
}),
|
|
1597
|
+
/**
|
|
1598
|
+
* Delete nested property using dot notation path.
|
|
1599
|
+
* Returns the deleted value or undefined.
|
|
1600
|
+
*/
|
|
1601
|
+
DELETE_PROPERTY: (path) => ({
|
|
1602
|
+
name: "builtin:delete_property",
|
|
1603
|
+
code: `
|
|
1604
|
+
if (!value) {
|
|
1605
|
+
return { value, result: undefined };
|
|
1606
|
+
}
|
|
1607
|
+
const parts = args.split('.');
|
|
1608
|
+
let current = value;
|
|
1609
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
1610
|
+
if (!current[parts[i]]) {
|
|
1611
|
+
return { value, result: undefined };
|
|
1612
|
+
}
|
|
1613
|
+
current = current[parts[i]];
|
|
1614
|
+
}
|
|
1615
|
+
const lastKey = parts[parts.length - 1];
|
|
1616
|
+
const deleted = current[lastKey];
|
|
1617
|
+
delete current[lastKey];
|
|
1618
|
+
return { value, result: deleted };
|
|
1619
|
+
`,
|
|
1620
|
+
args: path
|
|
1621
|
+
}),
|
|
1622
|
+
/**
|
|
1623
|
+
* Get current value without modifying it.
|
|
1624
|
+
* Useful for conditional reads.
|
|
1625
|
+
*/
|
|
1626
|
+
GET: () => ({
|
|
1627
|
+
name: "builtin:get",
|
|
1628
|
+
code: `
|
|
1629
|
+
return { value, result: value };
|
|
1630
|
+
`
|
|
1631
|
+
}),
|
|
1632
|
+
/**
|
|
1633
|
+
* Conditional update based on version/timestamp.
|
|
1634
|
+
* Only updates if current version matches expected.
|
|
1635
|
+
* Useful for optimistic locking.
|
|
1636
|
+
*/
|
|
1637
|
+
CONDITIONAL_UPDATE: (expectedVersion, newData) => ({
|
|
1638
|
+
name: "builtin:conditional_update",
|
|
1639
|
+
code: `
|
|
1640
|
+
if (!value || value.version !== args.expectedVersion) {
|
|
1641
|
+
return {
|
|
1642
|
+
value,
|
|
1643
|
+
result: { updated: false, conflict: true }
|
|
1644
|
+
};
|
|
1645
|
+
}
|
|
1646
|
+
const updated = {
|
|
1647
|
+
...value,
|
|
1648
|
+
...args.newData,
|
|
1649
|
+
version: (value.version ?? 0) + 1,
|
|
1650
|
+
};
|
|
1651
|
+
return {
|
|
1652
|
+
value: updated,
|
|
1653
|
+
result: { updated: true, conflict: false }
|
|
1654
|
+
};
|
|
1655
|
+
`,
|
|
1656
|
+
args: { expectedVersion, newData }
|
|
1657
|
+
}),
|
|
1658
|
+
/**
|
|
1659
|
+
* Merge object properties into existing value.
|
|
1660
|
+
* Shallow merge only.
|
|
1661
|
+
*/
|
|
1662
|
+
MERGE: (properties) => ({
|
|
1663
|
+
name: "builtin:merge",
|
|
1664
|
+
code: `
|
|
1665
|
+
const merged = { ...(value ?? {}), ...args };
|
|
1666
|
+
return { value: merged, result: merged };
|
|
1667
|
+
`,
|
|
1668
|
+
args: properties
|
|
1669
|
+
})
|
|
1670
|
+
};
|
|
1671
|
+
var DEFAULT_PROCESSOR_RATE_LIMITS = {
|
|
1672
|
+
maxExecutionsPerSecond: 100,
|
|
1673
|
+
maxCodeSizeBytes: 10240,
|
|
1674
|
+
// 10KB
|
|
1675
|
+
maxArgsSizeBytes: 1048576
|
|
1676
|
+
// 1MB
|
|
1677
|
+
};
|
|
1678
|
+
|
|
1679
|
+
// src/ConflictResolver.ts
|
|
1680
|
+
import { z as z2 } from "zod";
|
|
1681
|
+
var ConflictResolverDefSchema = z2.object({
|
|
1682
|
+
name: z2.string().min(1).max(100),
|
|
1683
|
+
code: z2.string().max(5e4).optional(),
|
|
1684
|
+
priority: z2.number().int().min(0).max(100).default(50),
|
|
1685
|
+
keyPattern: z2.string().optional()
|
|
1686
|
+
});
|
|
1687
|
+
var RESOLVER_FORBIDDEN_PATTERNS = [
|
|
1688
|
+
/\beval\b/,
|
|
1689
|
+
/\bFunction\b/,
|
|
1690
|
+
/\bprocess\b/,
|
|
1691
|
+
/\bglobal\b/,
|
|
1692
|
+
/\brequire\b/,
|
|
1693
|
+
/\bimport\b/,
|
|
1694
|
+
/\bfetch\b/,
|
|
1695
|
+
/\bXMLHttpRequest\b/,
|
|
1696
|
+
/\bsetTimeout\b/,
|
|
1697
|
+
/\bsetInterval\b/,
|
|
1698
|
+
/\bsetImmediate\b/
|
|
1699
|
+
];
|
|
1700
|
+
function validateResolverCode(code) {
|
|
1701
|
+
for (const pattern of RESOLVER_FORBIDDEN_PATTERNS) {
|
|
1702
|
+
if (pattern.test(code)) {
|
|
1703
|
+
return {
|
|
1704
|
+
valid: false,
|
|
1705
|
+
error: `Forbidden pattern detected: ${pattern.source}`
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
return { valid: true };
|
|
1710
|
+
}
|
|
1711
|
+
var DEFAULT_RESOLVER_RATE_LIMITS = {
|
|
1712
|
+
maxResolversPerClient: 50,
|
|
1713
|
+
maxCodeSizeBytes: 5e4
|
|
1714
|
+
// 50KB
|
|
1715
|
+
};
|
|
1716
|
+
function compareHLCTimestamps(a, b) {
|
|
1717
|
+
return HLC.compare(a, b);
|
|
1718
|
+
}
|
|
1719
|
+
function deepMerge(target, source) {
|
|
1720
|
+
const result = { ...target };
|
|
1721
|
+
for (const key of Object.keys(source)) {
|
|
1722
|
+
const sourceVal = source[key];
|
|
1723
|
+
const targetVal = target[key];
|
|
1724
|
+
if (typeof sourceVal === "object" && sourceVal !== null && typeof targetVal === "object" && targetVal !== null && !Array.isArray(sourceVal)) {
|
|
1725
|
+
result[key] = deepMerge(
|
|
1726
|
+
targetVal,
|
|
1727
|
+
sourceVal
|
|
1728
|
+
);
|
|
1729
|
+
} else {
|
|
1730
|
+
result[key] = sourceVal;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
return result;
|
|
1734
|
+
}
|
|
1735
|
+
var BuiltInResolvers = {
|
|
1736
|
+
/**
|
|
1737
|
+
* Standard Last-Write-Wins - accept if remote timestamp is newer.
|
|
1738
|
+
*/
|
|
1739
|
+
LWW: () => ({
|
|
1740
|
+
name: "builtin:lww",
|
|
1741
|
+
fn: (ctx) => {
|
|
1742
|
+
if (!ctx.localTimestamp) {
|
|
1743
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1744
|
+
}
|
|
1745
|
+
const cmp = compareHLCTimestamps(ctx.remoteTimestamp, ctx.localTimestamp);
|
|
1746
|
+
if (cmp > 0) {
|
|
1747
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1748
|
+
}
|
|
1749
|
+
return { action: "local" };
|
|
1750
|
+
},
|
|
1751
|
+
priority: 0
|
|
1752
|
+
// Lowest priority - fallback
|
|
1753
|
+
}),
|
|
1754
|
+
/**
|
|
1755
|
+
* First-Write-Wins - reject if local value exists.
|
|
1756
|
+
* Useful for booking systems, unique constraints.
|
|
1757
|
+
*/
|
|
1758
|
+
FIRST_WRITE_WINS: () => ({
|
|
1759
|
+
name: "builtin:first_write_wins",
|
|
1760
|
+
fn: (ctx) => {
|
|
1761
|
+
if (ctx.localValue !== void 0) {
|
|
1762
|
+
return { action: "reject", reason: "Entry already exists" };
|
|
1763
|
+
}
|
|
1764
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1765
|
+
},
|
|
1766
|
+
priority: 100
|
|
1767
|
+
}),
|
|
1768
|
+
/**
|
|
1769
|
+
* Numeric minimum - keep lowest value.
|
|
1770
|
+
* Useful for auction systems (lowest bid wins).
|
|
1771
|
+
*/
|
|
1772
|
+
NUMERIC_MIN: () => ({
|
|
1773
|
+
name: "builtin:numeric_min",
|
|
1774
|
+
fn: (ctx) => {
|
|
1775
|
+
const local = ctx.localValue ?? Infinity;
|
|
1776
|
+
const remote = ctx.remoteValue;
|
|
1777
|
+
return { action: "merge", value: Math.min(local, remote) };
|
|
1778
|
+
},
|
|
1779
|
+
priority: 50
|
|
1780
|
+
}),
|
|
1781
|
+
/**
|
|
1782
|
+
* Numeric maximum - keep highest value.
|
|
1783
|
+
* Useful for high score tracking.
|
|
1784
|
+
*/
|
|
1785
|
+
NUMERIC_MAX: () => ({
|
|
1786
|
+
name: "builtin:numeric_max",
|
|
1787
|
+
fn: (ctx) => {
|
|
1788
|
+
const local = ctx.localValue ?? -Infinity;
|
|
1789
|
+
const remote = ctx.remoteValue;
|
|
1790
|
+
return { action: "merge", value: Math.max(local, remote) };
|
|
1791
|
+
},
|
|
1792
|
+
priority: 50
|
|
1793
|
+
}),
|
|
1794
|
+
/**
|
|
1795
|
+
* Non-negative - reject if value would be negative.
|
|
1796
|
+
* Useful for inventory systems.
|
|
1797
|
+
*/
|
|
1798
|
+
NON_NEGATIVE: () => ({
|
|
1799
|
+
name: "builtin:non_negative",
|
|
1800
|
+
fn: (ctx) => {
|
|
1801
|
+
if (typeof ctx.remoteValue !== "number" || ctx.remoteValue < 0) {
|
|
1802
|
+
return { action: "reject", reason: "Value cannot be negative" };
|
|
1803
|
+
}
|
|
1804
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1805
|
+
},
|
|
1806
|
+
priority: 90
|
|
1807
|
+
}),
|
|
1808
|
+
/**
|
|
1809
|
+
* Array union - merge arrays by taking union of elements.
|
|
1810
|
+
* Useful for tags, categories.
|
|
1811
|
+
*/
|
|
1812
|
+
ARRAY_UNION: () => ({
|
|
1813
|
+
name: "builtin:array_union",
|
|
1814
|
+
fn: (ctx) => {
|
|
1815
|
+
const local = ctx.localValue ?? [];
|
|
1816
|
+
const remote = ctx.remoteValue ?? [];
|
|
1817
|
+
const merged = [.../* @__PURE__ */ new Set([...local, ...remote])];
|
|
1818
|
+
return { action: "merge", value: merged };
|
|
1819
|
+
},
|
|
1820
|
+
priority: 50
|
|
1821
|
+
}),
|
|
1822
|
+
/**
|
|
1823
|
+
* Deep merge - recursively merge objects.
|
|
1824
|
+
* Remote values take precedence at leaf level.
|
|
1825
|
+
*/
|
|
1826
|
+
DEEP_MERGE: () => ({
|
|
1827
|
+
name: "builtin:deep_merge",
|
|
1828
|
+
fn: (ctx) => {
|
|
1829
|
+
const local = ctx.localValue ?? {};
|
|
1830
|
+
const remote = ctx.remoteValue;
|
|
1831
|
+
const merged = deepMerge(local, remote);
|
|
1832
|
+
return { action: "merge", value: merged };
|
|
1833
|
+
},
|
|
1834
|
+
priority: 50
|
|
1835
|
+
}),
|
|
1836
|
+
/**
|
|
1837
|
+
* Server-only - reject all client writes.
|
|
1838
|
+
* Useful for server-controlled state.
|
|
1839
|
+
*/
|
|
1840
|
+
SERVER_ONLY: () => ({
|
|
1841
|
+
name: "builtin:server_only",
|
|
1842
|
+
fn: (ctx) => {
|
|
1843
|
+
if (ctx.auth?.roles?.includes("server") || ctx.remoteNodeId.startsWith("server:")) {
|
|
1844
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1845
|
+
}
|
|
1846
|
+
return { action: "reject", reason: "Only server can write to this entry" };
|
|
1847
|
+
},
|
|
1848
|
+
priority: 100
|
|
1849
|
+
}),
|
|
1850
|
+
/**
|
|
1851
|
+
* Owner-only - only the original creator can modify.
|
|
1852
|
+
* Requires value to have an `ownerId` property.
|
|
1853
|
+
*/
|
|
1854
|
+
OWNER_ONLY: () => ({
|
|
1855
|
+
name: "builtin:owner_only",
|
|
1856
|
+
fn: (ctx) => {
|
|
1857
|
+
if (!ctx.localValue) {
|
|
1858
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1859
|
+
}
|
|
1860
|
+
const ownerId = ctx.localValue.ownerId;
|
|
1861
|
+
if (ownerId && ctx.auth?.userId !== ownerId) {
|
|
1862
|
+
return { action: "reject", reason: "Only owner can modify this entry" };
|
|
1863
|
+
}
|
|
1864
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1865
|
+
},
|
|
1866
|
+
priority: 95
|
|
1867
|
+
}),
|
|
1868
|
+
/**
|
|
1869
|
+
* Immutable - reject any modifications after initial write.
|
|
1870
|
+
*/
|
|
1871
|
+
IMMUTABLE: () => ({
|
|
1872
|
+
name: "builtin:immutable",
|
|
1873
|
+
fn: (ctx) => {
|
|
1874
|
+
if (ctx.localValue !== void 0) {
|
|
1875
|
+
return { action: "reject", reason: "Entry is immutable" };
|
|
1876
|
+
}
|
|
1877
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1878
|
+
},
|
|
1879
|
+
priority: 100
|
|
1880
|
+
}),
|
|
1881
|
+
/**
|
|
1882
|
+
* Version check - only accept if version increments by 1.
|
|
1883
|
+
* Useful for optimistic locking.
|
|
1884
|
+
*/
|
|
1885
|
+
VERSION_INCREMENT: () => ({
|
|
1886
|
+
name: "builtin:version_increment",
|
|
1887
|
+
fn: (ctx) => {
|
|
1888
|
+
const localVersion = ctx.localValue?.version ?? 0;
|
|
1889
|
+
const remoteVersion = ctx.remoteValue?.version ?? 0;
|
|
1890
|
+
if (remoteVersion !== localVersion + 1) {
|
|
1891
|
+
return {
|
|
1892
|
+
action: "reject",
|
|
1893
|
+
reason: `Version conflict: expected ${localVersion + 1}, got ${remoteVersion}`
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
return { action: "accept", value: ctx.remoteValue };
|
|
1897
|
+
},
|
|
1898
|
+
priority: 90
|
|
1899
|
+
})
|
|
1900
|
+
};
|
|
1901
|
+
|
|
973
1902
|
// src/predicate.ts
|
|
974
1903
|
var Predicates = class {
|
|
975
1904
|
static equal(attribute, value) {
|
|
@@ -1057,31 +1986,31 @@ function evaluatePredicate(predicate, data) {
|
|
|
1057
1986
|
}
|
|
1058
1987
|
|
|
1059
1988
|
// src/schemas.ts
|
|
1060
|
-
import { z } from "zod";
|
|
1061
|
-
var WriteConcernSchema =
|
|
1989
|
+
import { z as z3 } from "zod";
|
|
1990
|
+
var WriteConcernSchema = z3.enum([
|
|
1062
1991
|
"FIRE_AND_FORGET",
|
|
1063
1992
|
"MEMORY",
|
|
1064
1993
|
"APPLIED",
|
|
1065
1994
|
"REPLICATED",
|
|
1066
1995
|
"PERSISTED"
|
|
1067
1996
|
]);
|
|
1068
|
-
var TimestampSchema =
|
|
1069
|
-
millis:
|
|
1070
|
-
counter:
|
|
1071
|
-
nodeId:
|
|
1997
|
+
var TimestampSchema = z3.object({
|
|
1998
|
+
millis: z3.union([z3.number(), z3.bigint()]).transform(Number),
|
|
1999
|
+
counter: z3.union([z3.number(), z3.bigint()]).transform(Number),
|
|
2000
|
+
nodeId: z3.string()
|
|
1072
2001
|
});
|
|
1073
|
-
var LWWRecordSchema =
|
|
1074
|
-
value:
|
|
2002
|
+
var LWWRecordSchema = z3.object({
|
|
2003
|
+
value: z3.any().nullable(),
|
|
1075
2004
|
timestamp: TimestampSchema,
|
|
1076
|
-
ttlMs:
|
|
2005
|
+
ttlMs: z3.number().optional()
|
|
1077
2006
|
});
|
|
1078
|
-
var ORMapRecordSchema =
|
|
1079
|
-
value:
|
|
2007
|
+
var ORMapRecordSchema = z3.object({
|
|
2008
|
+
value: z3.any(),
|
|
1080
2009
|
timestamp: TimestampSchema,
|
|
1081
|
-
tag:
|
|
1082
|
-
ttlMs:
|
|
2010
|
+
tag: z3.string(),
|
|
2011
|
+
ttlMs: z3.number().optional()
|
|
1083
2012
|
});
|
|
1084
|
-
var PredicateOpSchema =
|
|
2013
|
+
var PredicateOpSchema = z3.enum([
|
|
1085
2014
|
"eq",
|
|
1086
2015
|
"neq",
|
|
1087
2016
|
"gt",
|
|
@@ -1094,266 +2023,438 @@ var PredicateOpSchema = z.enum([
|
|
|
1094
2023
|
"or",
|
|
1095
2024
|
"not"
|
|
1096
2025
|
]);
|
|
1097
|
-
var PredicateNodeSchema =
|
|
2026
|
+
var PredicateNodeSchema = z3.lazy(() => z3.object({
|
|
1098
2027
|
op: PredicateOpSchema,
|
|
1099
|
-
attribute:
|
|
1100
|
-
value:
|
|
1101
|
-
children:
|
|
2028
|
+
attribute: z3.string().optional(),
|
|
2029
|
+
value: z3.any().optional(),
|
|
2030
|
+
children: z3.array(PredicateNodeSchema).optional()
|
|
1102
2031
|
}));
|
|
1103
|
-
var QuerySchema =
|
|
1104
|
-
where:
|
|
2032
|
+
var QuerySchema = z3.object({
|
|
2033
|
+
where: z3.record(z3.string(), z3.any()).optional(),
|
|
1105
2034
|
predicate: PredicateNodeSchema.optional(),
|
|
1106
|
-
sort:
|
|
1107
|
-
limit:
|
|
1108
|
-
offset:
|
|
1109
|
-
});
|
|
1110
|
-
var ClientOpSchema =
|
|
1111
|
-
id:
|
|
1112
|
-
mapName:
|
|
1113
|
-
key:
|
|
2035
|
+
sort: z3.record(z3.string(), z3.enum(["asc", "desc"])).optional(),
|
|
2036
|
+
limit: z3.number().optional(),
|
|
2037
|
+
offset: z3.number().optional()
|
|
2038
|
+
});
|
|
2039
|
+
var ClientOpSchema = z3.object({
|
|
2040
|
+
id: z3.string().optional(),
|
|
2041
|
+
mapName: z3.string(),
|
|
2042
|
+
key: z3.string(),
|
|
1114
2043
|
// Permissive opType to match ServerCoordinator behavior logic
|
|
1115
2044
|
// It can be 'REMOVE', 'OR_ADD', 'OR_REMOVE' or undefined/other (implies PUT/LWW)
|
|
1116
|
-
opType:
|
|
2045
|
+
opType: z3.string().optional(),
|
|
1117
2046
|
record: LWWRecordSchema.nullable().optional(),
|
|
1118
2047
|
orRecord: ORMapRecordSchema.nullable().optional(),
|
|
1119
|
-
orTag:
|
|
2048
|
+
orTag: z3.string().nullable().optional(),
|
|
1120
2049
|
// Write Concern fields (Phase 5.01)
|
|
1121
2050
|
writeConcern: WriteConcernSchema.optional(),
|
|
1122
|
-
timeout:
|
|
2051
|
+
timeout: z3.number().optional()
|
|
1123
2052
|
});
|
|
1124
|
-
var AuthMessageSchema =
|
|
1125
|
-
type:
|
|
1126
|
-
token:
|
|
2053
|
+
var AuthMessageSchema = z3.object({
|
|
2054
|
+
type: z3.literal("AUTH"),
|
|
2055
|
+
token: z3.string()
|
|
1127
2056
|
});
|
|
1128
|
-
var QuerySubMessageSchema =
|
|
1129
|
-
type:
|
|
1130
|
-
payload:
|
|
1131
|
-
queryId:
|
|
1132
|
-
mapName:
|
|
2057
|
+
var QuerySubMessageSchema = z3.object({
|
|
2058
|
+
type: z3.literal("QUERY_SUB"),
|
|
2059
|
+
payload: z3.object({
|
|
2060
|
+
queryId: z3.string(),
|
|
2061
|
+
mapName: z3.string(),
|
|
1133
2062
|
query: QuerySchema
|
|
1134
2063
|
})
|
|
1135
2064
|
});
|
|
1136
|
-
var QueryUnsubMessageSchema =
|
|
1137
|
-
type:
|
|
1138
|
-
payload:
|
|
1139
|
-
queryId:
|
|
2065
|
+
var QueryUnsubMessageSchema = z3.object({
|
|
2066
|
+
type: z3.literal("QUERY_UNSUB"),
|
|
2067
|
+
payload: z3.object({
|
|
2068
|
+
queryId: z3.string()
|
|
1140
2069
|
})
|
|
1141
2070
|
});
|
|
1142
|
-
var ClientOpMessageSchema =
|
|
1143
|
-
type:
|
|
2071
|
+
var ClientOpMessageSchema = z3.object({
|
|
2072
|
+
type: z3.literal("CLIENT_OP"),
|
|
1144
2073
|
payload: ClientOpSchema
|
|
1145
2074
|
});
|
|
1146
|
-
var OpBatchMessageSchema =
|
|
1147
|
-
type:
|
|
1148
|
-
payload:
|
|
1149
|
-
ops:
|
|
2075
|
+
var OpBatchMessageSchema = z3.object({
|
|
2076
|
+
type: z3.literal("OP_BATCH"),
|
|
2077
|
+
payload: z3.object({
|
|
2078
|
+
ops: z3.array(ClientOpSchema),
|
|
1150
2079
|
// Batch-level Write Concern (can be overridden per-op)
|
|
1151
2080
|
writeConcern: WriteConcernSchema.optional(),
|
|
1152
|
-
timeout:
|
|
2081
|
+
timeout: z3.number().optional()
|
|
1153
2082
|
})
|
|
1154
2083
|
});
|
|
1155
|
-
var SyncInitMessageSchema =
|
|
1156
|
-
type:
|
|
1157
|
-
mapName:
|
|
1158
|
-
lastSyncTimestamp:
|
|
2084
|
+
var SyncInitMessageSchema = z3.object({
|
|
2085
|
+
type: z3.literal("SYNC_INIT"),
|
|
2086
|
+
mapName: z3.string(),
|
|
2087
|
+
lastSyncTimestamp: z3.number().optional()
|
|
1159
2088
|
});
|
|
1160
|
-
var SyncRespRootMessageSchema =
|
|
1161
|
-
type:
|
|
1162
|
-
payload:
|
|
1163
|
-
mapName:
|
|
1164
|
-
rootHash:
|
|
2089
|
+
var SyncRespRootMessageSchema = z3.object({
|
|
2090
|
+
type: z3.literal("SYNC_RESP_ROOT"),
|
|
2091
|
+
payload: z3.object({
|
|
2092
|
+
mapName: z3.string(),
|
|
2093
|
+
rootHash: z3.number(),
|
|
1165
2094
|
timestamp: TimestampSchema
|
|
1166
2095
|
})
|
|
1167
2096
|
});
|
|
1168
|
-
var SyncRespBucketsMessageSchema =
|
|
1169
|
-
type:
|
|
1170
|
-
payload:
|
|
1171
|
-
mapName:
|
|
1172
|
-
path:
|
|
1173
|
-
buckets:
|
|
2097
|
+
var SyncRespBucketsMessageSchema = z3.object({
|
|
2098
|
+
type: z3.literal("SYNC_RESP_BUCKETS"),
|
|
2099
|
+
payload: z3.object({
|
|
2100
|
+
mapName: z3.string(),
|
|
2101
|
+
path: z3.string(),
|
|
2102
|
+
buckets: z3.record(z3.string(), z3.number())
|
|
1174
2103
|
})
|
|
1175
2104
|
});
|
|
1176
|
-
var SyncRespLeafMessageSchema =
|
|
1177
|
-
type:
|
|
1178
|
-
payload:
|
|
1179
|
-
mapName:
|
|
1180
|
-
path:
|
|
1181
|
-
records:
|
|
1182
|
-
key:
|
|
2105
|
+
var SyncRespLeafMessageSchema = z3.object({
|
|
2106
|
+
type: z3.literal("SYNC_RESP_LEAF"),
|
|
2107
|
+
payload: z3.object({
|
|
2108
|
+
mapName: z3.string(),
|
|
2109
|
+
path: z3.string(),
|
|
2110
|
+
records: z3.array(z3.object({
|
|
2111
|
+
key: z3.string(),
|
|
1183
2112
|
record: LWWRecordSchema
|
|
1184
2113
|
}))
|
|
1185
2114
|
})
|
|
1186
2115
|
});
|
|
1187
|
-
var MerkleReqBucketMessageSchema =
|
|
1188
|
-
type:
|
|
1189
|
-
payload:
|
|
1190
|
-
mapName:
|
|
1191
|
-
path:
|
|
2116
|
+
var MerkleReqBucketMessageSchema = z3.object({
|
|
2117
|
+
type: z3.literal("MERKLE_REQ_BUCKET"),
|
|
2118
|
+
payload: z3.object({
|
|
2119
|
+
mapName: z3.string(),
|
|
2120
|
+
path: z3.string()
|
|
1192
2121
|
})
|
|
1193
2122
|
});
|
|
1194
|
-
var LockRequestSchema =
|
|
1195
|
-
type:
|
|
1196
|
-
payload:
|
|
1197
|
-
requestId:
|
|
1198
|
-
name:
|
|
1199
|
-
ttl:
|
|
2123
|
+
var LockRequestSchema = z3.object({
|
|
2124
|
+
type: z3.literal("LOCK_REQUEST"),
|
|
2125
|
+
payload: z3.object({
|
|
2126
|
+
requestId: z3.string(),
|
|
2127
|
+
name: z3.string(),
|
|
2128
|
+
ttl: z3.number().optional()
|
|
1200
2129
|
})
|
|
1201
2130
|
});
|
|
1202
|
-
var LockReleaseSchema =
|
|
1203
|
-
type:
|
|
1204
|
-
payload:
|
|
1205
|
-
requestId:
|
|
1206
|
-
name:
|
|
1207
|
-
fencingToken:
|
|
2131
|
+
var LockReleaseSchema = z3.object({
|
|
2132
|
+
type: z3.literal("LOCK_RELEASE"),
|
|
2133
|
+
payload: z3.object({
|
|
2134
|
+
requestId: z3.string().optional(),
|
|
2135
|
+
name: z3.string(),
|
|
2136
|
+
fencingToken: z3.number()
|
|
1208
2137
|
})
|
|
1209
2138
|
});
|
|
1210
|
-
var TopicSubSchema =
|
|
1211
|
-
type:
|
|
1212
|
-
payload:
|
|
1213
|
-
topic:
|
|
2139
|
+
var TopicSubSchema = z3.object({
|
|
2140
|
+
type: z3.literal("TOPIC_SUB"),
|
|
2141
|
+
payload: z3.object({
|
|
2142
|
+
topic: z3.string()
|
|
1214
2143
|
})
|
|
1215
2144
|
});
|
|
1216
|
-
var TopicUnsubSchema =
|
|
1217
|
-
type:
|
|
1218
|
-
payload:
|
|
1219
|
-
topic:
|
|
2145
|
+
var TopicUnsubSchema = z3.object({
|
|
2146
|
+
type: z3.literal("TOPIC_UNSUB"),
|
|
2147
|
+
payload: z3.object({
|
|
2148
|
+
topic: z3.string()
|
|
1220
2149
|
})
|
|
1221
2150
|
});
|
|
1222
|
-
var TopicPubSchema =
|
|
1223
|
-
type:
|
|
1224
|
-
payload:
|
|
1225
|
-
topic:
|
|
1226
|
-
data:
|
|
2151
|
+
var TopicPubSchema = z3.object({
|
|
2152
|
+
type: z3.literal("TOPIC_PUB"),
|
|
2153
|
+
payload: z3.object({
|
|
2154
|
+
topic: z3.string(),
|
|
2155
|
+
data: z3.any()
|
|
1227
2156
|
})
|
|
1228
2157
|
});
|
|
1229
|
-
var TopicMessageEventSchema =
|
|
1230
|
-
type:
|
|
1231
|
-
payload:
|
|
1232
|
-
topic:
|
|
1233
|
-
data:
|
|
1234
|
-
publisherId:
|
|
1235
|
-
timestamp:
|
|
2158
|
+
var TopicMessageEventSchema = z3.object({
|
|
2159
|
+
type: z3.literal("TOPIC_MESSAGE"),
|
|
2160
|
+
payload: z3.object({
|
|
2161
|
+
topic: z3.string(),
|
|
2162
|
+
data: z3.any(),
|
|
2163
|
+
publisherId: z3.string().optional(),
|
|
2164
|
+
timestamp: z3.number()
|
|
1236
2165
|
})
|
|
1237
2166
|
});
|
|
1238
|
-
var
|
|
1239
|
-
|
|
1240
|
-
|
|
2167
|
+
var PNCounterStateObjectSchema = z3.object({
|
|
2168
|
+
p: z3.record(z3.string(), z3.number()),
|
|
2169
|
+
// positive counts per node
|
|
2170
|
+
n: z3.record(z3.string(), z3.number())
|
|
2171
|
+
// negative counts per node
|
|
2172
|
+
});
|
|
2173
|
+
var CounterRequestSchema = z3.object({
|
|
2174
|
+
type: z3.literal("COUNTER_REQUEST"),
|
|
2175
|
+
payload: z3.object({
|
|
2176
|
+
name: z3.string()
|
|
2177
|
+
})
|
|
2178
|
+
});
|
|
2179
|
+
var CounterSyncSchema = z3.object({
|
|
2180
|
+
type: z3.literal("COUNTER_SYNC"),
|
|
2181
|
+
payload: z3.object({
|
|
2182
|
+
name: z3.string(),
|
|
2183
|
+
state: PNCounterStateObjectSchema
|
|
2184
|
+
})
|
|
2185
|
+
});
|
|
2186
|
+
var CounterResponseSchema = z3.object({
|
|
2187
|
+
type: z3.literal("COUNTER_RESPONSE"),
|
|
2188
|
+
payload: z3.object({
|
|
2189
|
+
name: z3.string(),
|
|
2190
|
+
state: PNCounterStateObjectSchema
|
|
2191
|
+
})
|
|
2192
|
+
});
|
|
2193
|
+
var CounterUpdateSchema = z3.object({
|
|
2194
|
+
type: z3.literal("COUNTER_UPDATE"),
|
|
2195
|
+
payload: z3.object({
|
|
2196
|
+
name: z3.string(),
|
|
2197
|
+
state: PNCounterStateObjectSchema
|
|
2198
|
+
})
|
|
2199
|
+
});
|
|
2200
|
+
var PingMessageSchema = z3.object({
|
|
2201
|
+
type: z3.literal("PING"),
|
|
2202
|
+
timestamp: z3.number()
|
|
1241
2203
|
// Client's Date.now()
|
|
1242
2204
|
});
|
|
1243
|
-
var PongMessageSchema =
|
|
1244
|
-
type:
|
|
1245
|
-
timestamp:
|
|
2205
|
+
var PongMessageSchema = z3.object({
|
|
2206
|
+
type: z3.literal("PONG"),
|
|
2207
|
+
timestamp: z3.number(),
|
|
1246
2208
|
// Echo back client's timestamp
|
|
1247
|
-
serverTime:
|
|
2209
|
+
serverTime: z3.number()
|
|
1248
2210
|
// Server's Date.now() (for clock skew detection)
|
|
1249
2211
|
});
|
|
1250
|
-
var BatchMessageSchema =
|
|
1251
|
-
type:
|
|
1252
|
-
count:
|
|
1253
|
-
data:
|
|
2212
|
+
var BatchMessageSchema = z3.object({
|
|
2213
|
+
type: z3.literal("BATCH"),
|
|
2214
|
+
count: z3.number(),
|
|
2215
|
+
data: z3.instanceof(Uint8Array)
|
|
1254
2216
|
});
|
|
1255
|
-
var ORMapSyncInitSchema =
|
|
1256
|
-
type:
|
|
1257
|
-
mapName:
|
|
1258
|
-
rootHash:
|
|
1259
|
-
bucketHashes:
|
|
2217
|
+
var ORMapSyncInitSchema = z3.object({
|
|
2218
|
+
type: z3.literal("ORMAP_SYNC_INIT"),
|
|
2219
|
+
mapName: z3.string(),
|
|
2220
|
+
rootHash: z3.number(),
|
|
2221
|
+
bucketHashes: z3.record(z3.string(), z3.number()),
|
|
1260
2222
|
// path -> hash
|
|
1261
|
-
lastSyncTimestamp:
|
|
2223
|
+
lastSyncTimestamp: z3.number().optional()
|
|
1262
2224
|
});
|
|
1263
|
-
var ORMapSyncRespRootSchema =
|
|
1264
|
-
type:
|
|
1265
|
-
payload:
|
|
1266
|
-
mapName:
|
|
1267
|
-
rootHash:
|
|
2225
|
+
var ORMapSyncRespRootSchema = z3.object({
|
|
2226
|
+
type: z3.literal("ORMAP_SYNC_RESP_ROOT"),
|
|
2227
|
+
payload: z3.object({
|
|
2228
|
+
mapName: z3.string(),
|
|
2229
|
+
rootHash: z3.number(),
|
|
1268
2230
|
timestamp: TimestampSchema
|
|
1269
2231
|
})
|
|
1270
2232
|
});
|
|
1271
|
-
var ORMapSyncRespBucketsSchema =
|
|
1272
|
-
type:
|
|
1273
|
-
payload:
|
|
1274
|
-
mapName:
|
|
1275
|
-
path:
|
|
1276
|
-
buckets:
|
|
2233
|
+
var ORMapSyncRespBucketsSchema = z3.object({
|
|
2234
|
+
type: z3.literal("ORMAP_SYNC_RESP_BUCKETS"),
|
|
2235
|
+
payload: z3.object({
|
|
2236
|
+
mapName: z3.string(),
|
|
2237
|
+
path: z3.string(),
|
|
2238
|
+
buckets: z3.record(z3.string(), z3.number())
|
|
1277
2239
|
})
|
|
1278
2240
|
});
|
|
1279
|
-
var ORMapMerkleReqBucketSchema =
|
|
1280
|
-
type:
|
|
1281
|
-
payload:
|
|
1282
|
-
mapName:
|
|
1283
|
-
path:
|
|
2241
|
+
var ORMapMerkleReqBucketSchema = z3.object({
|
|
2242
|
+
type: z3.literal("ORMAP_MERKLE_REQ_BUCKET"),
|
|
2243
|
+
payload: z3.object({
|
|
2244
|
+
mapName: z3.string(),
|
|
2245
|
+
path: z3.string()
|
|
1284
2246
|
})
|
|
1285
2247
|
});
|
|
1286
|
-
var ORMapSyncRespLeafSchema =
|
|
1287
|
-
type:
|
|
1288
|
-
payload:
|
|
1289
|
-
mapName:
|
|
1290
|
-
path:
|
|
1291
|
-
entries:
|
|
1292
|
-
key:
|
|
1293
|
-
records:
|
|
1294
|
-
tombstones:
|
|
2248
|
+
var ORMapSyncRespLeafSchema = z3.object({
|
|
2249
|
+
type: z3.literal("ORMAP_SYNC_RESP_LEAF"),
|
|
2250
|
+
payload: z3.object({
|
|
2251
|
+
mapName: z3.string(),
|
|
2252
|
+
path: z3.string(),
|
|
2253
|
+
entries: z3.array(z3.object({
|
|
2254
|
+
key: z3.string(),
|
|
2255
|
+
records: z3.array(ORMapRecordSchema),
|
|
2256
|
+
tombstones: z3.array(z3.string())
|
|
1295
2257
|
// Tombstone tags for this key's records
|
|
1296
2258
|
}))
|
|
1297
2259
|
})
|
|
1298
2260
|
});
|
|
1299
|
-
var ORMapDiffRequestSchema =
|
|
1300
|
-
type:
|
|
1301
|
-
payload:
|
|
1302
|
-
mapName:
|
|
1303
|
-
keys:
|
|
2261
|
+
var ORMapDiffRequestSchema = z3.object({
|
|
2262
|
+
type: z3.literal("ORMAP_DIFF_REQUEST"),
|
|
2263
|
+
payload: z3.object({
|
|
2264
|
+
mapName: z3.string(),
|
|
2265
|
+
keys: z3.array(z3.string())
|
|
1304
2266
|
})
|
|
1305
2267
|
});
|
|
1306
|
-
var ORMapDiffResponseSchema =
|
|
1307
|
-
type:
|
|
1308
|
-
payload:
|
|
1309
|
-
mapName:
|
|
1310
|
-
entries:
|
|
1311
|
-
key:
|
|
1312
|
-
records:
|
|
1313
|
-
tombstones:
|
|
2268
|
+
var ORMapDiffResponseSchema = z3.object({
|
|
2269
|
+
type: z3.literal("ORMAP_DIFF_RESPONSE"),
|
|
2270
|
+
payload: z3.object({
|
|
2271
|
+
mapName: z3.string(),
|
|
2272
|
+
entries: z3.array(z3.object({
|
|
2273
|
+
key: z3.string(),
|
|
2274
|
+
records: z3.array(ORMapRecordSchema),
|
|
2275
|
+
tombstones: z3.array(z3.string())
|
|
1314
2276
|
}))
|
|
1315
2277
|
})
|
|
1316
2278
|
});
|
|
1317
|
-
var ORMapPushDiffSchema =
|
|
1318
|
-
type:
|
|
1319
|
-
payload:
|
|
1320
|
-
mapName:
|
|
1321
|
-
entries:
|
|
1322
|
-
key:
|
|
1323
|
-
records:
|
|
1324
|
-
tombstones:
|
|
2279
|
+
var ORMapPushDiffSchema = z3.object({
|
|
2280
|
+
type: z3.literal("ORMAP_PUSH_DIFF"),
|
|
2281
|
+
payload: z3.object({
|
|
2282
|
+
mapName: z3.string(),
|
|
2283
|
+
entries: z3.array(z3.object({
|
|
2284
|
+
key: z3.string(),
|
|
2285
|
+
records: z3.array(ORMapRecordSchema),
|
|
2286
|
+
tombstones: z3.array(z3.string())
|
|
1325
2287
|
}))
|
|
1326
2288
|
})
|
|
1327
2289
|
});
|
|
1328
|
-
var
|
|
1329
|
-
|
|
1330
|
-
|
|
2290
|
+
var PartitionMapRequestSchema = z3.object({
|
|
2291
|
+
type: z3.literal("PARTITION_MAP_REQUEST"),
|
|
2292
|
+
payload: z3.object({
|
|
2293
|
+
currentVersion: z3.number().optional()
|
|
2294
|
+
}).optional()
|
|
2295
|
+
});
|
|
2296
|
+
var EntryProcessorSchema = z3.object({
|
|
2297
|
+
name: z3.string().min(1).max(100),
|
|
2298
|
+
code: z3.string().min(1).max(1e4),
|
|
2299
|
+
args: z3.unknown().optional()
|
|
2300
|
+
});
|
|
2301
|
+
var EntryProcessRequestSchema = z3.object({
|
|
2302
|
+
type: z3.literal("ENTRY_PROCESS"),
|
|
2303
|
+
requestId: z3.string(),
|
|
2304
|
+
mapName: z3.string(),
|
|
2305
|
+
key: z3.string(),
|
|
2306
|
+
processor: EntryProcessorSchema
|
|
2307
|
+
});
|
|
2308
|
+
var EntryProcessBatchRequestSchema = z3.object({
|
|
2309
|
+
type: z3.literal("ENTRY_PROCESS_BATCH"),
|
|
2310
|
+
requestId: z3.string(),
|
|
2311
|
+
mapName: z3.string(),
|
|
2312
|
+
keys: z3.array(z3.string()),
|
|
2313
|
+
processor: EntryProcessorSchema
|
|
2314
|
+
});
|
|
2315
|
+
var EntryProcessResponseSchema = z3.object({
|
|
2316
|
+
type: z3.literal("ENTRY_PROCESS_RESPONSE"),
|
|
2317
|
+
requestId: z3.string(),
|
|
2318
|
+
success: z3.boolean(),
|
|
2319
|
+
result: z3.unknown().optional(),
|
|
2320
|
+
newValue: z3.unknown().optional(),
|
|
2321
|
+
error: z3.string().optional()
|
|
2322
|
+
});
|
|
2323
|
+
var EntryProcessKeyResultSchema = z3.object({
|
|
2324
|
+
success: z3.boolean(),
|
|
2325
|
+
result: z3.unknown().optional(),
|
|
2326
|
+
newValue: z3.unknown().optional(),
|
|
2327
|
+
error: z3.string().optional()
|
|
2328
|
+
});
|
|
2329
|
+
var EntryProcessBatchResponseSchema = z3.object({
|
|
2330
|
+
type: z3.literal("ENTRY_PROCESS_BATCH_RESPONSE"),
|
|
2331
|
+
requestId: z3.string(),
|
|
2332
|
+
results: z3.record(z3.string(), EntryProcessKeyResultSchema)
|
|
2333
|
+
});
|
|
2334
|
+
var JournalEventTypeSchema = z3.enum(["PUT", "UPDATE", "DELETE"]);
|
|
2335
|
+
var JournalEventDataSchema = z3.object({
|
|
2336
|
+
sequence: z3.string(),
|
|
2337
|
+
// bigint as string
|
|
2338
|
+
type: JournalEventTypeSchema,
|
|
2339
|
+
mapName: z3.string(),
|
|
2340
|
+
key: z3.string(),
|
|
2341
|
+
value: z3.unknown().optional(),
|
|
2342
|
+
previousValue: z3.unknown().optional(),
|
|
2343
|
+
timestamp: TimestampSchema,
|
|
2344
|
+
nodeId: z3.string(),
|
|
2345
|
+
metadata: z3.record(z3.string(), z3.unknown()).optional()
|
|
2346
|
+
});
|
|
2347
|
+
var JournalSubscribeRequestSchema = z3.object({
|
|
2348
|
+
type: z3.literal("JOURNAL_SUBSCRIBE"),
|
|
2349
|
+
requestId: z3.string(),
|
|
2350
|
+
fromSequence: z3.string().optional(),
|
|
2351
|
+
// bigint as string
|
|
2352
|
+
mapName: z3.string().optional(),
|
|
2353
|
+
types: z3.array(JournalEventTypeSchema).optional()
|
|
2354
|
+
});
|
|
2355
|
+
var JournalUnsubscribeRequestSchema = z3.object({
|
|
2356
|
+
type: z3.literal("JOURNAL_UNSUBSCRIBE"),
|
|
2357
|
+
subscriptionId: z3.string()
|
|
2358
|
+
});
|
|
2359
|
+
var JournalEventMessageSchema = z3.object({
|
|
2360
|
+
type: z3.literal("JOURNAL_EVENT"),
|
|
2361
|
+
event: JournalEventDataSchema
|
|
2362
|
+
});
|
|
2363
|
+
var JournalReadRequestSchema = z3.object({
|
|
2364
|
+
type: z3.literal("JOURNAL_READ"),
|
|
2365
|
+
requestId: z3.string(),
|
|
2366
|
+
fromSequence: z3.string(),
|
|
2367
|
+
limit: z3.number().optional(),
|
|
2368
|
+
mapName: z3.string().optional()
|
|
2369
|
+
});
|
|
2370
|
+
var JournalReadResponseSchema = z3.object({
|
|
2371
|
+
type: z3.literal("JOURNAL_READ_RESPONSE"),
|
|
2372
|
+
requestId: z3.string(),
|
|
2373
|
+
events: z3.array(JournalEventDataSchema),
|
|
2374
|
+
hasMore: z3.boolean()
|
|
2375
|
+
});
|
|
2376
|
+
var ConflictResolverSchema = z3.object({
|
|
2377
|
+
name: z3.string().min(1).max(100),
|
|
2378
|
+
code: z3.string().max(5e4),
|
|
2379
|
+
priority: z3.number().int().min(0).max(100).optional(),
|
|
2380
|
+
keyPattern: z3.string().optional()
|
|
2381
|
+
});
|
|
2382
|
+
var RegisterResolverRequestSchema = z3.object({
|
|
2383
|
+
type: z3.literal("REGISTER_RESOLVER"),
|
|
2384
|
+
requestId: z3.string(),
|
|
2385
|
+
mapName: z3.string(),
|
|
2386
|
+
resolver: ConflictResolverSchema
|
|
2387
|
+
});
|
|
2388
|
+
var RegisterResolverResponseSchema = z3.object({
|
|
2389
|
+
type: z3.literal("REGISTER_RESOLVER_RESPONSE"),
|
|
2390
|
+
requestId: z3.string(),
|
|
2391
|
+
success: z3.boolean(),
|
|
2392
|
+
error: z3.string().optional()
|
|
2393
|
+
});
|
|
2394
|
+
var UnregisterResolverRequestSchema = z3.object({
|
|
2395
|
+
type: z3.literal("UNREGISTER_RESOLVER"),
|
|
2396
|
+
requestId: z3.string(),
|
|
2397
|
+
mapName: z3.string(),
|
|
2398
|
+
resolverName: z3.string()
|
|
2399
|
+
});
|
|
2400
|
+
var UnregisterResolverResponseSchema = z3.object({
|
|
2401
|
+
type: z3.literal("UNREGISTER_RESOLVER_RESPONSE"),
|
|
2402
|
+
requestId: z3.string(),
|
|
2403
|
+
success: z3.boolean(),
|
|
2404
|
+
error: z3.string().optional()
|
|
2405
|
+
});
|
|
2406
|
+
var MergeRejectedMessageSchema = z3.object({
|
|
2407
|
+
type: z3.literal("MERGE_REJECTED"),
|
|
2408
|
+
mapName: z3.string(),
|
|
2409
|
+
key: z3.string(),
|
|
2410
|
+
attemptedValue: z3.unknown(),
|
|
2411
|
+
reason: z3.string(),
|
|
2412
|
+
timestamp: TimestampSchema
|
|
2413
|
+
});
|
|
2414
|
+
var ListResolversRequestSchema = z3.object({
|
|
2415
|
+
type: z3.literal("LIST_RESOLVERS"),
|
|
2416
|
+
requestId: z3.string(),
|
|
2417
|
+
mapName: z3.string().optional()
|
|
2418
|
+
});
|
|
2419
|
+
var ListResolversResponseSchema = z3.object({
|
|
2420
|
+
type: z3.literal("LIST_RESOLVERS_RESPONSE"),
|
|
2421
|
+
requestId: z3.string(),
|
|
2422
|
+
resolvers: z3.array(z3.object({
|
|
2423
|
+
mapName: z3.string(),
|
|
2424
|
+
name: z3.string(),
|
|
2425
|
+
priority: z3.number().optional(),
|
|
2426
|
+
keyPattern: z3.string().optional()
|
|
2427
|
+
}))
|
|
2428
|
+
});
|
|
2429
|
+
var OpResultSchema = z3.object({
|
|
2430
|
+
opId: z3.string(),
|
|
2431
|
+
success: z3.boolean(),
|
|
1331
2432
|
achievedLevel: WriteConcernSchema,
|
|
1332
|
-
error:
|
|
2433
|
+
error: z3.string().optional()
|
|
1333
2434
|
});
|
|
1334
|
-
var OpAckMessageSchema =
|
|
1335
|
-
type:
|
|
1336
|
-
payload:
|
|
2435
|
+
var OpAckMessageSchema = z3.object({
|
|
2436
|
+
type: z3.literal("OP_ACK"),
|
|
2437
|
+
payload: z3.object({
|
|
1337
2438
|
/** ID of the last operation in the batch (for backwards compatibility) */
|
|
1338
|
-
lastId:
|
|
2439
|
+
lastId: z3.string(),
|
|
1339
2440
|
/** Write Concern level achieved (for simple ACKs) */
|
|
1340
2441
|
achievedLevel: WriteConcernSchema.optional(),
|
|
1341
2442
|
/** Per-operation results (for batch operations with mixed Write Concern) */
|
|
1342
|
-
results:
|
|
2443
|
+
results: z3.array(OpResultSchema).optional()
|
|
1343
2444
|
})
|
|
1344
2445
|
});
|
|
1345
|
-
var OpRejectedMessageSchema =
|
|
1346
|
-
type:
|
|
1347
|
-
payload:
|
|
2446
|
+
var OpRejectedMessageSchema = z3.object({
|
|
2447
|
+
type: z3.literal("OP_REJECTED"),
|
|
2448
|
+
payload: z3.object({
|
|
1348
2449
|
/** Operation ID that was rejected */
|
|
1349
|
-
opId:
|
|
2450
|
+
opId: z3.string(),
|
|
1350
2451
|
/** Reason for rejection */
|
|
1351
|
-
reason:
|
|
2452
|
+
reason: z3.string(),
|
|
1352
2453
|
/** Error code */
|
|
1353
|
-
code:
|
|
2454
|
+
code: z3.number().optional()
|
|
1354
2455
|
})
|
|
1355
2456
|
});
|
|
1356
|
-
var MessageSchema =
|
|
2457
|
+
var MessageSchema = z3.discriminatedUnion("type", [
|
|
1357
2458
|
AuthMessageSchema,
|
|
1358
2459
|
QuerySubMessageSchema,
|
|
1359
2460
|
QueryUnsubMessageSchema,
|
|
@@ -1379,7 +2480,31 @@ var MessageSchema = z.discriminatedUnion("type", [
|
|
|
1379
2480
|
ORMapSyncRespLeafSchema,
|
|
1380
2481
|
ORMapDiffRequestSchema,
|
|
1381
2482
|
ORMapDiffResponseSchema,
|
|
1382
|
-
ORMapPushDiffSchema
|
|
2483
|
+
ORMapPushDiffSchema,
|
|
2484
|
+
// Phase 4: Partition Map
|
|
2485
|
+
PartitionMapRequestSchema,
|
|
2486
|
+
// Phase 5.2: PN Counter
|
|
2487
|
+
CounterRequestSchema,
|
|
2488
|
+
CounterSyncSchema,
|
|
2489
|
+
// Phase 5.03: Entry Processor
|
|
2490
|
+
EntryProcessRequestSchema,
|
|
2491
|
+
EntryProcessBatchRequestSchema,
|
|
2492
|
+
EntryProcessResponseSchema,
|
|
2493
|
+
EntryProcessBatchResponseSchema,
|
|
2494
|
+
// Phase 5.04: Event Journal
|
|
2495
|
+
JournalSubscribeRequestSchema,
|
|
2496
|
+
JournalUnsubscribeRequestSchema,
|
|
2497
|
+
JournalEventMessageSchema,
|
|
2498
|
+
JournalReadRequestSchema,
|
|
2499
|
+
JournalReadResponseSchema,
|
|
2500
|
+
// Phase 5.05: Conflict Resolver
|
|
2501
|
+
RegisterResolverRequestSchema,
|
|
2502
|
+
RegisterResolverResponseSchema,
|
|
2503
|
+
UnregisterResolverRequestSchema,
|
|
2504
|
+
UnregisterResolverResponseSchema,
|
|
2505
|
+
MergeRejectedMessageSchema,
|
|
2506
|
+
ListResolversRequestSchema,
|
|
2507
|
+
ListResolversResponseSchema
|
|
1383
2508
|
]);
|
|
1384
2509
|
|
|
1385
2510
|
// src/types/WriteConcern.ts
|
|
@@ -1414,17 +2539,105 @@ function getHighestWriteConcernLevel(achieved) {
|
|
|
1414
2539
|
}
|
|
1415
2540
|
return "FIRE_AND_FORGET" /* FIRE_AND_FORGET */;
|
|
1416
2541
|
}
|
|
2542
|
+
|
|
2543
|
+
// src/types/cluster.ts
|
|
2544
|
+
var DEFAULT_CONNECTION_POOL_CONFIG = {
|
|
2545
|
+
maxConnectionsPerNode: 1,
|
|
2546
|
+
connectionTimeoutMs: 5e3,
|
|
2547
|
+
healthCheckIntervalMs: 1e4,
|
|
2548
|
+
reconnectDelayMs: 1e3,
|
|
2549
|
+
maxReconnectDelayMs: 3e4,
|
|
2550
|
+
maxReconnectAttempts: 5
|
|
2551
|
+
};
|
|
2552
|
+
var DEFAULT_PARTITION_ROUTER_CONFIG = {
|
|
2553
|
+
fallbackMode: "forward",
|
|
2554
|
+
mapRefreshIntervalMs: 3e4,
|
|
2555
|
+
maxMapStalenessMs: 6e4
|
|
2556
|
+
};
|
|
2557
|
+
var DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
2558
|
+
failureThreshold: 5,
|
|
2559
|
+
resetTimeoutMs: 3e4
|
|
2560
|
+
};
|
|
2561
|
+
var PartitionState = /* @__PURE__ */ ((PartitionState2) => {
|
|
2562
|
+
PartitionState2["STABLE"] = "STABLE";
|
|
2563
|
+
PartitionState2["MIGRATING"] = "MIGRATING";
|
|
2564
|
+
PartitionState2["SYNC"] = "SYNC";
|
|
2565
|
+
PartitionState2["FAILED"] = "FAILED";
|
|
2566
|
+
return PartitionState2;
|
|
2567
|
+
})(PartitionState || {});
|
|
2568
|
+
var DEFAULT_MIGRATION_CONFIG = {
|
|
2569
|
+
batchSize: 10,
|
|
2570
|
+
batchIntervalMs: 5e3,
|
|
2571
|
+
transferChunkSize: 65536,
|
|
2572
|
+
// 64KB
|
|
2573
|
+
maxRetries: 3,
|
|
2574
|
+
syncTimeoutMs: 3e4,
|
|
2575
|
+
parallelTransfers: 4
|
|
2576
|
+
};
|
|
2577
|
+
var ConsistencyLevel = /* @__PURE__ */ ((ConsistencyLevel2) => {
|
|
2578
|
+
ConsistencyLevel2["STRONG"] = "STRONG";
|
|
2579
|
+
ConsistencyLevel2["QUORUM"] = "QUORUM";
|
|
2580
|
+
ConsistencyLevel2["EVENTUAL"] = "EVENTUAL";
|
|
2581
|
+
return ConsistencyLevel2;
|
|
2582
|
+
})(ConsistencyLevel || {});
|
|
2583
|
+
var DEFAULT_REPLICATION_CONFIG = {
|
|
2584
|
+
defaultConsistency: "EVENTUAL" /* EVENTUAL */,
|
|
2585
|
+
queueSizeLimit: 1e4,
|
|
2586
|
+
batchSize: 100,
|
|
2587
|
+
batchIntervalMs: 50,
|
|
2588
|
+
ackTimeoutMs: 5e3,
|
|
2589
|
+
maxRetries: 3
|
|
2590
|
+
};
|
|
2591
|
+
var PARTITION_COUNT = 271;
|
|
2592
|
+
var DEFAULT_BACKUP_COUNT = 1;
|
|
1417
2593
|
export {
|
|
1418
2594
|
AuthMessageSchema,
|
|
1419
2595
|
BatchMessageSchema,
|
|
2596
|
+
BuiltInProcessors,
|
|
2597
|
+
BuiltInResolvers,
|
|
1420
2598
|
ClientOpMessageSchema,
|
|
1421
2599
|
ClientOpSchema,
|
|
2600
|
+
ConflictResolverDefSchema,
|
|
2601
|
+
ConflictResolverSchema,
|
|
2602
|
+
ConsistencyLevel,
|
|
2603
|
+
CounterRequestSchema,
|
|
2604
|
+
CounterResponseSchema,
|
|
2605
|
+
CounterSyncSchema,
|
|
2606
|
+
CounterUpdateSchema,
|
|
2607
|
+
DEFAULT_BACKUP_COUNT,
|
|
2608
|
+
DEFAULT_CIRCUIT_BREAKER_CONFIG,
|
|
2609
|
+
DEFAULT_CONNECTION_POOL_CONFIG,
|
|
2610
|
+
DEFAULT_EVENT_JOURNAL_CONFIG,
|
|
2611
|
+
DEFAULT_MIGRATION_CONFIG,
|
|
2612
|
+
DEFAULT_PARTITION_ROUTER_CONFIG,
|
|
2613
|
+
DEFAULT_PROCESSOR_RATE_LIMITS,
|
|
2614
|
+
DEFAULT_REPLICATION_CONFIG,
|
|
2615
|
+
DEFAULT_RESOLVER_RATE_LIMITS,
|
|
1422
2616
|
DEFAULT_WRITE_CONCERN_TIMEOUT,
|
|
2617
|
+
EntryProcessBatchRequestSchema,
|
|
2618
|
+
EntryProcessBatchResponseSchema,
|
|
2619
|
+
EntryProcessKeyResultSchema,
|
|
2620
|
+
EntryProcessRequestSchema,
|
|
2621
|
+
EntryProcessResponseSchema,
|
|
2622
|
+
EntryProcessorDefSchema,
|
|
2623
|
+
EntryProcessorSchema,
|
|
2624
|
+
EventJournalImpl,
|
|
2625
|
+
FORBIDDEN_PATTERNS,
|
|
1423
2626
|
HLC,
|
|
2627
|
+
JournalEventDataSchema,
|
|
2628
|
+
JournalEventMessageSchema,
|
|
2629
|
+
JournalEventTypeSchema,
|
|
2630
|
+
JournalReadRequestSchema,
|
|
2631
|
+
JournalReadResponseSchema,
|
|
2632
|
+
JournalSubscribeRequestSchema,
|
|
2633
|
+
JournalUnsubscribeRequestSchema,
|
|
1424
2634
|
LWWMap,
|
|
1425
2635
|
LWWRecordSchema,
|
|
2636
|
+
ListResolversRequestSchema,
|
|
2637
|
+
ListResolversResponseSchema,
|
|
1426
2638
|
LockReleaseSchema,
|
|
1427
2639
|
LockRequestSchema,
|
|
2640
|
+
MergeRejectedMessageSchema,
|
|
1428
2641
|
MerkleReqBucketMessageSchema,
|
|
1429
2642
|
MerkleTree,
|
|
1430
2643
|
MessageSchema,
|
|
@@ -1443,6 +2656,11 @@ export {
|
|
|
1443
2656
|
OpBatchMessageSchema,
|
|
1444
2657
|
OpRejectedMessageSchema,
|
|
1445
2658
|
OpResultSchema,
|
|
2659
|
+
PARTITION_COUNT,
|
|
2660
|
+
PNCounterImpl,
|
|
2661
|
+
PNCounterStateObjectSchema,
|
|
2662
|
+
PartitionMapRequestSchema,
|
|
2663
|
+
PartitionState,
|
|
1446
2664
|
PingMessageSchema,
|
|
1447
2665
|
PongMessageSchema,
|
|
1448
2666
|
PredicateNodeSchema,
|
|
@@ -1451,6 +2669,10 @@ export {
|
|
|
1451
2669
|
QuerySchema,
|
|
1452
2670
|
QuerySubMessageSchema,
|
|
1453
2671
|
QueryUnsubMessageSchema,
|
|
2672
|
+
RESOLVER_FORBIDDEN_PATTERNS,
|
|
2673
|
+
RegisterResolverRequestSchema,
|
|
2674
|
+
RegisterResolverResponseSchema,
|
|
2675
|
+
Ringbuffer,
|
|
1454
2676
|
SyncInitMessageSchema,
|
|
1455
2677
|
SyncRespBucketsMessageSchema,
|
|
1456
2678
|
SyncRespLeafMessageSchema,
|
|
@@ -1460,11 +2682,15 @@ export {
|
|
|
1460
2682
|
TopicPubSchema,
|
|
1461
2683
|
TopicSubSchema,
|
|
1462
2684
|
TopicUnsubSchema,
|
|
2685
|
+
UnregisterResolverRequestSchema,
|
|
2686
|
+
UnregisterResolverResponseSchema,
|
|
1463
2687
|
WRITE_CONCERN_ORDER,
|
|
1464
2688
|
WriteConcern,
|
|
1465
2689
|
WriteConcernSchema,
|
|
1466
2690
|
combineHashes,
|
|
2691
|
+
compareHLCTimestamps,
|
|
1467
2692
|
compareTimestamps,
|
|
2693
|
+
deepMerge,
|
|
1468
2694
|
deserialize,
|
|
1469
2695
|
disableNativeHash,
|
|
1470
2696
|
evaluatePredicate,
|
|
@@ -1476,6 +2702,8 @@ export {
|
|
|
1476
2702
|
isWriteConcernAchieved,
|
|
1477
2703
|
resetNativeHash,
|
|
1478
2704
|
serialize,
|
|
1479
|
-
timestampToString
|
|
2705
|
+
timestampToString,
|
|
2706
|
+
validateProcessorCode,
|
|
2707
|
+
validateResolverCode
|
|
1480
2708
|
};
|
|
1481
2709
|
//# sourceMappingURL=index.mjs.map
|