@aouda/client 0.1.13 → 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 +366 -77
- 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 +366 -77
- package/dist/cli/index.js.map +1 -1
- package/dist/{client-DFujaTFB.d.cts → client-CXfjcF61.d.cts} +121 -23
- package/dist/{client-DFujaTFB.d.ts → client-CXfjcF61.d.ts} +121 -23
- package/dist/index.cjs +371 -76
- 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 +368 -76
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,7 @@ __export(index_exports, {
|
|
|
60
60
|
MaterializedQueriesApi: () => MaterializedQueriesApi,
|
|
61
61
|
MaterializedQueryState: () => MaterializedQueryState,
|
|
62
62
|
MaterializedQueryType: () => MaterializedQueryType,
|
|
63
|
+
MemoryConsistencyTokenStore: () => MemoryConsistencyTokenStore,
|
|
63
64
|
MetricsAdminApi: () => MetricsAdminApi,
|
|
64
65
|
NamedMutationsApi: () => NamedMutationsApi,
|
|
65
66
|
NamedQueriesApi: () => NamedQueriesApi,
|
|
@@ -75,10 +76,12 @@ __export(index_exports, {
|
|
|
75
76
|
applyLocalNetworkAccess: () => applyLocalNetworkAccess,
|
|
76
77
|
coerceColumnarValue: () => coerceColumnarValue,
|
|
77
78
|
columnarToRows: () => columnarToRows,
|
|
79
|
+
compareOrdinal: () => compareOrdinal,
|
|
78
80
|
createAoudaClient: () => createAoudaClient,
|
|
79
81
|
createAoudaClusterMcpToolSet: () => createAoudaClusterMcpToolSet,
|
|
80
82
|
installLocalNetworkFetch: () => installLocalNetworkFetch,
|
|
81
83
|
localNetworkFetch: () => localNetworkFetch,
|
|
84
|
+
maxToken: () => maxToken,
|
|
82
85
|
resolveTargetAddressSpace: () => resolveTargetAddressSpace,
|
|
83
86
|
version: () => version
|
|
84
87
|
});
|
|
@@ -87,7 +90,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
87
90
|
// package.json
|
|
88
91
|
var package_default = {
|
|
89
92
|
name: "@aouda/client",
|
|
90
|
-
version: "0.1.
|
|
93
|
+
version: "0.1.15",
|
|
91
94
|
description: "Official TypeScript/JavaScript client library for Aouda",
|
|
92
95
|
type: "module",
|
|
93
96
|
main: "./dist/index.cjs",
|
|
@@ -219,43 +222,44 @@ var AoudaResponseError = class extends AoudaError {
|
|
|
219
222
|
}
|
|
220
223
|
};
|
|
221
224
|
var AoudaApiError = class extends AoudaError {
|
|
222
|
-
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
225
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
223
226
|
super(message);
|
|
224
227
|
this.code = code;
|
|
225
228
|
this.statusCode = statusCode;
|
|
226
229
|
this.details = details;
|
|
227
230
|
this.requestId = requestId;
|
|
228
231
|
this.retryAfterSeconds = retryAfterSeconds;
|
|
232
|
+
this.token = token;
|
|
229
233
|
this.name = "AoudaApiError";
|
|
230
234
|
}
|
|
231
235
|
};
|
|
232
236
|
var AoudaNotFoundError = class extends AoudaApiError {
|
|
233
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
234
|
-
super(message, code, statusCode, details, requestId);
|
|
237
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
238
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
235
239
|
this.name = "AoudaNotFoundError";
|
|
236
240
|
}
|
|
237
241
|
};
|
|
238
242
|
var AoudaConflictError = class extends AoudaApiError {
|
|
239
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
240
|
-
super(message, code, statusCode, details, requestId);
|
|
243
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
244
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
241
245
|
this.name = "AoudaConflictError";
|
|
242
246
|
}
|
|
243
247
|
};
|
|
244
248
|
var AoudaValidationError = class extends AoudaApiError {
|
|
245
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
246
|
-
super(message, code, statusCode, details, requestId);
|
|
249
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
250
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
247
251
|
this.name = "AoudaValidationError";
|
|
248
252
|
}
|
|
249
253
|
};
|
|
250
254
|
var AoudaServerError = class extends AoudaApiError {
|
|
251
|
-
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
252
|
-
super(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
255
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
256
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
253
257
|
this.name = "AoudaServerError";
|
|
254
258
|
}
|
|
255
259
|
};
|
|
256
260
|
var AoudaAuthenticationError = class extends AoudaApiError {
|
|
257
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
258
|
-
super(message, code, statusCode, details, requestId);
|
|
261
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds, token) {
|
|
262
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds, token);
|
|
259
263
|
this.name = "AoudaAuthenticationError";
|
|
260
264
|
}
|
|
261
265
|
};
|
|
@@ -1067,7 +1071,7 @@ function buildHandle(jobId, commitResp, wasResumed, transport, database, signal)
|
|
|
1067
1071
|
rowsDurablyCommitted: commitResp.rowsLoaded,
|
|
1068
1072
|
segmentsCreated: commitResp.segmentsCreated,
|
|
1069
1073
|
committedAtUtc: commitResp.committedAtUtc,
|
|
1070
|
-
|
|
1074
|
+
token: commitResp.token,
|
|
1071
1075
|
writeConcernSatisfied: commitResp.writeConcernAchieved ?? "acknowledged",
|
|
1072
1076
|
writeConcernTimedOut: commitResp.writeConcernTimedOut,
|
|
1073
1077
|
wasResumed,
|
|
@@ -1193,6 +1197,7 @@ var PROTOCOL_VERSION_HEADER = "X-Aouda-Protocol-Version";
|
|
|
1193
1197
|
var PROTOCOL_VERSION = "1";
|
|
1194
1198
|
var CONTENT_TYPE_JSON2 = "application/json";
|
|
1195
1199
|
var REQUEST_ID_HEADER2 = "X-Request-Id";
|
|
1200
|
+
var TOKEN_HEADER = "X-Aouda-Token";
|
|
1196
1201
|
var ERROR_CODE_MAP = {
|
|
1197
1202
|
TABLE_NOT_FOUND: AoudaNotFoundError,
|
|
1198
1203
|
COLUMN_NOT_FOUND: AoudaNotFoundError,
|
|
@@ -1232,7 +1237,12 @@ var ERROR_CODE_MAP = {
|
|
|
1232
1237
|
AUTH_IDENTITY_INVALID: AoudaValidationError,
|
|
1233
1238
|
AUTH_IDENTITY_NOT_FOUND: AoudaValidationError,
|
|
1234
1239
|
BULK_LOAD_TRANSFORM_INTENT_REQUIRED: AoudaValidationError,
|
|
1235
|
-
BULK_LOAD_TRANSFORM_INTENT_CONFLICT: AoudaValidationError
|
|
1240
|
+
BULK_LOAD_TRANSFORM_INTENT_CONFLICT: AoudaValidationError,
|
|
1241
|
+
TOKEN_MALFORMED: AoudaValidationError,
|
|
1242
|
+
TOKEN_FOREIGN_DATABASE: AoudaValidationError,
|
|
1243
|
+
TOKEN_EPOCH_SUPERSEDED: AoudaConflictError,
|
|
1244
|
+
TOKEN_UNSATISFIED: AoudaConflictError,
|
|
1245
|
+
TOKEN_FETCH_PRIMARY: AoudaApiError
|
|
1236
1246
|
};
|
|
1237
1247
|
function createComposedAbortController(...signals) {
|
|
1238
1248
|
const controller = new AbortController();
|
|
@@ -1269,7 +1279,7 @@ function createApiError(statusCode, statusText, body, retryAfterHeader) {
|
|
|
1269
1279
|
const requestId = body.requestId;
|
|
1270
1280
|
const retryAfterSeconds = parseRetryAfterSeconds(retryAfterHeader ?? null);
|
|
1271
1281
|
const Ctor = ERROR_CODE_MAP[code] ?? AoudaApiError;
|
|
1272
|
-
return new Ctor(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
1282
|
+
return new Ctor(message, code, statusCode, details, requestId, retryAfterSeconds, body.token);
|
|
1273
1283
|
}
|
|
1274
1284
|
var HttpTransport = class {
|
|
1275
1285
|
constructor(options) {
|
|
@@ -1281,6 +1291,29 @@ var HttpTransport = class {
|
|
|
1281
1291
|
...options.defaultHeaders
|
|
1282
1292
|
};
|
|
1283
1293
|
this.abortController = new AbortController();
|
|
1294
|
+
this.database = options.database;
|
|
1295
|
+
this.store = options.consistencyTokenStore;
|
|
1296
|
+
}
|
|
1297
|
+
presentTokenHeaders(path, headers) {
|
|
1298
|
+
if (this.store == null || this.database == null || isAuthPath(path)) {
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
const token = this.store.get(this.database);
|
|
1302
|
+
if (token != null && token.length > 0) {
|
|
1303
|
+
headers[TOKEN_HEADER] = token;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
observeResponse(_path, response, bodyText, errorCode) {
|
|
1307
|
+
if (this.store == null || this.database == null) {
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
if (errorCode === "TOKEN_MALFORMED" || errorCode === "TOKEN_FOREIGN_DATABASE") {
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
const header = response.headers.get(TOKEN_HEADER);
|
|
1314
|
+
const bodyToken = readBodyToken(bodyText);
|
|
1315
|
+
const token = header != null && header.trim().length > 0 ? header : bodyToken;
|
|
1316
|
+
this.store.observe(this.database, token);
|
|
1284
1317
|
}
|
|
1285
1318
|
/**
|
|
1286
1319
|
* Abort all in-flight and future requests (e.g. on client disconnect).
|
|
@@ -1318,6 +1351,7 @@ var HttpTransport = class {
|
|
|
1318
1351
|
...this.defaultHeaders,
|
|
1319
1352
|
...config.headers
|
|
1320
1353
|
};
|
|
1354
|
+
this.presentTokenHeaders(config.path, headers);
|
|
1321
1355
|
if (config.body !== void 0 && config.body !== null) {
|
|
1322
1356
|
headers["Content-Type"] = CONTENT_TYPE_JSON2;
|
|
1323
1357
|
}
|
|
@@ -1337,6 +1371,7 @@ var HttpTransport = class {
|
|
|
1337
1371
|
const text = await response.text();
|
|
1338
1372
|
if (config.allowStatuses?.includes(response.status) && text) {
|
|
1339
1373
|
try {
|
|
1374
|
+
this.observeResponse(config.path, response, text);
|
|
1340
1375
|
return JSON.parse(text);
|
|
1341
1376
|
} catch {
|
|
1342
1377
|
}
|
|
@@ -1350,15 +1385,19 @@ var HttpTransport = class {
|
|
|
1350
1385
|
}
|
|
1351
1386
|
if (response.status === 401) {
|
|
1352
1387
|
const code = errorBody?.code ?? "AUTH_TOKEN_MISSING";
|
|
1388
|
+
this.observeResponse(config.path, response, text, code);
|
|
1353
1389
|
throw new AoudaAuthenticationError(
|
|
1354
1390
|
errorBody?.error ?? "Unauthorized",
|
|
1355
1391
|
code,
|
|
1356
1392
|
401,
|
|
1357
1393
|
errorBody?.details,
|
|
1358
|
-
errorBody?.requestId
|
|
1394
|
+
errorBody?.requestId,
|
|
1395
|
+
void 0,
|
|
1396
|
+
errorBody?.token
|
|
1359
1397
|
);
|
|
1360
1398
|
}
|
|
1361
1399
|
if (errorBody?.code != null) {
|
|
1400
|
+
this.observeResponse(config.path, response, text, errorBody.code);
|
|
1362
1401
|
throw createApiError(
|
|
1363
1402
|
response.status,
|
|
1364
1403
|
response.statusText,
|
|
@@ -1366,6 +1405,7 @@ var HttpTransport = class {
|
|
|
1366
1405
|
response.headers.get("Retry-After")
|
|
1367
1406
|
);
|
|
1368
1407
|
}
|
|
1408
|
+
this.observeResponse(config.path, response, text);
|
|
1369
1409
|
throw new AoudaResponseError(
|
|
1370
1410
|
errorBody?.error ?? `${response.status} ${response.statusText}`,
|
|
1371
1411
|
response.status,
|
|
@@ -1373,6 +1413,7 @@ var HttpTransport = class {
|
|
|
1373
1413
|
);
|
|
1374
1414
|
}
|
|
1375
1415
|
const responseText = await response.text();
|
|
1416
|
+
this.observeResponse(config.path, response, responseText);
|
|
1376
1417
|
if (config.rawText) {
|
|
1377
1418
|
return responseText;
|
|
1378
1419
|
}
|
|
@@ -1433,6 +1474,7 @@ var HttpTransport = class {
|
|
|
1433
1474
|
...this.defaultHeaders,
|
|
1434
1475
|
...config.headers
|
|
1435
1476
|
};
|
|
1477
|
+
this.presentTokenHeaders(config.path, headers);
|
|
1436
1478
|
if (config.rawBodyStr === void 0 && config.body !== void 0 && config.body !== null) {
|
|
1437
1479
|
headers["Content-Type"] = CONTENT_TYPE_JSON2;
|
|
1438
1480
|
}
|
|
@@ -1449,6 +1491,7 @@ var HttpTransport = class {
|
|
|
1449
1491
|
try {
|
|
1450
1492
|
const response = await localNetworkFetch(url, init);
|
|
1451
1493
|
if (response.ok || config.allowStatuses?.includes(response.status)) {
|
|
1494
|
+
this.observeResponse(config.path, response, void 0);
|
|
1452
1495
|
return response;
|
|
1453
1496
|
}
|
|
1454
1497
|
const text = await response.text();
|
|
@@ -1461,15 +1504,19 @@ var HttpTransport = class {
|
|
|
1461
1504
|
}
|
|
1462
1505
|
if (response.status === 401) {
|
|
1463
1506
|
const code = errorBody?.code ?? "AUTH_TOKEN_MISSING";
|
|
1507
|
+
this.observeResponse(config.path, response, text, code);
|
|
1464
1508
|
throw new AoudaAuthenticationError(
|
|
1465
1509
|
errorBody?.error ?? "Unauthorized",
|
|
1466
1510
|
code,
|
|
1467
1511
|
401,
|
|
1468
1512
|
errorBody?.details,
|
|
1469
|
-
errorBody?.requestId
|
|
1513
|
+
errorBody?.requestId,
|
|
1514
|
+
void 0,
|
|
1515
|
+
errorBody?.token
|
|
1470
1516
|
);
|
|
1471
1517
|
}
|
|
1472
1518
|
if (errorBody?.code != null) {
|
|
1519
|
+
this.observeResponse(config.path, response, text, errorBody.code);
|
|
1473
1520
|
throw createApiError(
|
|
1474
1521
|
response.status,
|
|
1475
1522
|
response.statusText,
|
|
@@ -1477,6 +1524,7 @@ var HttpTransport = class {
|
|
|
1477
1524
|
response.headers.get("Retry-After")
|
|
1478
1525
|
);
|
|
1479
1526
|
}
|
|
1527
|
+
this.observeResponse(config.path, response, text);
|
|
1480
1528
|
throw new AoudaResponseError(
|
|
1481
1529
|
errorBody?.error ?? `${response.status} ${response.statusText}`,
|
|
1482
1530
|
response.status,
|
|
@@ -1631,6 +1679,47 @@ var HttpTransport = class {
|
|
|
1631
1679
|
});
|
|
1632
1680
|
}
|
|
1633
1681
|
};
|
|
1682
|
+
function isAuthPath(path) {
|
|
1683
|
+
let p = path;
|
|
1684
|
+
const q = p.indexOf("?");
|
|
1685
|
+
if (q >= 0) {
|
|
1686
|
+
p = p.slice(0, q);
|
|
1687
|
+
}
|
|
1688
|
+
if (/^https?:\/\//i.test(p)) {
|
|
1689
|
+
try {
|
|
1690
|
+
p = new URL(p).pathname;
|
|
1691
|
+
} catch {
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
const lower = p.toLowerCase();
|
|
1695
|
+
if (lower === "/api/auth" || lower.startsWith("/api/auth/")) {
|
|
1696
|
+
return true;
|
|
1697
|
+
}
|
|
1698
|
+
const prefix = "/api/databases/";
|
|
1699
|
+
if (!lower.startsWith(prefix)) {
|
|
1700
|
+
return false;
|
|
1701
|
+
}
|
|
1702
|
+
const rest = lower.slice(prefix.length);
|
|
1703
|
+
const slash = rest.indexOf("/");
|
|
1704
|
+
if (slash < 0) {
|
|
1705
|
+
return false;
|
|
1706
|
+
}
|
|
1707
|
+
const afterDb = rest.slice(slash + 1);
|
|
1708
|
+
return afterDb === "auth" || afterDb.startsWith("auth/");
|
|
1709
|
+
}
|
|
1710
|
+
function readBodyToken(bodyText) {
|
|
1711
|
+
if (bodyText == null || bodyText.trim().length === 0) {
|
|
1712
|
+
return void 0;
|
|
1713
|
+
}
|
|
1714
|
+
try {
|
|
1715
|
+
const parsed = JSON.parse(bodyText);
|
|
1716
|
+
if (parsed !== null && typeof parsed === "object" && "token" in parsed && typeof parsed.token === "string") {
|
|
1717
|
+
return parsed.token;
|
|
1718
|
+
}
|
|
1719
|
+
} catch {
|
|
1720
|
+
}
|
|
1721
|
+
return void 0;
|
|
1722
|
+
}
|
|
1634
1723
|
|
|
1635
1724
|
// src/resilience/retry.ts
|
|
1636
1725
|
var DEFAULT_MAX_RETRIES = 3;
|
|
@@ -2063,6 +2152,48 @@ function databasePath2(db) {
|
|
|
2063
2152
|
return `/api/databases/${encodeURIComponent(db)}`;
|
|
2064
2153
|
}
|
|
2065
2154
|
|
|
2155
|
+
// src/consistency-token-store.ts
|
|
2156
|
+
var MemoryConsistencyTokenStore = class {
|
|
2157
|
+
constructor() {
|
|
2158
|
+
this.tokens = /* @__PURE__ */ new Map();
|
|
2159
|
+
}
|
|
2160
|
+
get(database) {
|
|
2161
|
+
if (typeof database !== "string" || database.trim().length === 0) {
|
|
2162
|
+
throw new Error("database must be a non-empty string");
|
|
2163
|
+
}
|
|
2164
|
+
return this.tokens.get(normalizeKey(database));
|
|
2165
|
+
}
|
|
2166
|
+
observe(database, token) {
|
|
2167
|
+
if (typeof database !== "string" || database.trim().length === 0) {
|
|
2168
|
+
throw new Error("database must be a non-empty string");
|
|
2169
|
+
}
|
|
2170
|
+
if (token == null || token.trim().length === 0) {
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
const key = normalizeKey(database);
|
|
2174
|
+
const stored = this.tokens.get(key);
|
|
2175
|
+
if (stored === void 0 || compareOrdinal(token, stored) > 0) {
|
|
2176
|
+
this.tokens.set(key, token);
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
function compareOrdinal(left, right) {
|
|
2181
|
+
if (left === right) return 0;
|
|
2182
|
+
return left < right ? -1 : 1;
|
|
2183
|
+
}
|
|
2184
|
+
function maxToken(left, right) {
|
|
2185
|
+
if (left == null || left.length === 0) {
|
|
2186
|
+
return right == null || right.length === 0 ? void 0 : right;
|
|
2187
|
+
}
|
|
2188
|
+
if (right == null || right.length === 0) {
|
|
2189
|
+
return left;
|
|
2190
|
+
}
|
|
2191
|
+
return compareOrdinal(left, right) >= 0 ? left : right;
|
|
2192
|
+
}
|
|
2193
|
+
function normalizeKey(database) {
|
|
2194
|
+
return database.toLowerCase();
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2066
2197
|
// src/streaming/subscription.ts
|
|
2067
2198
|
var AsyncEventQueue = class {
|
|
2068
2199
|
constructor() {
|
|
@@ -2119,7 +2250,7 @@ var AsyncEventQueue = class {
|
|
|
2119
2250
|
}
|
|
2120
2251
|
};
|
|
2121
2252
|
var TableSubscription = class {
|
|
2122
|
-
constructor(transport, identity, options = {}, onWarnings) {
|
|
2253
|
+
constructor(transport, identity, options = {}, onWarnings, store, database) {
|
|
2123
2254
|
this._queue = new AsyncEventQueue();
|
|
2124
2255
|
this._active = true;
|
|
2125
2256
|
this._started = false;
|
|
@@ -2135,6 +2266,11 @@ var TableSubscription = class {
|
|
|
2135
2266
|
this._onError = options.onError;
|
|
2136
2267
|
this._onWarnings = onWarnings;
|
|
2137
2268
|
this._conflate = options.conflate;
|
|
2269
|
+
this._atLeast = options.atLeast;
|
|
2270
|
+
this._waitMs = options.waitMs;
|
|
2271
|
+
this._onExceeded = options.onExceeded;
|
|
2272
|
+
this._store = store;
|
|
2273
|
+
this._database = database;
|
|
2138
2274
|
this._reconnectHandlerKey = `${this.id}::reconnect`;
|
|
2139
2275
|
}
|
|
2140
2276
|
get lastVersion() {
|
|
@@ -2199,10 +2335,13 @@ var TableSubscription = class {
|
|
|
2199
2335
|
id: this.id
|
|
2200
2336
|
};
|
|
2201
2337
|
if (this._identity.kind === "named") {
|
|
2202
|
-
message.
|
|
2338
|
+
message.name = this._identity.name;
|
|
2203
2339
|
if (this._identity.args !== void 0) {
|
|
2204
2340
|
message.args = this._identity.args;
|
|
2205
2341
|
}
|
|
2342
|
+
if (this._identity.orderByIndex !== void 0) {
|
|
2343
|
+
message.orderByIndex = this._identity.orderByIndex;
|
|
2344
|
+
}
|
|
2206
2345
|
} else {
|
|
2207
2346
|
message.target = this._identity.target;
|
|
2208
2347
|
if (this._identity.filter !== void 0) {
|
|
@@ -2215,8 +2354,30 @@ var TableSubscription = class {
|
|
|
2215
2354
|
if (this._conflate !== void 0) {
|
|
2216
2355
|
message.conflate = this._conflate;
|
|
2217
2356
|
}
|
|
2357
|
+
const pin = this._resolvePin();
|
|
2358
|
+
if (pin !== void 0) {
|
|
2359
|
+
message.at_least = pin;
|
|
2360
|
+
}
|
|
2361
|
+
if (this._waitMs !== void 0) {
|
|
2362
|
+
message.wait_ms = this._waitMs;
|
|
2363
|
+
}
|
|
2364
|
+
if (this._onExceeded !== void 0) {
|
|
2365
|
+
message.on_exceeded = this._onExceeded;
|
|
2366
|
+
}
|
|
2218
2367
|
await this._transport.send(message);
|
|
2219
2368
|
}
|
|
2369
|
+
_resolvePin() {
|
|
2370
|
+
if (this._atLeast !== void 0 && this._store != null && this._database != null) {
|
|
2371
|
+
this._store.observe(this._database, this._atLeast);
|
|
2372
|
+
}
|
|
2373
|
+
const stored = this._store != null && this._database != null ? this._store.get(this._database) : void 0;
|
|
2374
|
+
return maxToken(this._atLeast, stored);
|
|
2375
|
+
}
|
|
2376
|
+
_observeToken(token) {
|
|
2377
|
+
if (token !== void 0 && this._store != null && this._database != null) {
|
|
2378
|
+
this._store.observe(this._database, token);
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2220
2381
|
_handleMessage(message) {
|
|
2221
2382
|
if (!this._active) {
|
|
2222
2383
|
return;
|
|
@@ -2243,6 +2404,7 @@ var TableSubscription = class {
|
|
|
2243
2404
|
}
|
|
2244
2405
|
_handleSnapshotPage(message) {
|
|
2245
2406
|
this._pendingSnapshotRows.push(...message.rows);
|
|
2407
|
+
this._observeToken(message.token);
|
|
2246
2408
|
}
|
|
2247
2409
|
_handleSnapshotComplete(message) {
|
|
2248
2410
|
this._lastVersion = message.version;
|
|
@@ -2251,12 +2413,20 @@ var TableSubscription = class {
|
|
|
2251
2413
|
}
|
|
2252
2414
|
const rows = this._pendingSnapshotRows;
|
|
2253
2415
|
this._pendingSnapshotRows = [];
|
|
2254
|
-
this._onSnapshot?.(rows, message.version);
|
|
2255
|
-
|
|
2416
|
+
this._onSnapshot?.(rows, message.version, message.total_matches);
|
|
2417
|
+
const snapshot = {
|
|
2256
2418
|
type: "snapshot",
|
|
2257
2419
|
rows,
|
|
2258
2420
|
version: message.version
|
|
2259
|
-
}
|
|
2421
|
+
};
|
|
2422
|
+
if (message.total_matches !== void 0) {
|
|
2423
|
+
snapshot.totalMatches = message.total_matches;
|
|
2424
|
+
}
|
|
2425
|
+
if (message.token !== void 0) {
|
|
2426
|
+
snapshot.token = message.token;
|
|
2427
|
+
this._observeToken(message.token);
|
|
2428
|
+
}
|
|
2429
|
+
this._queue.push(snapshot);
|
|
2260
2430
|
}
|
|
2261
2431
|
async _handleGap(message) {
|
|
2262
2432
|
this._pendingSnapshotRows = [];
|
|
@@ -2281,6 +2451,10 @@ var TableSubscription = class {
|
|
|
2281
2451
|
if (message.values_skipped !== void 0) {
|
|
2282
2452
|
event.values_skipped = message.values_skipped;
|
|
2283
2453
|
}
|
|
2454
|
+
if (message.token !== void 0) {
|
|
2455
|
+
event.token = message.token;
|
|
2456
|
+
this._observeToken(message.token);
|
|
2457
|
+
}
|
|
2284
2458
|
this._onChange?.(event);
|
|
2285
2459
|
this._queue.push(event);
|
|
2286
2460
|
}
|
|
@@ -2625,11 +2799,12 @@ var TableQuery = class _TableQuery {
|
|
|
2625
2799
|
* @param state - Optional initial state (used for immutable chaining).
|
|
2626
2800
|
* @internal Use `client.table()` to create queries.
|
|
2627
2801
|
*/
|
|
2628
|
-
constructor(transport, tableName, database, state, getWebSocketTransport) {
|
|
2802
|
+
constructor(transport, tableName, database, state, getWebSocketTransport, store) {
|
|
2629
2803
|
this.transport = transport;
|
|
2630
2804
|
this.tableName = tableName;
|
|
2631
2805
|
this.database = database;
|
|
2632
2806
|
this.getWebSocketTransport = getWebSocketTransport;
|
|
2807
|
+
this.store = store;
|
|
2633
2808
|
this.state = state ?? {
|
|
2634
2809
|
predicates: [],
|
|
2635
2810
|
groupClauses: [],
|
|
@@ -2645,6 +2820,16 @@ var TableQuery = class _TableQuery {
|
|
|
2645
2820
|
isDistinct: false
|
|
2646
2821
|
};
|
|
2647
2822
|
}
|
|
2823
|
+
withState(state) {
|
|
2824
|
+
return new _TableQuery(
|
|
2825
|
+
this.transport,
|
|
2826
|
+
this.tableName,
|
|
2827
|
+
this.database,
|
|
2828
|
+
state,
|
|
2829
|
+
this.getWebSocketTransport,
|
|
2830
|
+
this.store
|
|
2831
|
+
);
|
|
2832
|
+
}
|
|
2648
2833
|
where(column, operator, value) {
|
|
2649
2834
|
const newPredicates = buildWherePredicates(column, operator, value);
|
|
2650
2835
|
return new _TableQuery(
|
|
@@ -2655,7 +2840,8 @@ var TableQuery = class _TableQuery {
|
|
|
2655
2840
|
...this.state,
|
|
2656
2841
|
predicates: [...this.state.predicates, ...newPredicates]
|
|
2657
2842
|
},
|
|
2658
|
-
this.getWebSocketTransport
|
|
2843
|
+
this.getWebSocketTransport,
|
|
2844
|
+
this.store
|
|
2659
2845
|
);
|
|
2660
2846
|
}
|
|
2661
2847
|
/**
|
|
@@ -2674,7 +2860,7 @@ var TableQuery = class _TableQuery {
|
|
|
2674
2860
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2675
2861
|
...this.state,
|
|
2676
2862
|
groupClauses: [...this.state.groupClauses, sub]
|
|
2677
|
-
}, this.getWebSocketTransport);
|
|
2863
|
+
}, this.getWebSocketTransport, this.store);
|
|
2678
2864
|
}
|
|
2679
2865
|
/**
|
|
2680
2866
|
* Sets the primary sort column for the query.
|
|
@@ -2699,7 +2885,7 @@ var TableQuery = class _TableQuery {
|
|
|
2699
2885
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2700
2886
|
...this.state,
|
|
2701
2887
|
orderByClauses: [orderByClause]
|
|
2702
|
-
}, this.getWebSocketTransport);
|
|
2888
|
+
}, this.getWebSocketTransport, this.store);
|
|
2703
2889
|
}
|
|
2704
2890
|
/**
|
|
2705
2891
|
* Sets the primary sort column to descending order.
|
|
@@ -2745,7 +2931,7 @@ var TableQuery = class _TableQuery {
|
|
|
2745
2931
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2746
2932
|
...this.state,
|
|
2747
2933
|
orderByClauses: [...this.state.orderByClauses, orderByClause]
|
|
2748
|
-
}, this.getWebSocketTransport);
|
|
2934
|
+
}, this.getWebSocketTransport, this.store);
|
|
2749
2935
|
}
|
|
2750
2936
|
/**
|
|
2751
2937
|
* Sets the maximum number of rows to return.
|
|
@@ -2762,7 +2948,7 @@ var TableQuery = class _TableQuery {
|
|
|
2762
2948
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2763
2949
|
...this.state,
|
|
2764
2950
|
limitValue: count
|
|
2765
|
-
}, this.getWebSocketTransport);
|
|
2951
|
+
}, this.getWebSocketTransport, this.store);
|
|
2766
2952
|
}
|
|
2767
2953
|
/**
|
|
2768
2954
|
* Sets the number of rows to skip.
|
|
@@ -2779,7 +2965,7 @@ var TableQuery = class _TableQuery {
|
|
|
2779
2965
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2780
2966
|
...this.state,
|
|
2781
2967
|
offsetValue: count
|
|
2782
|
-
}, this.getWebSocketTransport);
|
|
2968
|
+
}, this.getWebSocketTransport, this.store);
|
|
2783
2969
|
}
|
|
2784
2970
|
/**
|
|
2785
2971
|
* Requests cross-partition access for this query.
|
|
@@ -2794,10 +2980,21 @@ var TableQuery = class _TableQuery {
|
|
|
2794
2980
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2795
2981
|
...this.state,
|
|
2796
2982
|
crossPartitionAccess: true
|
|
2797
|
-
}, this.getWebSocketTransport);
|
|
2983
|
+
}, this.getWebSocketTransport, this.store);
|
|
2984
|
+
}
|
|
2985
|
+
/**
|
|
2986
|
+
* Pin this query at at least this C-1 token. Observes the token into the
|
|
2987
|
+
* client store (I3, sticky) and presents it on execute via `X-Aouda-Token`.
|
|
2988
|
+
*/
|
|
2989
|
+
atLeast(token) {
|
|
2990
|
+
if (typeof token !== "string" || token.trim().length === 0) {
|
|
2991
|
+
throw new Error("atLeast() requires a non-empty token");
|
|
2992
|
+
}
|
|
2993
|
+
this.store?.observe(this.database, token);
|
|
2994
|
+
return this.withState({ ...this.state, atLeast: token });
|
|
2798
2995
|
}
|
|
2799
2996
|
/**
|
|
2800
|
-
*
|
|
2997
|
+
* Selects specific columns to return.
|
|
2801
2998
|
* If not called, all columns are returned.
|
|
2802
2999
|
*
|
|
2803
3000
|
* When T is a specific row type, only keys of T are accepted as column names.
|
|
@@ -2819,7 +3016,7 @@ var TableQuery = class _TableQuery {
|
|
|
2819
3016
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2820
3017
|
...this.state,
|
|
2821
3018
|
selectColumns: columns.length > 0 ? columns : null
|
|
2822
|
-
}, this.getWebSocketTransport);
|
|
3019
|
+
}, this.getWebSocketTransport, this.store);
|
|
2823
3020
|
}
|
|
2824
3021
|
/**
|
|
2825
3022
|
* Return only distinct (de-duplicated) rows for the given columns — SQL `SELECT DISTINCT`.
|
|
@@ -2849,7 +3046,7 @@ var TableQuery = class _TableQuery {
|
|
|
2849
3046
|
...this.state,
|
|
2850
3047
|
selectColumns: columns,
|
|
2851
3048
|
isDistinct: true
|
|
2852
|
-
}, this.getWebSocketTransport);
|
|
3049
|
+
}, this.getWebSocketTransport, this.store);
|
|
2853
3050
|
}
|
|
2854
3051
|
/**
|
|
2855
3052
|
* Adds server-side computed columns to the query result.
|
|
@@ -2878,7 +3075,7 @@ var TableQuery = class _TableQuery {
|
|
|
2878
3075
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2879
3076
|
...this.state,
|
|
2880
3077
|
selectExprs: projections
|
|
2881
|
-
}, this.getWebSocketTransport);
|
|
3078
|
+
}, this.getWebSocketTransport, this.store);
|
|
2882
3079
|
}
|
|
2883
3080
|
join(rightTable, leftColumnOrColumns, rightColumnOrColumns) {
|
|
2884
3081
|
return this.addJoinClause(
|
|
@@ -2936,7 +3133,8 @@ var TableQuery = class _TableQuery {
|
|
|
2936
3133
|
}
|
|
2937
3134
|
]
|
|
2938
3135
|
},
|
|
2939
|
-
this.getWebSocketTransport
|
|
3136
|
+
this.getWebSocketTransport,
|
|
3137
|
+
this.store
|
|
2940
3138
|
);
|
|
2941
3139
|
}
|
|
2942
3140
|
/**
|
|
@@ -2972,7 +3170,8 @@ var TableQuery = class _TableQuery {
|
|
|
2972
3170
|
...this.state,
|
|
2973
3171
|
groupByColumns: [...columns]
|
|
2974
3172
|
},
|
|
2975
|
-
this.getWebSocketTransport
|
|
3173
|
+
this.getWebSocketTransport,
|
|
3174
|
+
this.store
|
|
2976
3175
|
);
|
|
2977
3176
|
}
|
|
2978
3177
|
/**
|
|
@@ -3006,8 +3205,11 @@ var TableQuery = class _TableQuery {
|
|
|
3006
3205
|
onSnapshot: options.onSnapshot,
|
|
3007
3206
|
onChange: options.onChange,
|
|
3008
3207
|
onError: options.onError,
|
|
3009
|
-
conflate: options.conflate
|
|
3010
|
-
|
|
3208
|
+
conflate: options.conflate,
|
|
3209
|
+
atLeast: options.atLeast ?? this.state.atLeast,
|
|
3210
|
+
waitMs: options.waitMs,
|
|
3211
|
+
onExceeded: options.onExceeded
|
|
3212
|
+
}, void 0, this.store, this.database);
|
|
3011
3213
|
subscription.start();
|
|
3012
3214
|
return subscription;
|
|
3013
3215
|
}
|
|
@@ -3122,7 +3324,8 @@ var TableQuery = class _TableQuery {
|
|
|
3122
3324
|
...this.state,
|
|
3123
3325
|
joinClauses: [...this.state.joinClauses, joinClause]
|
|
3124
3326
|
},
|
|
3125
|
-
this.getWebSocketTransport
|
|
3327
|
+
this.getWebSocketTransport,
|
|
3328
|
+
this.store
|
|
3126
3329
|
);
|
|
3127
3330
|
}
|
|
3128
3331
|
addAggregate(op, column) {
|
|
@@ -3143,7 +3346,8 @@ var TableQuery = class _TableQuery {
|
|
|
3143
3346
|
}
|
|
3144
3347
|
]
|
|
3145
3348
|
},
|
|
3146
|
-
this.getWebSocketTransport
|
|
3349
|
+
this.getWebSocketTransport,
|
|
3350
|
+
this.store
|
|
3147
3351
|
);
|
|
3148
3352
|
}
|
|
3149
3353
|
requireWebSocketTransport() {
|
|
@@ -3173,17 +3377,23 @@ var TableQuery = class _TableQuery {
|
|
|
3173
3377
|
* ```
|
|
3174
3378
|
*/
|
|
3175
3379
|
async execute() {
|
|
3380
|
+
if (this.state.atLeast) {
|
|
3381
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3382
|
+
}
|
|
3176
3383
|
const request = this.buildRequest();
|
|
3177
3384
|
const path = `${databasePath2(this.database)}/query`;
|
|
3178
3385
|
const response = await this.transport.post(path, request);
|
|
3179
3386
|
const rows = columnarToRows(response);
|
|
3180
3387
|
const stats = response.stats;
|
|
3181
|
-
return { rows, stats };
|
|
3388
|
+
return { rows, stats, token: response.token };
|
|
3182
3389
|
}
|
|
3183
3390
|
/**
|
|
3184
3391
|
* Executes the query and returns the raw columnar JSON payload (no row-object conversion).
|
|
3185
3392
|
*/
|
|
3186
3393
|
async toColumnar() {
|
|
3394
|
+
if (this.state.atLeast) {
|
|
3395
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3396
|
+
}
|
|
3187
3397
|
const request = this.buildRequest();
|
|
3188
3398
|
const path = `${databasePath2(this.database)}/query`;
|
|
3189
3399
|
return this.transport.post(path, request);
|
|
@@ -3213,8 +3423,12 @@ var TableQuery = class _TableQuery {
|
|
|
3213
3423
|
limitValue: 0,
|
|
3214
3424
|
selectColumns: []
|
|
3215
3425
|
},
|
|
3216
|
-
this.getWebSocketTransport
|
|
3426
|
+
this.getWebSocketTransport,
|
|
3427
|
+
this.store
|
|
3217
3428
|
);
|
|
3429
|
+
if (this.state.atLeast) {
|
|
3430
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3431
|
+
}
|
|
3218
3432
|
const request = countQuery.buildRequest();
|
|
3219
3433
|
const path = `${databasePath2(this.database)}/query`;
|
|
3220
3434
|
const response = await this.transport.post(path, request);
|
|
@@ -3261,7 +3475,8 @@ var TableQuery = class _TableQuery {
|
|
|
3261
3475
|
const response = await this.transport.post(path, body);
|
|
3262
3476
|
const result = {
|
|
3263
3477
|
rowsInserted: response.rowsInserted,
|
|
3264
|
-
executionMs: response.executionMs
|
|
3478
|
+
executionMs: response.executionMs,
|
|
3479
|
+
token: response.token
|
|
3265
3480
|
};
|
|
3266
3481
|
if (response.generatedValues !== void 0) {
|
|
3267
3482
|
result.generatedValues = response.generatedValues;
|
|
@@ -3311,7 +3526,8 @@ var TableQuery = class _TableQuery {
|
|
|
3311
3526
|
const response = await this.transport.post(path, body);
|
|
3312
3527
|
const result = {
|
|
3313
3528
|
rowsInserted: response.rowsInserted,
|
|
3314
|
-
executionMs: response.executionMs
|
|
3529
|
+
executionMs: response.executionMs,
|
|
3530
|
+
token: response.token
|
|
3315
3531
|
};
|
|
3316
3532
|
if (response.generatedValues !== void 0) {
|
|
3317
3533
|
result.generatedValues = response.generatedValues;
|
|
@@ -3363,6 +3579,7 @@ var TableQuery = class _TableQuery {
|
|
|
3363
3579
|
return {
|
|
3364
3580
|
rowsAffected: response.rowsUpdated,
|
|
3365
3581
|
executionMs: response.executionMs,
|
|
3582
|
+
token: response.token,
|
|
3366
3583
|
...response.rows ? { rows: columnarToRows(response.rows) } : {},
|
|
3367
3584
|
...response.rowsTruncated ? { rowsTruncated: true } : {}
|
|
3368
3585
|
};
|
|
@@ -3413,6 +3630,7 @@ var TableQuery = class _TableQuery {
|
|
|
3413
3630
|
rowsAffected: response.rowsDeleted,
|
|
3414
3631
|
executionMs: response.executionMs,
|
|
3415
3632
|
hasMore: response.hasMore,
|
|
3633
|
+
token: response.token,
|
|
3416
3634
|
...response.rows ? { rows: columnarToRows(response.rows) } : {},
|
|
3417
3635
|
...response.rowsTruncated ? { rowsTruncated: true } : {}
|
|
3418
3636
|
};
|
|
@@ -3432,7 +3650,8 @@ var TableQuery = class _TableQuery {
|
|
|
3432
3650
|
return {
|
|
3433
3651
|
rowsAffected: response.rowsDeleted,
|
|
3434
3652
|
executionMs: response.executionMs,
|
|
3435
|
-
hasMore: false
|
|
3653
|
+
hasMore: false,
|
|
3654
|
+
token: response.token
|
|
3436
3655
|
};
|
|
3437
3656
|
}
|
|
3438
3657
|
/**
|
|
@@ -3445,7 +3664,14 @@ var TableQuery = class _TableQuery {
|
|
|
3445
3664
|
throw new Error("batch() requires a non-empty operations array");
|
|
3446
3665
|
}
|
|
3447
3666
|
const wireOperations = operations.map((op, index) => {
|
|
3448
|
-
const base = new _TableQuery(
|
|
3667
|
+
const base = new _TableQuery(
|
|
3668
|
+
this.transport,
|
|
3669
|
+
this.tableName,
|
|
3670
|
+
this.database,
|
|
3671
|
+
void 0,
|
|
3672
|
+
this.getWebSocketTransport,
|
|
3673
|
+
this.store
|
|
3674
|
+
);
|
|
3449
3675
|
const scoped = op.where(base);
|
|
3450
3676
|
const where = scoped.buildWhereClause();
|
|
3451
3677
|
if (!where) {
|
|
@@ -4813,12 +5039,12 @@ function raiseDeprecationWarnings(sink, warnings) {
|
|
|
4813
5039
|
continue;
|
|
4814
5040
|
}
|
|
4815
5041
|
const sunset = warning.sunsetAt != null ? ` sunsetAt=${warning.sunsetAt}` : "";
|
|
4816
|
-
const
|
|
5042
|
+
const name = warning.name != null && warning.name.length > 0 ? ` name=${warning.name}` : "";
|
|
4817
5043
|
sink({
|
|
4818
5044
|
code: warning.code,
|
|
4819
|
-
|
|
5045
|
+
name: warning.name,
|
|
4820
5046
|
sunsetAt: warning.sunsetAt,
|
|
4821
|
-
message: `${warning.code}:${
|
|
5047
|
+
message: `${warning.code}:${name}${sunset}`.trim()
|
|
4822
5048
|
});
|
|
4823
5049
|
}
|
|
4824
5050
|
}
|
|
@@ -4831,21 +5057,31 @@ function emptyStats() {
|
|
|
4831
5057
|
};
|
|
4832
5058
|
}
|
|
4833
5059
|
var NamedQueriesApi = class {
|
|
4834
|
-
constructor(transport, database, onWarning, getStreamingTransport) {
|
|
5060
|
+
constructor(transport, database, onWarning, getStreamingTransport, store) {
|
|
4835
5061
|
this.transport = transport;
|
|
4836
5062
|
this.database = database;
|
|
4837
5063
|
this.onWarning = onWarning;
|
|
4838
5064
|
this.getStreamingTransport = getStreamingTransport;
|
|
5065
|
+
this.store = store;
|
|
4839
5066
|
}
|
|
4840
|
-
async execute(
|
|
4841
|
-
if (typeof
|
|
4842
|
-
throw new Error("Named query
|
|
5067
|
+
async execute(name, args, options) {
|
|
5068
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
5069
|
+
throw new Error("Named query name must be a non-empty string");
|
|
4843
5070
|
}
|
|
4844
5071
|
const prefix = databasePath2(this.database);
|
|
4845
|
-
const path = `${prefix}/named-queries/${encodeURIComponent(
|
|
5072
|
+
const path = `${prefix}/named-queries/${encodeURIComponent(name)}/query?format=columnar`;
|
|
5073
|
+
const body = {
|
|
5074
|
+
args: args ?? {}
|
|
5075
|
+
};
|
|
5076
|
+
if (options?.orderByIndex !== void 0) {
|
|
5077
|
+
body.orderByIndex = options.orderByIndex;
|
|
5078
|
+
}
|
|
5079
|
+
if (options?.atLeast !== void 0) {
|
|
5080
|
+
this.store?.observe(this.database, options.atLeast);
|
|
5081
|
+
}
|
|
4846
5082
|
const response = await this.transport.post(
|
|
4847
5083
|
path,
|
|
4848
|
-
|
|
5084
|
+
body,
|
|
4849
5085
|
{ signal: options?.signal }
|
|
4850
5086
|
);
|
|
4851
5087
|
const rows = columnarToRows(response);
|
|
@@ -4853,7 +5089,9 @@ var NamedQueriesApi = class {
|
|
|
4853
5089
|
return {
|
|
4854
5090
|
rows,
|
|
4855
5091
|
stats: response.stats,
|
|
4856
|
-
warnings: response.warnings
|
|
5092
|
+
warnings: response.warnings,
|
|
5093
|
+
totalMatches: response.totalMatches,
|
|
5094
|
+
token: response.token
|
|
4857
5095
|
};
|
|
4858
5096
|
}
|
|
4859
5097
|
async batch(items, options) {
|
|
@@ -4871,6 +5109,9 @@ var NamedQueriesApi = class {
|
|
|
4871
5109
|
400
|
|
4872
5110
|
);
|
|
4873
5111
|
}
|
|
5112
|
+
if (options?.atLeast !== void 0) {
|
|
5113
|
+
this.store?.observe(this.database, options.atLeast);
|
|
5114
|
+
}
|
|
4874
5115
|
const prefix = databasePath2(this.database);
|
|
4875
5116
|
const path = `${prefix}/named-queries/batch?format=columnar`;
|
|
4876
5117
|
const envelope = await this.transport.post(
|
|
@@ -4892,33 +5133,42 @@ var NamedQueriesApi = class {
|
|
|
4892
5133
|
data: slot.data ?? [],
|
|
4893
5134
|
rowCount: slot.rowCount ?? 0,
|
|
4894
5135
|
stats: slot.stats ?? emptyStats(),
|
|
4895
|
-
warnings: slot.warnings
|
|
5136
|
+
warnings: slot.warnings,
|
|
5137
|
+
totalMatches: slot.totalMatches,
|
|
5138
|
+
token: slot.token
|
|
4896
5139
|
};
|
|
4897
5140
|
const result = {
|
|
4898
5141
|
rows: columnarToRows(columnar),
|
|
4899
5142
|
stats: columnar.stats,
|
|
4900
|
-
warnings: slot.warnings
|
|
5143
|
+
warnings: slot.warnings,
|
|
5144
|
+
totalMatches: slot.totalMatches,
|
|
5145
|
+
token: slot.token
|
|
4901
5146
|
};
|
|
4902
5147
|
raiseDeprecationWarnings(this.onWarning, slot.warnings);
|
|
4903
5148
|
return { isError: false, result };
|
|
4904
5149
|
});
|
|
4905
5150
|
}
|
|
4906
|
-
subscribe(
|
|
4907
|
-
if (typeof
|
|
4908
|
-
throw new Error("Named query
|
|
5151
|
+
subscribe(name, args, options = {}) {
|
|
5152
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
5153
|
+
throw new Error("Named query name must be a non-empty string");
|
|
4909
5154
|
}
|
|
4910
5155
|
const subscription = new TableSubscription(
|
|
4911
5156
|
this.getStreamingTransport(),
|
|
4912
|
-
{ kind: "named",
|
|
5157
|
+
{ kind: "named", name, args, orderByIndex: options.orderByIndex },
|
|
4913
5158
|
{
|
|
4914
5159
|
onSnapshot: options.onSnapshot,
|
|
4915
5160
|
onChange: options.onChange,
|
|
4916
5161
|
onError: options.onError,
|
|
4917
|
-
conflate: options.conflate
|
|
5162
|
+
conflate: options.conflate,
|
|
5163
|
+
atLeast: options.atLeast,
|
|
5164
|
+
waitMs: options.waitMs,
|
|
5165
|
+
onExceeded: options.onExceeded
|
|
4918
5166
|
},
|
|
4919
5167
|
(warnings) => {
|
|
4920
5168
|
raiseDeprecationWarnings(this.onWarning, warnings);
|
|
4921
|
-
}
|
|
5169
|
+
},
|
|
5170
|
+
this.store,
|
|
5171
|
+
this.database
|
|
4922
5172
|
);
|
|
4923
5173
|
subscription.start();
|
|
4924
5174
|
return subscription;
|
|
@@ -4930,12 +5180,12 @@ var NamedMutationsApi = class {
|
|
|
4930
5180
|
this.database = database;
|
|
4931
5181
|
this.onWarning = onWarning;
|
|
4932
5182
|
}
|
|
4933
|
-
async execute(
|
|
4934
|
-
if (typeof
|
|
4935
|
-
throw new Error("Named mutation
|
|
5183
|
+
async execute(name, args) {
|
|
5184
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
5185
|
+
throw new Error("Named mutation name must be a non-empty string");
|
|
4936
5186
|
}
|
|
4937
5187
|
const prefix = databasePath2(this.database);
|
|
4938
|
-
const path = `${prefix}/named-mutations/${encodeURIComponent(
|
|
5188
|
+
const path = `${prefix}/named-mutations/${encodeURIComponent(name)}/execute`;
|
|
4939
5189
|
const wire = await this.transport.post(path, {
|
|
4940
5190
|
args: args ?? {}
|
|
4941
5191
|
});
|
|
@@ -4996,6 +5246,7 @@ var WebSocketTransport = class {
|
|
|
4996
5246
|
// Serialized-send queue: each send appends to this tail.
|
|
4997
5247
|
this._sendTail = Promise.resolve();
|
|
4998
5248
|
this._lastVersion = 0;
|
|
5249
|
+
this._lastToken = null;
|
|
4999
5250
|
this._reconnectAttempt = 0;
|
|
5000
5251
|
this._disposed = false;
|
|
5001
5252
|
this._missedPings = 0;
|
|
@@ -5013,6 +5264,7 @@ var WebSocketTransport = class {
|
|
|
5013
5264
|
this._pingIntervalMs = options.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS;
|
|
5014
5265
|
this._maxMissedHeartbeats = options.maxMissedHeartbeats ?? DEFAULT_MAX_MISSED_HEARTBEATS;
|
|
5015
5266
|
this._enableCompression = options.enableCompression ?? true;
|
|
5267
|
+
this._store = options.consistencyTokenStore;
|
|
5016
5268
|
this._wireMode = options.wireMode ?? "json";
|
|
5017
5269
|
this._authHandler?.setOnAccessTokenRefreshed((token) => {
|
|
5018
5270
|
if (this._handshakeComplete && this._ws?.readyState === WS_READY_STATE_OPEN) {
|
|
@@ -5021,10 +5273,14 @@ var WebSocketTransport = class {
|
|
|
5021
5273
|
});
|
|
5022
5274
|
}
|
|
5023
5275
|
// ─── Public API ────────────────────────────────────────────────────────────
|
|
5024
|
-
/** Latest
|
|
5276
|
+
/** Latest change-event sequence from the most recent server `heartbeat` message. */
|
|
5025
5277
|
get lastVersion() {
|
|
5026
5278
|
return this._lastVersion;
|
|
5027
5279
|
}
|
|
5280
|
+
/** Consistency token from the most recent server `heartbeat` (ADR 0042 D-13). */
|
|
5281
|
+
get lastToken() {
|
|
5282
|
+
return this._lastToken;
|
|
5283
|
+
}
|
|
5028
5284
|
/**
|
|
5029
5285
|
* Registers a handler for incoming server messages with the given channel id.
|
|
5030
5286
|
* Use `"__global__"` to receive broadcast messages that carry no `id`.
|
|
@@ -5212,6 +5468,10 @@ var WebSocketTransport = class {
|
|
|
5212
5468
|
}
|
|
5213
5469
|
case "heartbeat":
|
|
5214
5470
|
this._lastVersion = msg.version;
|
|
5471
|
+
this._lastToken = msg.token ?? null;
|
|
5472
|
+
if (this._lastToken != null && this._lastToken.length > 0) {
|
|
5473
|
+
this._store?.observe(this._database, this._lastToken);
|
|
5474
|
+
}
|
|
5215
5475
|
break;
|
|
5216
5476
|
case "pong":
|
|
5217
5477
|
this._missedPings = 0;
|
|
@@ -5377,16 +5637,21 @@ var LongPollTransport = class {
|
|
|
5377
5637
|
this._connected = false;
|
|
5378
5638
|
this._pollTask = null;
|
|
5379
5639
|
this._lastVersion = 0;
|
|
5640
|
+
this._lastToken = null;
|
|
5380
5641
|
this._serverUrl = serverUrl;
|
|
5381
5642
|
this._database = database;
|
|
5382
5643
|
this._authHandler = options.authHandler;
|
|
5383
5644
|
this._onReconnected = options.onReconnected;
|
|
5384
5645
|
this._waitMs = Math.max(1, options.waitMs ?? DEFAULT_WAIT_MS);
|
|
5385
5646
|
this._fetch = options.fetchImpl ?? localNetworkFetch;
|
|
5647
|
+
this._store = options.consistencyTokenStore;
|
|
5386
5648
|
}
|
|
5387
5649
|
get lastVersion() {
|
|
5388
5650
|
return this._lastVersion;
|
|
5389
5651
|
}
|
|
5652
|
+
get lastToken() {
|
|
5653
|
+
return this._lastToken;
|
|
5654
|
+
}
|
|
5390
5655
|
registerHandler(id, handler) {
|
|
5391
5656
|
this._handlers.set(id, handler);
|
|
5392
5657
|
}
|
|
@@ -5509,6 +5774,10 @@ var LongPollTransport = class {
|
|
|
5509
5774
|
for (const msg of payload.messages) {
|
|
5510
5775
|
if (msg.type === "heartbeat") {
|
|
5511
5776
|
this._lastVersion = msg.version;
|
|
5777
|
+
this._lastToken = msg.token ?? null;
|
|
5778
|
+
if (this._lastToken != null && this._lastToken.length > 0) {
|
|
5779
|
+
this._store?.observe(this._database, this._lastToken);
|
|
5780
|
+
}
|
|
5512
5781
|
}
|
|
5513
5782
|
const id = "id" in msg ? msg.id : void 0;
|
|
5514
5783
|
if (id !== void 0 && id !== null) {
|
|
@@ -5588,6 +5857,9 @@ var FallbackStreamingTransport = class {
|
|
|
5588
5857
|
get lastVersion() {
|
|
5589
5858
|
return this._active.lastVersion;
|
|
5590
5859
|
}
|
|
5860
|
+
get lastToken() {
|
|
5861
|
+
return this._active.lastToken;
|
|
5862
|
+
}
|
|
5591
5863
|
registerHandler(id, handler) {
|
|
5592
5864
|
this._handlers.set(id, handler);
|
|
5593
5865
|
this._active.registerHandler(id, handler);
|
|
@@ -5667,6 +5939,7 @@ var AoudaClient = class {
|
|
|
5667
5939
|
this.baseUrl = normalizeBaseUrl(options.serverUrl);
|
|
5668
5940
|
this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
5669
5941
|
this.database = options.database.trim();
|
|
5942
|
+
this._store = options.consistencyTokenStore ?? new MemoryConsistencyTokenStore();
|
|
5670
5943
|
if (!Number.isFinite(this.timeout) || this.timeout <= 0) {
|
|
5671
5944
|
throw new Error("timeout must be a finite positive number");
|
|
5672
5945
|
}
|
|
@@ -5701,7 +5974,9 @@ var AoudaClient = class {
|
|
|
5701
5974
|
}
|
|
5702
5975
|
const httpTransport = new HttpTransport({
|
|
5703
5976
|
baseUrl: this.baseUrl,
|
|
5704
|
-
timeout: this.timeout
|
|
5977
|
+
timeout: this.timeout,
|
|
5978
|
+
database: this.database,
|
|
5979
|
+
consistencyTokenStore: this._store
|
|
5705
5980
|
});
|
|
5706
5981
|
const activeAuth = options.serverAuth ?? options.appAuth;
|
|
5707
5982
|
if (activeAuth) {
|
|
@@ -5761,7 +6036,8 @@ var AoudaClient = class {
|
|
|
5761
6036
|
this.transport,
|
|
5762
6037
|
this.database,
|
|
5763
6038
|
onNamedArtifactWarning,
|
|
5764
|
-
() => this._getOrCreateWebSocketTransport()
|
|
6039
|
+
() => this._getOrCreateWebSocketTransport(),
|
|
6040
|
+
this._store
|
|
5765
6041
|
);
|
|
5766
6042
|
this._namedMutations = new NamedMutationsApi(
|
|
5767
6043
|
this.transport,
|
|
@@ -5860,7 +6136,8 @@ var AoudaClient = class {
|
|
|
5860
6136
|
name,
|
|
5861
6137
|
this.database,
|
|
5862
6138
|
void 0,
|
|
5863
|
-
() => this._getOrCreateWebSocketTransport()
|
|
6139
|
+
() => this._getOrCreateWebSocketTransport(),
|
|
6140
|
+
this._store
|
|
5864
6141
|
);
|
|
5865
6142
|
}
|
|
5866
6143
|
/**
|
|
@@ -5912,13 +6189,26 @@ var AoudaClient = class {
|
|
|
5912
6189
|
return this._materializedQueries;
|
|
5913
6190
|
}
|
|
5914
6191
|
/**
|
|
5915
|
-
*
|
|
6192
|
+
* Named-query execute, read-only batch, and subscribe by unique schema name.
|
|
5916
6193
|
*/
|
|
5917
6194
|
get namedQueries() {
|
|
5918
6195
|
return this._namedQueries;
|
|
5919
6196
|
}
|
|
6197
|
+
observeConsistencyToken(token) {
|
|
6198
|
+
this._store.observe(this.database, token);
|
|
6199
|
+
}
|
|
6200
|
+
getObservedConsistencyToken() {
|
|
6201
|
+
return this._store.get(this.database);
|
|
6202
|
+
}
|
|
6203
|
+
async getConsistencyToken() {
|
|
6204
|
+
const body = await this.transport.get(
|
|
6205
|
+
`/api/databases/${encodeURIComponent(this.database)}/token`
|
|
6206
|
+
);
|
|
6207
|
+
this._store.observe(this.database, body.token);
|
|
6208
|
+
return this._store.get(this.database) ?? body.token;
|
|
6209
|
+
}
|
|
5920
6210
|
/**
|
|
5921
|
-
*
|
|
6211
|
+
* Named-mutation execute by unique schema name. No batch.
|
|
5922
6212
|
*/
|
|
5923
6213
|
get namedMutations() {
|
|
5924
6214
|
return this._namedMutations;
|
|
@@ -6045,13 +6335,15 @@ var AoudaClient = class {
|
|
|
6045
6335
|
const primary = new WebSocketTransport(this.baseUrl, this.database, {
|
|
6046
6336
|
authHandler: this._authHandler,
|
|
6047
6337
|
enableCompression: this._streamingEnableCompression,
|
|
6048
|
-
wireMode: this._streamingWireMode
|
|
6338
|
+
wireMode: this._streamingWireMode,
|
|
6339
|
+
consistencyTokenStore: this._store
|
|
6049
6340
|
});
|
|
6050
6341
|
if (this._streamingEnableLongPollFallback) {
|
|
6051
6342
|
this._wsTransport = new FallbackStreamingTransport(primary, () => {
|
|
6052
6343
|
return new LongPollTransport(this.baseUrl, this.database, {
|
|
6053
6344
|
authHandler: this._authHandler,
|
|
6054
|
-
waitMs: this._streamingLongPollWaitMs
|
|
6345
|
+
waitMs: this._streamingLongPollWaitMs,
|
|
6346
|
+
consistencyTokenStore: this._store
|
|
6055
6347
|
});
|
|
6056
6348
|
});
|
|
6057
6349
|
} else {
|
|
@@ -6349,6 +6641,7 @@ var version = package_default.version;
|
|
|
6349
6641
|
MaterializedQueriesApi,
|
|
6350
6642
|
MaterializedQueryState,
|
|
6351
6643
|
MaterializedQueryType,
|
|
6644
|
+
MemoryConsistencyTokenStore,
|
|
6352
6645
|
MetricsAdminApi,
|
|
6353
6646
|
NamedMutationsApi,
|
|
6354
6647
|
NamedQueriesApi,
|
|
@@ -6364,10 +6657,12 @@ var version = package_default.version;
|
|
|
6364
6657
|
applyLocalNetworkAccess,
|
|
6365
6658
|
coerceColumnarValue,
|
|
6366
6659
|
columnarToRows,
|
|
6660
|
+
compareOrdinal,
|
|
6367
6661
|
createAoudaClient,
|
|
6368
6662
|
createAoudaClusterMcpToolSet,
|
|
6369
6663
|
installLocalNetworkFetch,
|
|
6370
6664
|
localNetworkFetch,
|
|
6665
|
+
maxToken,
|
|
6371
6666
|
resolveTargetAddressSpace,
|
|
6372
6667
|
version
|
|
6373
6668
|
});
|