@aouda/client 0.1.14 → 0.1.15
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/cli/index.cjs +346 -73
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +346 -73
- package/dist/cli/index.js.map +1 -1
- package/dist/{client-BCMP-Fge.d.cts → client-CXfjcF61.d.cts} +99 -21
- package/dist/{client-BCMP-Fge.d.ts → client-CXfjcF61.d.ts} +99 -21
- package/dist/index.cjs +351 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.js +348 -72
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@aouda/client",
|
|
4
|
-
version: "0.1.
|
|
4
|
+
version: "0.1.15",
|
|
5
5
|
description: "Official TypeScript/JavaScript client library for Aouda",
|
|
6
6
|
type: "module",
|
|
7
7
|
main: "./dist/index.cjs",
|
|
@@ -133,43 +133,44 @@ var AoudaResponseError = class extends AoudaError {
|
|
|
133
133
|
}
|
|
134
134
|
};
|
|
135
135
|
var AoudaApiError = class extends AoudaError {
|
|
136
|
-
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
136
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
137
137
|
super(message);
|
|
138
138
|
this.code = code;
|
|
139
139
|
this.statusCode = statusCode;
|
|
140
140
|
this.details = details;
|
|
141
141
|
this.requestId = requestId;
|
|
142
142
|
this.retryAfterSeconds = retryAfterSeconds;
|
|
143
|
+
this.token = token;
|
|
143
144
|
this.name = "AoudaApiError";
|
|
144
145
|
}
|
|
145
146
|
};
|
|
146
147
|
var AoudaNotFoundError = class extends AoudaApiError {
|
|
147
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
148
|
-
super(message, code, statusCode, details, requestId);
|
|
148
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
149
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
149
150
|
this.name = "AoudaNotFoundError";
|
|
150
151
|
}
|
|
151
152
|
};
|
|
152
153
|
var AoudaConflictError = class extends AoudaApiError {
|
|
153
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
154
|
-
super(message, code, statusCode, details, requestId);
|
|
154
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
155
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
155
156
|
this.name = "AoudaConflictError";
|
|
156
157
|
}
|
|
157
158
|
};
|
|
158
159
|
var AoudaValidationError = class extends AoudaApiError {
|
|
159
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
160
|
-
super(message, code, statusCode, details, requestId);
|
|
160
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
161
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
161
162
|
this.name = "AoudaValidationError";
|
|
162
163
|
}
|
|
163
164
|
};
|
|
164
165
|
var AoudaServerError = class extends AoudaApiError {
|
|
165
|
-
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
166
|
-
super(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
166
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
167
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
167
168
|
this.name = "AoudaServerError";
|
|
168
169
|
}
|
|
169
170
|
};
|
|
170
171
|
var AoudaAuthenticationError = class extends AoudaApiError {
|
|
171
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
172
|
-
super(message, code, statusCode, details, requestId);
|
|
172
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
173
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
173
174
|
this.name = "AoudaAuthenticationError";
|
|
174
175
|
}
|
|
175
176
|
};
|
|
@@ -981,7 +982,7 @@ function buildHandle(jobId, commitResp, wasResumed, transport, database, signal)
|
|
|
981
982
|
rowsDurablyCommitted: commitResp.rowsLoaded,
|
|
982
983
|
segmentsCreated: commitResp.segmentsCreated,
|
|
983
984
|
committedAtUtc: commitResp.committedAtUtc,
|
|
984
|
-
|
|
985
|
+
token: commitResp.token,
|
|
985
986
|
writeConcernSatisfied: commitResp.writeConcernAchieved ?? "acknowledged",
|
|
986
987
|
writeConcernTimedOut: commitResp.writeConcernTimedOut,
|
|
987
988
|
wasResumed,
|
|
@@ -1107,6 +1108,7 @@ var PROTOCOL_VERSION_HEADER = "X-Aouda-Protocol-Version";
|
|
|
1107
1108
|
var PROTOCOL_VERSION = "1";
|
|
1108
1109
|
var CONTENT_TYPE_JSON2 = "application/json";
|
|
1109
1110
|
var REQUEST_ID_HEADER2 = "X-Request-Id";
|
|
1111
|
+
var TOKEN_HEADER = "X-Aouda-Token";
|
|
1110
1112
|
var ERROR_CODE_MAP = {
|
|
1111
1113
|
TABLE_NOT_FOUND: AoudaNotFoundError,
|
|
1112
1114
|
COLUMN_NOT_FOUND: AoudaNotFoundError,
|
|
@@ -1146,7 +1148,12 @@ var ERROR_CODE_MAP = {
|
|
|
1146
1148
|
AUTH_IDENTITY_INVALID: AoudaValidationError,
|
|
1147
1149
|
AUTH_IDENTITY_NOT_FOUND: AoudaValidationError,
|
|
1148
1150
|
BULK_LOAD_TRANSFORM_INTENT_REQUIRED: AoudaValidationError,
|
|
1149
|
-
BULK_LOAD_TRANSFORM_INTENT_CONFLICT: AoudaValidationError
|
|
1151
|
+
BULK_LOAD_TRANSFORM_INTENT_CONFLICT: AoudaValidationError,
|
|
1152
|
+
TOKEN_MALFORMED: AoudaValidationError,
|
|
1153
|
+
TOKEN_FOREIGN_DATABASE: AoudaValidationError,
|
|
1154
|
+
TOKEN_EPOCH_SUPERSEDED: AoudaConflictError,
|
|
1155
|
+
TOKEN_UNSATISFIED: AoudaConflictError,
|
|
1156
|
+
TOKEN_FETCH_PRIMARY: AoudaApiError
|
|
1150
1157
|
};
|
|
1151
1158
|
function createComposedAbortController(...signals) {
|
|
1152
1159
|
const controller = new AbortController();
|
|
@@ -1183,7 +1190,7 @@ function createApiError(statusCode, statusText, body, retryAfterHeader) {
|
|
|
1183
1190
|
const requestId = body.requestId;
|
|
1184
1191
|
const retryAfterSeconds = parseRetryAfterSeconds(retryAfterHeader ?? null);
|
|
1185
1192
|
const Ctor = ERROR_CODE_MAP[code] ?? AoudaApiError;
|
|
1186
|
-
return new Ctor(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
1193
|
+
return new Ctor(message, code, statusCode, details, requestId, retryAfterSeconds, body.token);
|
|
1187
1194
|
}
|
|
1188
1195
|
var HttpTransport = class {
|
|
1189
1196
|
constructor(options) {
|
|
@@ -1195,6 +1202,29 @@ var HttpTransport = class {
|
|
|
1195
1202
|
...options.defaultHeaders
|
|
1196
1203
|
};
|
|
1197
1204
|
this.abortController = new AbortController();
|
|
1205
|
+
this.database = options.database;
|
|
1206
|
+
this.store = options.consistencyTokenStore;
|
|
1207
|
+
}
|
|
1208
|
+
presentTokenHeaders(path, headers) {
|
|
1209
|
+
if (this.store == null || this.database == null || isAuthPath(path)) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
const token = this.store.get(this.database);
|
|
1213
|
+
if (token != null && token.length > 0) {
|
|
1214
|
+
headers[TOKEN_HEADER] = token;
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
observeResponse(_path, response, bodyText, errorCode) {
|
|
1218
|
+
if (this.store == null || this.database == null) {
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
if (errorCode === "TOKEN_MALFORMED" || errorCode === "TOKEN_FOREIGN_DATABASE") {
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
const header = response.headers.get(TOKEN_HEADER);
|
|
1225
|
+
const bodyToken = readBodyToken(bodyText);
|
|
1226
|
+
const token = header != null && header.trim().length > 0 ? header : bodyToken;
|
|
1227
|
+
this.store.observe(this.database, token);
|
|
1198
1228
|
}
|
|
1199
1229
|
/**
|
|
1200
1230
|
* Abort all in-flight and future requests (e.g. on client disconnect).
|
|
@@ -1232,6 +1262,7 @@ var HttpTransport = class {
|
|
|
1232
1262
|
...this.defaultHeaders,
|
|
1233
1263
|
...config.headers
|
|
1234
1264
|
};
|
|
1265
|
+
this.presentTokenHeaders(config.path, headers);
|
|
1235
1266
|
if (config.body !== void 0 && config.body !== null) {
|
|
1236
1267
|
headers["Content-Type"] = CONTENT_TYPE_JSON2;
|
|
1237
1268
|
}
|
|
@@ -1251,6 +1282,7 @@ var HttpTransport = class {
|
|
|
1251
1282
|
const text = await response.text();
|
|
1252
1283
|
if (config.allowStatuses?.includes(response.status) && text) {
|
|
1253
1284
|
try {
|
|
1285
|
+
this.observeResponse(config.path, response, text);
|
|
1254
1286
|
return JSON.parse(text);
|
|
1255
1287
|
} catch {
|
|
1256
1288
|
}
|
|
@@ -1264,15 +1296,19 @@ var HttpTransport = class {
|
|
|
1264
1296
|
}
|
|
1265
1297
|
if (response.status === 401) {
|
|
1266
1298
|
const code = errorBody?.code ?? "AUTH_TOKEN_MISSING";
|
|
1299
|
+
this.observeResponse(config.path, response, text, code);
|
|
1267
1300
|
throw new AoudaAuthenticationError(
|
|
1268
1301
|
errorBody?.error ?? "Unauthorized",
|
|
1269
1302
|
code,
|
|
1270
1303
|
401,
|
|
1271
1304
|
errorBody?.details,
|
|
1272
|
-
errorBody?.requestId
|
|
1305
|
+
errorBody?.requestId,
|
|
1306
|
+
void 0,
|
|
1307
|
+
errorBody?.token
|
|
1273
1308
|
);
|
|
1274
1309
|
}
|
|
1275
1310
|
if (errorBody?.code != null) {
|
|
1311
|
+
this.observeResponse(config.path, response, text, errorBody.code);
|
|
1276
1312
|
throw createApiError(
|
|
1277
1313
|
response.status,
|
|
1278
1314
|
response.statusText,
|
|
@@ -1280,6 +1316,7 @@ var HttpTransport = class {
|
|
|
1280
1316
|
response.headers.get("Retry-After")
|
|
1281
1317
|
);
|
|
1282
1318
|
}
|
|
1319
|
+
this.observeResponse(config.path, response, text);
|
|
1283
1320
|
throw new AoudaResponseError(
|
|
1284
1321
|
errorBody?.error ?? `${response.status} ${response.statusText}`,
|
|
1285
1322
|
response.status,
|
|
@@ -1287,6 +1324,7 @@ var HttpTransport = class {
|
|
|
1287
1324
|
);
|
|
1288
1325
|
}
|
|
1289
1326
|
const responseText = await response.text();
|
|
1327
|
+
this.observeResponse(config.path, response, responseText);
|
|
1290
1328
|
if (config.rawText) {
|
|
1291
1329
|
return responseText;
|
|
1292
1330
|
}
|
|
@@ -1347,6 +1385,7 @@ var HttpTransport = class {
|
|
|
1347
1385
|
...this.defaultHeaders,
|
|
1348
1386
|
...config.headers
|
|
1349
1387
|
};
|
|
1388
|
+
this.presentTokenHeaders(config.path, headers);
|
|
1350
1389
|
if (config.rawBodyStr === void 0 && config.body !== void 0 && config.body !== null) {
|
|
1351
1390
|
headers["Content-Type"] = CONTENT_TYPE_JSON2;
|
|
1352
1391
|
}
|
|
@@ -1363,6 +1402,7 @@ var HttpTransport = class {
|
|
|
1363
1402
|
try {
|
|
1364
1403
|
const response = await localNetworkFetch(url, init);
|
|
1365
1404
|
if (response.ok || config.allowStatuses?.includes(response.status)) {
|
|
1405
|
+
this.observeResponse(config.path, response, void 0);
|
|
1366
1406
|
return response;
|
|
1367
1407
|
}
|
|
1368
1408
|
const text = await response.text();
|
|
@@ -1375,15 +1415,19 @@ var HttpTransport = class {
|
|
|
1375
1415
|
}
|
|
1376
1416
|
if (response.status === 401) {
|
|
1377
1417
|
const code = errorBody?.code ?? "AUTH_TOKEN_MISSING";
|
|
1418
|
+
this.observeResponse(config.path, response, text, code);
|
|
1378
1419
|
throw new AoudaAuthenticationError(
|
|
1379
1420
|
errorBody?.error ?? "Unauthorized",
|
|
1380
1421
|
code,
|
|
1381
1422
|
401,
|
|
1382
1423
|
errorBody?.details,
|
|
1383
|
-
errorBody?.requestId
|
|
1424
|
+
errorBody?.requestId,
|
|
1425
|
+
void 0,
|
|
1426
|
+
errorBody?.token
|
|
1384
1427
|
);
|
|
1385
1428
|
}
|
|
1386
1429
|
if (errorBody?.code != null) {
|
|
1430
|
+
this.observeResponse(config.path, response, text, errorBody.code);
|
|
1387
1431
|
throw createApiError(
|
|
1388
1432
|
response.status,
|
|
1389
1433
|
response.statusText,
|
|
@@ -1391,6 +1435,7 @@ var HttpTransport = class {
|
|
|
1391
1435
|
response.headers.get("Retry-After")
|
|
1392
1436
|
);
|
|
1393
1437
|
}
|
|
1438
|
+
this.observeResponse(config.path, response, text);
|
|
1394
1439
|
throw new AoudaResponseError(
|
|
1395
1440
|
errorBody?.error ?? `${response.status} ${response.statusText}`,
|
|
1396
1441
|
response.status,
|
|
@@ -1545,6 +1590,47 @@ var HttpTransport = class {
|
|
|
1545
1590
|
});
|
|
1546
1591
|
}
|
|
1547
1592
|
};
|
|
1593
|
+
function isAuthPath(path) {
|
|
1594
|
+
let p = path;
|
|
1595
|
+
const q = p.indexOf("?");
|
|
1596
|
+
if (q >= 0) {
|
|
1597
|
+
p = p.slice(0, q);
|
|
1598
|
+
}
|
|
1599
|
+
if (/^https?:\/\//i.test(p)) {
|
|
1600
|
+
try {
|
|
1601
|
+
p = new URL(p).pathname;
|
|
1602
|
+
} catch {
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
const lower = p.toLowerCase();
|
|
1606
|
+
if (lower === "/api/auth" || lower.startsWith("/api/auth/")) {
|
|
1607
|
+
return true;
|
|
1608
|
+
}
|
|
1609
|
+
const prefix = "/api/databases/";
|
|
1610
|
+
if (!lower.startsWith(prefix)) {
|
|
1611
|
+
return false;
|
|
1612
|
+
}
|
|
1613
|
+
const rest = lower.slice(prefix.length);
|
|
1614
|
+
const slash = rest.indexOf("/");
|
|
1615
|
+
if (slash < 0) {
|
|
1616
|
+
return false;
|
|
1617
|
+
}
|
|
1618
|
+
const afterDb = rest.slice(slash + 1);
|
|
1619
|
+
return afterDb === "auth" || afterDb.startsWith("auth/");
|
|
1620
|
+
}
|
|
1621
|
+
function readBodyToken(bodyText) {
|
|
1622
|
+
if (bodyText == null || bodyText.trim().length === 0) {
|
|
1623
|
+
return void 0;
|
|
1624
|
+
}
|
|
1625
|
+
try {
|
|
1626
|
+
const parsed = JSON.parse(bodyText);
|
|
1627
|
+
if (parsed !== null && typeof parsed === "object" && "token" in parsed && typeof parsed.token === "string") {
|
|
1628
|
+
return parsed.token;
|
|
1629
|
+
}
|
|
1630
|
+
} catch {
|
|
1631
|
+
}
|
|
1632
|
+
return void 0;
|
|
1633
|
+
}
|
|
1548
1634
|
|
|
1549
1635
|
// src/resilience/retry.ts
|
|
1550
1636
|
var DEFAULT_MAX_RETRIES = 3;
|
|
@@ -1977,6 +2063,48 @@ function databasePath2(db) {
|
|
|
1977
2063
|
return `/api/databases/${encodeURIComponent(db)}`;
|
|
1978
2064
|
}
|
|
1979
2065
|
|
|
2066
|
+
// src/consistency-token-store.ts
|
|
2067
|
+
var MemoryConsistencyTokenStore = class {
|
|
2068
|
+
constructor() {
|
|
2069
|
+
this.tokens = /* @__PURE__ */ new Map();
|
|
2070
|
+
}
|
|
2071
|
+
get(database) {
|
|
2072
|
+
if (typeof database !== "string" || database.trim().length === 0) {
|
|
2073
|
+
throw new Error("database must be a non-empty string");
|
|
2074
|
+
}
|
|
2075
|
+
return this.tokens.get(normalizeKey(database));
|
|
2076
|
+
}
|
|
2077
|
+
observe(database, token) {
|
|
2078
|
+
if (typeof database !== "string" || database.trim().length === 0) {
|
|
2079
|
+
throw new Error("database must be a non-empty string");
|
|
2080
|
+
}
|
|
2081
|
+
if (token == null || token.trim().length === 0) {
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
const key = normalizeKey(database);
|
|
2085
|
+
const stored = this.tokens.get(key);
|
|
2086
|
+
if (stored === void 0 || compareOrdinal(token, stored) > 0) {
|
|
2087
|
+
this.tokens.set(key, token);
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
};
|
|
2091
|
+
function compareOrdinal(left, right) {
|
|
2092
|
+
if (left === right) return 0;
|
|
2093
|
+
return left < right ? -1 : 1;
|
|
2094
|
+
}
|
|
2095
|
+
function maxToken(left, right) {
|
|
2096
|
+
if (left == null || left.length === 0) {
|
|
2097
|
+
return right == null || right.length === 0 ? void 0 : right;
|
|
2098
|
+
}
|
|
2099
|
+
if (right == null || right.length === 0) {
|
|
2100
|
+
return left;
|
|
2101
|
+
}
|
|
2102
|
+
return compareOrdinal(left, right) >= 0 ? left : right;
|
|
2103
|
+
}
|
|
2104
|
+
function normalizeKey(database) {
|
|
2105
|
+
return database.toLowerCase();
|
|
2106
|
+
}
|
|
2107
|
+
|
|
1980
2108
|
// src/streaming/subscription.ts
|
|
1981
2109
|
var AsyncEventQueue = class {
|
|
1982
2110
|
constructor() {
|
|
@@ -2033,7 +2161,7 @@ var AsyncEventQueue = class {
|
|
|
2033
2161
|
}
|
|
2034
2162
|
};
|
|
2035
2163
|
var TableSubscription = class {
|
|
2036
|
-
constructor(transport, identity, options = {}, onWarnings) {
|
|
2164
|
+
constructor(transport, identity, options = {}, onWarnings, store, database) {
|
|
2037
2165
|
this._queue = new AsyncEventQueue();
|
|
2038
2166
|
this._active = true;
|
|
2039
2167
|
this._started = false;
|
|
@@ -2049,6 +2177,11 @@ var TableSubscription = class {
|
|
|
2049
2177
|
this._onError = options.onError;
|
|
2050
2178
|
this._onWarnings = onWarnings;
|
|
2051
2179
|
this._conflate = options.conflate;
|
|
2180
|
+
this._atLeast = options.atLeast;
|
|
2181
|
+
this._waitMs = options.waitMs;
|
|
2182
|
+
this._onExceeded = options.onExceeded;
|
|
2183
|
+
this._store = store;
|
|
2184
|
+
this._database = database;
|
|
2052
2185
|
this._reconnectHandlerKey = `${this.id}::reconnect`;
|
|
2053
2186
|
}
|
|
2054
2187
|
get lastVersion() {
|
|
@@ -2113,7 +2246,7 @@ var TableSubscription = class {
|
|
|
2113
2246
|
id: this.id
|
|
2114
2247
|
};
|
|
2115
2248
|
if (this._identity.kind === "named") {
|
|
2116
|
-
message.
|
|
2249
|
+
message.name = this._identity.name;
|
|
2117
2250
|
if (this._identity.args !== void 0) {
|
|
2118
2251
|
message.args = this._identity.args;
|
|
2119
2252
|
}
|
|
@@ -2132,8 +2265,30 @@ var TableSubscription = class {
|
|
|
2132
2265
|
if (this._conflate !== void 0) {
|
|
2133
2266
|
message.conflate = this._conflate;
|
|
2134
2267
|
}
|
|
2268
|
+
const pin = this._resolvePin();
|
|
2269
|
+
if (pin !== void 0) {
|
|
2270
|
+
message.at_least = pin;
|
|
2271
|
+
}
|
|
2272
|
+
if (this._waitMs !== void 0) {
|
|
2273
|
+
message.wait_ms = this._waitMs;
|
|
2274
|
+
}
|
|
2275
|
+
if (this._onExceeded !== void 0) {
|
|
2276
|
+
message.on_exceeded = this._onExceeded;
|
|
2277
|
+
}
|
|
2135
2278
|
await this._transport.send(message);
|
|
2136
2279
|
}
|
|
2280
|
+
_resolvePin() {
|
|
2281
|
+
if (this._atLeast !== void 0 && this._store != null && this._database != null) {
|
|
2282
|
+
this._store.observe(this._database, this._atLeast);
|
|
2283
|
+
}
|
|
2284
|
+
const stored = this._store != null && this._database != null ? this._store.get(this._database) : void 0;
|
|
2285
|
+
return maxToken(this._atLeast, stored);
|
|
2286
|
+
}
|
|
2287
|
+
_observeToken(token) {
|
|
2288
|
+
if (token !== void 0 && this._store != null && this._database != null) {
|
|
2289
|
+
this._store.observe(this._database, token);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2137
2292
|
_handleMessage(message) {
|
|
2138
2293
|
if (!this._active) {
|
|
2139
2294
|
return;
|
|
@@ -2160,6 +2315,7 @@ var TableSubscription = class {
|
|
|
2160
2315
|
}
|
|
2161
2316
|
_handleSnapshotPage(message) {
|
|
2162
2317
|
this._pendingSnapshotRows.push(...message.rows);
|
|
2318
|
+
this._observeToken(message.token);
|
|
2163
2319
|
}
|
|
2164
2320
|
_handleSnapshotComplete(message) {
|
|
2165
2321
|
this._lastVersion = message.version;
|
|
@@ -2177,6 +2333,10 @@ var TableSubscription = class {
|
|
|
2177
2333
|
if (message.total_matches !== void 0) {
|
|
2178
2334
|
snapshot.totalMatches = message.total_matches;
|
|
2179
2335
|
}
|
|
2336
|
+
if (message.token !== void 0) {
|
|
2337
|
+
snapshot.token = message.token;
|
|
2338
|
+
this._observeToken(message.token);
|
|
2339
|
+
}
|
|
2180
2340
|
this._queue.push(snapshot);
|
|
2181
2341
|
}
|
|
2182
2342
|
async _handleGap(message) {
|
|
@@ -2202,6 +2362,10 @@ var TableSubscription = class {
|
|
|
2202
2362
|
if (message.values_skipped !== void 0) {
|
|
2203
2363
|
event.values_skipped = message.values_skipped;
|
|
2204
2364
|
}
|
|
2365
|
+
if (message.token !== void 0) {
|
|
2366
|
+
event.token = message.token;
|
|
2367
|
+
this._observeToken(message.token);
|
|
2368
|
+
}
|
|
2205
2369
|
this._onChange?.(event);
|
|
2206
2370
|
this._queue.push(event);
|
|
2207
2371
|
}
|
|
@@ -2546,11 +2710,12 @@ var TableQuery = class _TableQuery {
|
|
|
2546
2710
|
* @param state - Optional initial state (used for immutable chaining).
|
|
2547
2711
|
* @internal Use `client.table()` to create queries.
|
|
2548
2712
|
*/
|
|
2549
|
-
constructor(transport, tableName, database, state, getWebSocketTransport) {
|
|
2713
|
+
constructor(transport, tableName, database, state, getWebSocketTransport, store) {
|
|
2550
2714
|
this.transport = transport;
|
|
2551
2715
|
this.tableName = tableName;
|
|
2552
2716
|
this.database = database;
|
|
2553
2717
|
this.getWebSocketTransport = getWebSocketTransport;
|
|
2718
|
+
this.store = store;
|
|
2554
2719
|
this.state = state ?? {
|
|
2555
2720
|
predicates: [],
|
|
2556
2721
|
groupClauses: [],
|
|
@@ -2566,6 +2731,16 @@ var TableQuery = class _TableQuery {
|
|
|
2566
2731
|
isDistinct: false
|
|
2567
2732
|
};
|
|
2568
2733
|
}
|
|
2734
|
+
withState(state) {
|
|
2735
|
+
return new _TableQuery(
|
|
2736
|
+
this.transport,
|
|
2737
|
+
this.tableName,
|
|
2738
|
+
this.database,
|
|
2739
|
+
state,
|
|
2740
|
+
this.getWebSocketTransport,
|
|
2741
|
+
this.store
|
|
2742
|
+
);
|
|
2743
|
+
}
|
|
2569
2744
|
where(column, operator, value) {
|
|
2570
2745
|
const newPredicates = buildWherePredicates(column, operator, value);
|
|
2571
2746
|
return new _TableQuery(
|
|
@@ -2576,7 +2751,8 @@ var TableQuery = class _TableQuery {
|
|
|
2576
2751
|
...this.state,
|
|
2577
2752
|
predicates: [...this.state.predicates, ...newPredicates]
|
|
2578
2753
|
},
|
|
2579
|
-
this.getWebSocketTransport
|
|
2754
|
+
this.getWebSocketTransport,
|
|
2755
|
+
this.store
|
|
2580
2756
|
);
|
|
2581
2757
|
}
|
|
2582
2758
|
/**
|
|
@@ -2595,7 +2771,7 @@ var TableQuery = class _TableQuery {
|
|
|
2595
2771
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2596
2772
|
...this.state,
|
|
2597
2773
|
groupClauses: [...this.state.groupClauses, sub]
|
|
2598
|
-
}, this.getWebSocketTransport);
|
|
2774
|
+
}, this.getWebSocketTransport, this.store);
|
|
2599
2775
|
}
|
|
2600
2776
|
/**
|
|
2601
2777
|
* Sets the primary sort column for the query.
|
|
@@ -2620,7 +2796,7 @@ var TableQuery = class _TableQuery {
|
|
|
2620
2796
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2621
2797
|
...this.state,
|
|
2622
2798
|
orderByClauses: [orderByClause]
|
|
2623
|
-
}, this.getWebSocketTransport);
|
|
2799
|
+
}, this.getWebSocketTransport, this.store);
|
|
2624
2800
|
}
|
|
2625
2801
|
/**
|
|
2626
2802
|
* Sets the primary sort column to descending order.
|
|
@@ -2666,7 +2842,7 @@ var TableQuery = class _TableQuery {
|
|
|
2666
2842
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2667
2843
|
...this.state,
|
|
2668
2844
|
orderByClauses: [...this.state.orderByClauses, orderByClause]
|
|
2669
|
-
}, this.getWebSocketTransport);
|
|
2845
|
+
}, this.getWebSocketTransport, this.store);
|
|
2670
2846
|
}
|
|
2671
2847
|
/**
|
|
2672
2848
|
* Sets the maximum number of rows to return.
|
|
@@ -2683,7 +2859,7 @@ var TableQuery = class _TableQuery {
|
|
|
2683
2859
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2684
2860
|
...this.state,
|
|
2685
2861
|
limitValue: count
|
|
2686
|
-
}, this.getWebSocketTransport);
|
|
2862
|
+
}, this.getWebSocketTransport, this.store);
|
|
2687
2863
|
}
|
|
2688
2864
|
/**
|
|
2689
2865
|
* Sets the number of rows to skip.
|
|
@@ -2700,7 +2876,7 @@ var TableQuery = class _TableQuery {
|
|
|
2700
2876
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2701
2877
|
...this.state,
|
|
2702
2878
|
offsetValue: count
|
|
2703
|
-
}, this.getWebSocketTransport);
|
|
2879
|
+
}, this.getWebSocketTransport, this.store);
|
|
2704
2880
|
}
|
|
2705
2881
|
/**
|
|
2706
2882
|
* Requests cross-partition access for this query.
|
|
@@ -2715,10 +2891,21 @@ var TableQuery = class _TableQuery {
|
|
|
2715
2891
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2716
2892
|
...this.state,
|
|
2717
2893
|
crossPartitionAccess: true
|
|
2718
|
-
}, this.getWebSocketTransport);
|
|
2894
|
+
}, this.getWebSocketTransport, this.store);
|
|
2719
2895
|
}
|
|
2720
2896
|
/**
|
|
2721
|
-
*
|
|
2897
|
+
* Pin this query at at least this C-1 token. Observes the token into the
|
|
2898
|
+
* client store (I3, sticky) and presents it on execute via `X-Aouda-Token`.
|
|
2899
|
+
*/
|
|
2900
|
+
atLeast(token) {
|
|
2901
|
+
if (typeof token !== "string" || token.trim().length === 0) {
|
|
2902
|
+
throw new Error("atLeast() requires a non-empty token");
|
|
2903
|
+
}
|
|
2904
|
+
this.store?.observe(this.database, token);
|
|
2905
|
+
return this.withState({ ...this.state, atLeast: token });
|
|
2906
|
+
}
|
|
2907
|
+
/**
|
|
2908
|
+
* Selects specific columns to return.
|
|
2722
2909
|
* If not called, all columns are returned.
|
|
2723
2910
|
*
|
|
2724
2911
|
* When T is a specific row type, only keys of T are accepted as column names.
|
|
@@ -2740,7 +2927,7 @@ var TableQuery = class _TableQuery {
|
|
|
2740
2927
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2741
2928
|
...this.state,
|
|
2742
2929
|
selectColumns: columns.length > 0 ? columns : null
|
|
2743
|
-
}, this.getWebSocketTransport);
|
|
2930
|
+
}, this.getWebSocketTransport, this.store);
|
|
2744
2931
|
}
|
|
2745
2932
|
/**
|
|
2746
2933
|
* Return only distinct (de-duplicated) rows for the given columns — SQL `SELECT DISTINCT`.
|
|
@@ -2770,7 +2957,7 @@ var TableQuery = class _TableQuery {
|
|
|
2770
2957
|
...this.state,
|
|
2771
2958
|
selectColumns: columns,
|
|
2772
2959
|
isDistinct: true
|
|
2773
|
-
}, this.getWebSocketTransport);
|
|
2960
|
+
}, this.getWebSocketTransport, this.store);
|
|
2774
2961
|
}
|
|
2775
2962
|
/**
|
|
2776
2963
|
* Adds server-side computed columns to the query result.
|
|
@@ -2799,7 +2986,7 @@ var TableQuery = class _TableQuery {
|
|
|
2799
2986
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2800
2987
|
...this.state,
|
|
2801
2988
|
selectExprs: projections
|
|
2802
|
-
}, this.getWebSocketTransport);
|
|
2989
|
+
}, this.getWebSocketTransport, this.store);
|
|
2803
2990
|
}
|
|
2804
2991
|
join(rightTable, leftColumnOrColumns, rightColumnOrColumns) {
|
|
2805
2992
|
return this.addJoinClause(
|
|
@@ -2857,7 +3044,8 @@ var TableQuery = class _TableQuery {
|
|
|
2857
3044
|
}
|
|
2858
3045
|
]
|
|
2859
3046
|
},
|
|
2860
|
-
this.getWebSocketTransport
|
|
3047
|
+
this.getWebSocketTransport,
|
|
3048
|
+
this.store
|
|
2861
3049
|
);
|
|
2862
3050
|
}
|
|
2863
3051
|
/**
|
|
@@ -2893,7 +3081,8 @@ var TableQuery = class _TableQuery {
|
|
|
2893
3081
|
...this.state,
|
|
2894
3082
|
groupByColumns: [...columns]
|
|
2895
3083
|
},
|
|
2896
|
-
this.getWebSocketTransport
|
|
3084
|
+
this.getWebSocketTransport,
|
|
3085
|
+
this.store
|
|
2897
3086
|
);
|
|
2898
3087
|
}
|
|
2899
3088
|
/**
|
|
@@ -2927,8 +3116,11 @@ var TableQuery = class _TableQuery {
|
|
|
2927
3116
|
onSnapshot: options.onSnapshot,
|
|
2928
3117
|
onChange: options.onChange,
|
|
2929
3118
|
onError: options.onError,
|
|
2930
|
-
conflate: options.conflate
|
|
2931
|
-
|
|
3119
|
+
conflate: options.conflate,
|
|
3120
|
+
atLeast: options.atLeast ?? this.state.atLeast,
|
|
3121
|
+
waitMs: options.waitMs,
|
|
3122
|
+
onExceeded: options.onExceeded
|
|
3123
|
+
}, void 0, this.store, this.database);
|
|
2932
3124
|
subscription.start();
|
|
2933
3125
|
return subscription;
|
|
2934
3126
|
}
|
|
@@ -3043,7 +3235,8 @@ var TableQuery = class _TableQuery {
|
|
|
3043
3235
|
...this.state,
|
|
3044
3236
|
joinClauses: [...this.state.joinClauses, joinClause]
|
|
3045
3237
|
},
|
|
3046
|
-
this.getWebSocketTransport
|
|
3238
|
+
this.getWebSocketTransport,
|
|
3239
|
+
this.store
|
|
3047
3240
|
);
|
|
3048
3241
|
}
|
|
3049
3242
|
addAggregate(op, column) {
|
|
@@ -3064,7 +3257,8 @@ var TableQuery = class _TableQuery {
|
|
|
3064
3257
|
}
|
|
3065
3258
|
]
|
|
3066
3259
|
},
|
|
3067
|
-
this.getWebSocketTransport
|
|
3260
|
+
this.getWebSocketTransport,
|
|
3261
|
+
this.store
|
|
3068
3262
|
);
|
|
3069
3263
|
}
|
|
3070
3264
|
requireWebSocketTransport() {
|
|
@@ -3094,17 +3288,23 @@ var TableQuery = class _TableQuery {
|
|
|
3094
3288
|
* ```
|
|
3095
3289
|
*/
|
|
3096
3290
|
async execute() {
|
|
3291
|
+
if (this.state.atLeast) {
|
|
3292
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3293
|
+
}
|
|
3097
3294
|
const request = this.buildRequest();
|
|
3098
3295
|
const path = `${databasePath2(this.database)}/query`;
|
|
3099
3296
|
const response = await this.transport.post(path, request);
|
|
3100
3297
|
const rows = columnarToRows(response);
|
|
3101
3298
|
const stats = response.stats;
|
|
3102
|
-
return { rows, stats };
|
|
3299
|
+
return { rows, stats, token: response.token };
|
|
3103
3300
|
}
|
|
3104
3301
|
/**
|
|
3105
3302
|
* Executes the query and returns the raw columnar JSON payload (no row-object conversion).
|
|
3106
3303
|
*/
|
|
3107
3304
|
async toColumnar() {
|
|
3305
|
+
if (this.state.atLeast) {
|
|
3306
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3307
|
+
}
|
|
3108
3308
|
const request = this.buildRequest();
|
|
3109
3309
|
const path = `${databasePath2(this.database)}/query`;
|
|
3110
3310
|
return this.transport.post(path, request);
|
|
@@ -3134,8 +3334,12 @@ var TableQuery = class _TableQuery {
|
|
|
3134
3334
|
limitValue: 0,
|
|
3135
3335
|
selectColumns: []
|
|
3136
3336
|
},
|
|
3137
|
-
this.getWebSocketTransport
|
|
3337
|
+
this.getWebSocketTransport,
|
|
3338
|
+
this.store
|
|
3138
3339
|
);
|
|
3340
|
+
if (this.state.atLeast) {
|
|
3341
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3342
|
+
}
|
|
3139
3343
|
const request = countQuery.buildRequest();
|
|
3140
3344
|
const path = `${databasePath2(this.database)}/query`;
|
|
3141
3345
|
const response = await this.transport.post(path, request);
|
|
@@ -3182,7 +3386,8 @@ var TableQuery = class _TableQuery {
|
|
|
3182
3386
|
const response = await this.transport.post(path, body);
|
|
3183
3387
|
const result = {
|
|
3184
3388
|
rowsInserted: response.rowsInserted,
|
|
3185
|
-
executionMs: response.executionMs
|
|
3389
|
+
executionMs: response.executionMs,
|
|
3390
|
+
token: response.token
|
|
3186
3391
|
};
|
|
3187
3392
|
if (response.generatedValues !== void 0) {
|
|
3188
3393
|
result.generatedValues = response.generatedValues;
|
|
@@ -3232,7 +3437,8 @@ var TableQuery = class _TableQuery {
|
|
|
3232
3437
|
const response = await this.transport.post(path, body);
|
|
3233
3438
|
const result = {
|
|
3234
3439
|
rowsInserted: response.rowsInserted,
|
|
3235
|
-
executionMs: response.executionMs
|
|
3440
|
+
executionMs: response.executionMs,
|
|
3441
|
+
token: response.token
|
|
3236
3442
|
};
|
|
3237
3443
|
if (response.generatedValues !== void 0) {
|
|
3238
3444
|
result.generatedValues = response.generatedValues;
|
|
@@ -3284,6 +3490,7 @@ var TableQuery = class _TableQuery {
|
|
|
3284
3490
|
return {
|
|
3285
3491
|
rowsAffected: response.rowsUpdated,
|
|
3286
3492
|
executionMs: response.executionMs,
|
|
3493
|
+
token: response.token,
|
|
3287
3494
|
...response.rows ? { rows: columnarToRows(response.rows) } : {},
|
|
3288
3495
|
...response.rowsTruncated ? { rowsTruncated: true } : {}
|
|
3289
3496
|
};
|
|
@@ -3334,6 +3541,7 @@ var TableQuery = class _TableQuery {
|
|
|
3334
3541
|
rowsAffected: response.rowsDeleted,
|
|
3335
3542
|
executionMs: response.executionMs,
|
|
3336
3543
|
hasMore: response.hasMore,
|
|
3544
|
+
token: response.token,
|
|
3337
3545
|
...response.rows ? { rows: columnarToRows(response.rows) } : {},
|
|
3338
3546
|
...response.rowsTruncated ? { rowsTruncated: true } : {}
|
|
3339
3547
|
};
|
|
@@ -3353,7 +3561,8 @@ var TableQuery = class _TableQuery {
|
|
|
3353
3561
|
return {
|
|
3354
3562
|
rowsAffected: response.rowsDeleted,
|
|
3355
3563
|
executionMs: response.executionMs,
|
|
3356
|
-
hasMore: false
|
|
3564
|
+
hasMore: false,
|
|
3565
|
+
token: response.token
|
|
3357
3566
|
};
|
|
3358
3567
|
}
|
|
3359
3568
|
/**
|
|
@@ -3366,7 +3575,14 @@ var TableQuery = class _TableQuery {
|
|
|
3366
3575
|
throw new Error("batch() requires a non-empty operations array");
|
|
3367
3576
|
}
|
|
3368
3577
|
const wireOperations = operations.map((op, index) => {
|
|
3369
|
-
const base = new _TableQuery(
|
|
3578
|
+
const base = new _TableQuery(
|
|
3579
|
+
this.transport,
|
|
3580
|
+
this.tableName,
|
|
3581
|
+
this.database,
|
|
3582
|
+
void 0,
|
|
3583
|
+
this.getWebSocketTransport,
|
|
3584
|
+
this.store
|
|
3585
|
+
);
|
|
3370
3586
|
const scoped = op.where(base);
|
|
3371
3587
|
const where = scoped.buildWhereClause();
|
|
3372
3588
|
if (!where) {
|
|
@@ -4734,12 +4950,12 @@ function raiseDeprecationWarnings(sink, warnings) {
|
|
|
4734
4950
|
continue;
|
|
4735
4951
|
}
|
|
4736
4952
|
const sunset = warning.sunsetAt != null ? ` sunsetAt=${warning.sunsetAt}` : "";
|
|
4737
|
-
const
|
|
4953
|
+
const name = warning.name != null && warning.name.length > 0 ? ` name=${warning.name}` : "";
|
|
4738
4954
|
sink({
|
|
4739
4955
|
code: warning.code,
|
|
4740
|
-
|
|
4956
|
+
name: warning.name,
|
|
4741
4957
|
sunsetAt: warning.sunsetAt,
|
|
4742
|
-
message: `${warning.code}:${
|
|
4958
|
+
message: `${warning.code}:${name}${sunset}`.trim()
|
|
4743
4959
|
});
|
|
4744
4960
|
}
|
|
4745
4961
|
}
|
|
@@ -4752,24 +4968,28 @@ function emptyStats() {
|
|
|
4752
4968
|
};
|
|
4753
4969
|
}
|
|
4754
4970
|
var NamedQueriesApi = class {
|
|
4755
|
-
constructor(transport, database, onWarning, getStreamingTransport) {
|
|
4971
|
+
constructor(transport, database, onWarning, getStreamingTransport, store) {
|
|
4756
4972
|
this.transport = transport;
|
|
4757
4973
|
this.database = database;
|
|
4758
4974
|
this.onWarning = onWarning;
|
|
4759
4975
|
this.getStreamingTransport = getStreamingTransport;
|
|
4976
|
+
this.store = store;
|
|
4760
4977
|
}
|
|
4761
|
-
async execute(
|
|
4762
|
-
if (typeof
|
|
4763
|
-
throw new Error("Named query
|
|
4978
|
+
async execute(name, args, options) {
|
|
4979
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
4980
|
+
throw new Error("Named query name must be a non-empty string");
|
|
4764
4981
|
}
|
|
4765
4982
|
const prefix = databasePath2(this.database);
|
|
4766
|
-
const path = `${prefix}/named-queries/${encodeURIComponent(
|
|
4983
|
+
const path = `${prefix}/named-queries/${encodeURIComponent(name)}/query?format=columnar`;
|
|
4767
4984
|
const body = {
|
|
4768
4985
|
args: args ?? {}
|
|
4769
4986
|
};
|
|
4770
4987
|
if (options?.orderByIndex !== void 0) {
|
|
4771
4988
|
body.orderByIndex = options.orderByIndex;
|
|
4772
4989
|
}
|
|
4990
|
+
if (options?.atLeast !== void 0) {
|
|
4991
|
+
this.store?.observe(this.database, options.atLeast);
|
|
4992
|
+
}
|
|
4773
4993
|
const response = await this.transport.post(
|
|
4774
4994
|
path,
|
|
4775
4995
|
body,
|
|
@@ -4781,7 +5001,8 @@ var NamedQueriesApi = class {
|
|
|
4781
5001
|
rows,
|
|
4782
5002
|
stats: response.stats,
|
|
4783
5003
|
warnings: response.warnings,
|
|
4784
|
-
totalMatches: response.totalMatches
|
|
5004
|
+
totalMatches: response.totalMatches,
|
|
5005
|
+
token: response.token
|
|
4785
5006
|
};
|
|
4786
5007
|
}
|
|
4787
5008
|
async batch(items, options) {
|
|
@@ -4799,6 +5020,9 @@ var NamedQueriesApi = class {
|
|
|
4799
5020
|
400
|
|
4800
5021
|
);
|
|
4801
5022
|
}
|
|
5023
|
+
if (options?.atLeast !== void 0) {
|
|
5024
|
+
this.store?.observe(this.database, options.atLeast);
|
|
5025
|
+
}
|
|
4802
5026
|
const prefix = databasePath2(this.database);
|
|
4803
5027
|
const path = `${prefix}/named-queries/batch?format=columnar`;
|
|
4804
5028
|
const envelope = await this.transport.post(
|
|
@@ -4821,34 +5045,41 @@ var NamedQueriesApi = class {
|
|
|
4821
5045
|
rowCount: slot.rowCount ?? 0,
|
|
4822
5046
|
stats: slot.stats ?? emptyStats(),
|
|
4823
5047
|
warnings: slot.warnings,
|
|
4824
|
-
totalMatches: slot.totalMatches
|
|
5048
|
+
totalMatches: slot.totalMatches,
|
|
5049
|
+
token: slot.token
|
|
4825
5050
|
};
|
|
4826
5051
|
const result = {
|
|
4827
5052
|
rows: columnarToRows(columnar),
|
|
4828
5053
|
stats: columnar.stats,
|
|
4829
5054
|
warnings: slot.warnings,
|
|
4830
|
-
totalMatches: slot.totalMatches
|
|
5055
|
+
totalMatches: slot.totalMatches,
|
|
5056
|
+
token: slot.token
|
|
4831
5057
|
};
|
|
4832
5058
|
raiseDeprecationWarnings(this.onWarning, slot.warnings);
|
|
4833
5059
|
return { isError: false, result };
|
|
4834
5060
|
});
|
|
4835
5061
|
}
|
|
4836
|
-
subscribe(
|
|
4837
|
-
if (typeof
|
|
4838
|
-
throw new Error("Named query
|
|
5062
|
+
subscribe(name, args, options = {}) {
|
|
5063
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
5064
|
+
throw new Error("Named query name must be a non-empty string");
|
|
4839
5065
|
}
|
|
4840
5066
|
const subscription = new TableSubscription(
|
|
4841
5067
|
this.getStreamingTransport(),
|
|
4842
|
-
{ kind: "named",
|
|
5068
|
+
{ kind: "named", name, args, orderByIndex: options.orderByIndex },
|
|
4843
5069
|
{
|
|
4844
5070
|
onSnapshot: options.onSnapshot,
|
|
4845
5071
|
onChange: options.onChange,
|
|
4846
5072
|
onError: options.onError,
|
|
4847
|
-
conflate: options.conflate
|
|
5073
|
+
conflate: options.conflate,
|
|
5074
|
+
atLeast: options.atLeast,
|
|
5075
|
+
waitMs: options.waitMs,
|
|
5076
|
+
onExceeded: options.onExceeded
|
|
4848
5077
|
},
|
|
4849
5078
|
(warnings) => {
|
|
4850
5079
|
raiseDeprecationWarnings(this.onWarning, warnings);
|
|
4851
|
-
}
|
|
5080
|
+
},
|
|
5081
|
+
this.store,
|
|
5082
|
+
this.database
|
|
4852
5083
|
);
|
|
4853
5084
|
subscription.start();
|
|
4854
5085
|
return subscription;
|
|
@@ -4860,12 +5091,12 @@ var NamedMutationsApi = class {
|
|
|
4860
5091
|
this.database = database;
|
|
4861
5092
|
this.onWarning = onWarning;
|
|
4862
5093
|
}
|
|
4863
|
-
async execute(
|
|
4864
|
-
if (typeof
|
|
4865
|
-
throw new Error("Named mutation
|
|
5094
|
+
async execute(name, args) {
|
|
5095
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
5096
|
+
throw new Error("Named mutation name must be a non-empty string");
|
|
4866
5097
|
}
|
|
4867
5098
|
const prefix = databasePath2(this.database);
|
|
4868
|
-
const path = `${prefix}/named-mutations/${encodeURIComponent(
|
|
5099
|
+
const path = `${prefix}/named-mutations/${encodeURIComponent(name)}/execute`;
|
|
4869
5100
|
const wire = await this.transport.post(path, {
|
|
4870
5101
|
args: args ?? {}
|
|
4871
5102
|
});
|
|
@@ -4926,6 +5157,7 @@ var WebSocketTransport = class {
|
|
|
4926
5157
|
// Serialized-send queue: each send appends to this tail.
|
|
4927
5158
|
this._sendTail = Promise.resolve();
|
|
4928
5159
|
this._lastVersion = 0;
|
|
5160
|
+
this._lastToken = null;
|
|
4929
5161
|
this._reconnectAttempt = 0;
|
|
4930
5162
|
this._disposed = false;
|
|
4931
5163
|
this._missedPings = 0;
|
|
@@ -4943,6 +5175,7 @@ var WebSocketTransport = class {
|
|
|
4943
5175
|
this._pingIntervalMs = options.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS;
|
|
4944
5176
|
this._maxMissedHeartbeats = options.maxMissedHeartbeats ?? DEFAULT_MAX_MISSED_HEARTBEATS;
|
|
4945
5177
|
this._enableCompression = options.enableCompression ?? true;
|
|
5178
|
+
this._store = options.consistencyTokenStore;
|
|
4946
5179
|
this._wireMode = options.wireMode ?? "json";
|
|
4947
5180
|
this._authHandler?.setOnAccessTokenRefreshed((token) => {
|
|
4948
5181
|
if (this._handshakeComplete && this._ws?.readyState === WS_READY_STATE_OPEN) {
|
|
@@ -4951,10 +5184,14 @@ var WebSocketTransport = class {
|
|
|
4951
5184
|
});
|
|
4952
5185
|
}
|
|
4953
5186
|
// ─── Public API ────────────────────────────────────────────────────────────
|
|
4954
|
-
/** Latest
|
|
5187
|
+
/** Latest change-event sequence from the most recent server `heartbeat` message. */
|
|
4955
5188
|
get lastVersion() {
|
|
4956
5189
|
return this._lastVersion;
|
|
4957
5190
|
}
|
|
5191
|
+
/** Consistency token from the most recent server `heartbeat` (ADR 0042 D-13). */
|
|
5192
|
+
get lastToken() {
|
|
5193
|
+
return this._lastToken;
|
|
5194
|
+
}
|
|
4958
5195
|
/**
|
|
4959
5196
|
* Registers a handler for incoming server messages with the given channel id.
|
|
4960
5197
|
* Use `"__global__"` to receive broadcast messages that carry no `id`.
|
|
@@ -5142,6 +5379,10 @@ var WebSocketTransport = class {
|
|
|
5142
5379
|
}
|
|
5143
5380
|
case "heartbeat":
|
|
5144
5381
|
this._lastVersion = msg.version;
|
|
5382
|
+
this._lastToken = msg.token ?? null;
|
|
5383
|
+
if (this._lastToken != null && this._lastToken.length > 0) {
|
|
5384
|
+
this._store?.observe(this._database, this._lastToken);
|
|
5385
|
+
}
|
|
5145
5386
|
break;
|
|
5146
5387
|
case "pong":
|
|
5147
5388
|
this._missedPings = 0;
|
|
@@ -5307,16 +5548,21 @@ var LongPollTransport = class {
|
|
|
5307
5548
|
this._connected = false;
|
|
5308
5549
|
this._pollTask = null;
|
|
5309
5550
|
this._lastVersion = 0;
|
|
5551
|
+
this._lastToken = null;
|
|
5310
5552
|
this._serverUrl = serverUrl;
|
|
5311
5553
|
this._database = database;
|
|
5312
5554
|
this._authHandler = options.authHandler;
|
|
5313
5555
|
this._onReconnected = options.onReconnected;
|
|
5314
5556
|
this._waitMs = Math.max(1, options.waitMs ?? DEFAULT_WAIT_MS);
|
|
5315
5557
|
this._fetch = options.fetchImpl ?? localNetworkFetch;
|
|
5558
|
+
this._store = options.consistencyTokenStore;
|
|
5316
5559
|
}
|
|
5317
5560
|
get lastVersion() {
|
|
5318
5561
|
return this._lastVersion;
|
|
5319
5562
|
}
|
|
5563
|
+
get lastToken() {
|
|
5564
|
+
return this._lastToken;
|
|
5565
|
+
}
|
|
5320
5566
|
registerHandler(id, handler) {
|
|
5321
5567
|
this._handlers.set(id, handler);
|
|
5322
5568
|
}
|
|
@@ -5439,6 +5685,10 @@ var LongPollTransport = class {
|
|
|
5439
5685
|
for (const msg of payload.messages) {
|
|
5440
5686
|
if (msg.type === "heartbeat") {
|
|
5441
5687
|
this._lastVersion = msg.version;
|
|
5688
|
+
this._lastToken = msg.token ?? null;
|
|
5689
|
+
if (this._lastToken != null && this._lastToken.length > 0) {
|
|
5690
|
+
this._store?.observe(this._database, this._lastToken);
|
|
5691
|
+
}
|
|
5442
5692
|
}
|
|
5443
5693
|
const id = "id" in msg ? msg.id : void 0;
|
|
5444
5694
|
if (id !== void 0 && id !== null) {
|
|
@@ -5518,6 +5768,9 @@ var FallbackStreamingTransport = class {
|
|
|
5518
5768
|
get lastVersion() {
|
|
5519
5769
|
return this._active.lastVersion;
|
|
5520
5770
|
}
|
|
5771
|
+
get lastToken() {
|
|
5772
|
+
return this._active.lastToken;
|
|
5773
|
+
}
|
|
5521
5774
|
registerHandler(id, handler) {
|
|
5522
5775
|
this._handlers.set(id, handler);
|
|
5523
5776
|
this._active.registerHandler(id, handler);
|
|
@@ -5597,6 +5850,7 @@ var AoudaClient = class {
|
|
|
5597
5850
|
this.baseUrl = normalizeBaseUrl(options.serverUrl);
|
|
5598
5851
|
this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
5599
5852
|
this.database = options.database.trim();
|
|
5853
|
+
this._store = options.consistencyTokenStore ?? new MemoryConsistencyTokenStore();
|
|
5600
5854
|
if (!Number.isFinite(this.timeout) || this.timeout <= 0) {
|
|
5601
5855
|
throw new Error("timeout must be a finite positive number");
|
|
5602
5856
|
}
|
|
@@ -5631,7 +5885,9 @@ var AoudaClient = class {
|
|
|
5631
5885
|
}
|
|
5632
5886
|
const httpTransport = new HttpTransport({
|
|
5633
5887
|
baseUrl: this.baseUrl,
|
|
5634
|
-
timeout: this.timeout
|
|
5888
|
+
timeout: this.timeout,
|
|
5889
|
+
database: this.database,
|
|
5890
|
+
consistencyTokenStore: this._store
|
|
5635
5891
|
});
|
|
5636
5892
|
const activeAuth = options.serverAuth ?? options.appAuth;
|
|
5637
5893
|
if (activeAuth) {
|
|
@@ -5691,7 +5947,8 @@ var AoudaClient = class {
|
|
|
5691
5947
|
this.transport,
|
|
5692
5948
|
this.database,
|
|
5693
5949
|
onNamedArtifactWarning,
|
|
5694
|
-
() => this._getOrCreateWebSocketTransport()
|
|
5950
|
+
() => this._getOrCreateWebSocketTransport(),
|
|
5951
|
+
this._store
|
|
5695
5952
|
);
|
|
5696
5953
|
this._namedMutations = new NamedMutationsApi(
|
|
5697
5954
|
this.transport,
|
|
@@ -5790,7 +6047,8 @@ var AoudaClient = class {
|
|
|
5790
6047
|
name,
|
|
5791
6048
|
this.database,
|
|
5792
6049
|
void 0,
|
|
5793
|
-
() => this._getOrCreateWebSocketTransport()
|
|
6050
|
+
() => this._getOrCreateWebSocketTransport(),
|
|
6051
|
+
this._store
|
|
5794
6052
|
);
|
|
5795
6053
|
}
|
|
5796
6054
|
/**
|
|
@@ -5842,13 +6100,26 @@ var AoudaClient = class {
|
|
|
5842
6100
|
return this._materializedQueries;
|
|
5843
6101
|
}
|
|
5844
6102
|
/**
|
|
5845
|
-
*
|
|
6103
|
+
* Named-query execute, read-only batch, and subscribe by unique schema name.
|
|
5846
6104
|
*/
|
|
5847
6105
|
get namedQueries() {
|
|
5848
6106
|
return this._namedQueries;
|
|
5849
6107
|
}
|
|
6108
|
+
observeConsistencyToken(token) {
|
|
6109
|
+
this._store.observe(this.database, token);
|
|
6110
|
+
}
|
|
6111
|
+
getObservedConsistencyToken() {
|
|
6112
|
+
return this._store.get(this.database);
|
|
6113
|
+
}
|
|
6114
|
+
async getConsistencyToken() {
|
|
6115
|
+
const body = await this.transport.get(
|
|
6116
|
+
`/api/databases/${encodeURIComponent(this.database)}/token`
|
|
6117
|
+
);
|
|
6118
|
+
this._store.observe(this.database, body.token);
|
|
6119
|
+
return this._store.get(this.database) ?? body.token;
|
|
6120
|
+
}
|
|
5850
6121
|
/**
|
|
5851
|
-
*
|
|
6122
|
+
* Named-mutation execute by unique schema name. No batch.
|
|
5852
6123
|
*/
|
|
5853
6124
|
get namedMutations() {
|
|
5854
6125
|
return this._namedMutations;
|
|
@@ -5975,13 +6246,15 @@ var AoudaClient = class {
|
|
|
5975
6246
|
const primary = new WebSocketTransport(this.baseUrl, this.database, {
|
|
5976
6247
|
authHandler: this._authHandler,
|
|
5977
6248
|
enableCompression: this._streamingEnableCompression,
|
|
5978
|
-
wireMode: this._streamingWireMode
|
|
6249
|
+
wireMode: this._streamingWireMode,
|
|
6250
|
+
consistencyTokenStore: this._store
|
|
5979
6251
|
});
|
|
5980
6252
|
if (this._streamingEnableLongPollFallback) {
|
|
5981
6253
|
this._wsTransport = new FallbackStreamingTransport(primary, () => {
|
|
5982
6254
|
return new LongPollTransport(this.baseUrl, this.database, {
|
|
5983
6255
|
authHandler: this._authHandler,
|
|
5984
|
-
waitMs: this._streamingLongPollWaitMs
|
|
6256
|
+
waitMs: this._streamingLongPollWaitMs,
|
|
6257
|
+
consistencyTokenStore: this._store
|
|
5985
6258
|
});
|
|
5986
6259
|
});
|
|
5987
6260
|
} else {
|
|
@@ -6278,6 +6551,7 @@ export {
|
|
|
6278
6551
|
MaterializedQueriesApi,
|
|
6279
6552
|
MaterializedQueryState,
|
|
6280
6553
|
MaterializedQueryType,
|
|
6554
|
+
MemoryConsistencyTokenStore,
|
|
6281
6555
|
MetricsAdminApi,
|
|
6282
6556
|
NamedMutationsApi,
|
|
6283
6557
|
NamedQueriesApi,
|
|
@@ -6293,10 +6567,12 @@ export {
|
|
|
6293
6567
|
applyLocalNetworkAccess,
|
|
6294
6568
|
coerceColumnarValue,
|
|
6295
6569
|
columnarToRows,
|
|
6570
|
+
compareOrdinal,
|
|
6296
6571
|
createAoudaClient,
|
|
6297
6572
|
createAoudaClusterMcpToolSet,
|
|
6298
6573
|
installLocalNetworkFetch,
|
|
6299
6574
|
localNetworkFetch,
|
|
6575
|
+
maxToken,
|
|
6300
6576
|
resolveTargetAddressSpace,
|
|
6301
6577
|
version
|
|
6302
6578
|
};
|