@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.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,10 +2246,13 @@ 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
|
}
|
|
2253
|
+
if (this._identity.orderByIndex !== void 0) {
|
|
2254
|
+
message.orderByIndex = this._identity.orderByIndex;
|
|
2255
|
+
}
|
|
2120
2256
|
} else {
|
|
2121
2257
|
message.target = this._identity.target;
|
|
2122
2258
|
if (this._identity.filter !== void 0) {
|
|
@@ -2129,8 +2265,30 @@ var TableSubscription = class {
|
|
|
2129
2265
|
if (this._conflate !== void 0) {
|
|
2130
2266
|
message.conflate = this._conflate;
|
|
2131
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
|
+
}
|
|
2132
2278
|
await this._transport.send(message);
|
|
2133
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
|
+
}
|
|
2134
2292
|
_handleMessage(message) {
|
|
2135
2293
|
if (!this._active) {
|
|
2136
2294
|
return;
|
|
@@ -2157,6 +2315,7 @@ var TableSubscription = class {
|
|
|
2157
2315
|
}
|
|
2158
2316
|
_handleSnapshotPage(message) {
|
|
2159
2317
|
this._pendingSnapshotRows.push(...message.rows);
|
|
2318
|
+
this._observeToken(message.token);
|
|
2160
2319
|
}
|
|
2161
2320
|
_handleSnapshotComplete(message) {
|
|
2162
2321
|
this._lastVersion = message.version;
|
|
@@ -2165,12 +2324,20 @@ var TableSubscription = class {
|
|
|
2165
2324
|
}
|
|
2166
2325
|
const rows = this._pendingSnapshotRows;
|
|
2167
2326
|
this._pendingSnapshotRows = [];
|
|
2168
|
-
this._onSnapshot?.(rows, message.version);
|
|
2169
|
-
|
|
2327
|
+
this._onSnapshot?.(rows, message.version, message.total_matches);
|
|
2328
|
+
const snapshot = {
|
|
2170
2329
|
type: "snapshot",
|
|
2171
2330
|
rows,
|
|
2172
2331
|
version: message.version
|
|
2173
|
-
}
|
|
2332
|
+
};
|
|
2333
|
+
if (message.total_matches !== void 0) {
|
|
2334
|
+
snapshot.totalMatches = message.total_matches;
|
|
2335
|
+
}
|
|
2336
|
+
if (message.token !== void 0) {
|
|
2337
|
+
snapshot.token = message.token;
|
|
2338
|
+
this._observeToken(message.token);
|
|
2339
|
+
}
|
|
2340
|
+
this._queue.push(snapshot);
|
|
2174
2341
|
}
|
|
2175
2342
|
async _handleGap(message) {
|
|
2176
2343
|
this._pendingSnapshotRows = [];
|
|
@@ -2195,6 +2362,10 @@ var TableSubscription = class {
|
|
|
2195
2362
|
if (message.values_skipped !== void 0) {
|
|
2196
2363
|
event.values_skipped = message.values_skipped;
|
|
2197
2364
|
}
|
|
2365
|
+
if (message.token !== void 0) {
|
|
2366
|
+
event.token = message.token;
|
|
2367
|
+
this._observeToken(message.token);
|
|
2368
|
+
}
|
|
2198
2369
|
this._onChange?.(event);
|
|
2199
2370
|
this._queue.push(event);
|
|
2200
2371
|
}
|
|
@@ -2539,11 +2710,12 @@ var TableQuery = class _TableQuery {
|
|
|
2539
2710
|
* @param state - Optional initial state (used for immutable chaining).
|
|
2540
2711
|
* @internal Use `client.table()` to create queries.
|
|
2541
2712
|
*/
|
|
2542
|
-
constructor(transport, tableName, database, state, getWebSocketTransport) {
|
|
2713
|
+
constructor(transport, tableName, database, state, getWebSocketTransport, store) {
|
|
2543
2714
|
this.transport = transport;
|
|
2544
2715
|
this.tableName = tableName;
|
|
2545
2716
|
this.database = database;
|
|
2546
2717
|
this.getWebSocketTransport = getWebSocketTransport;
|
|
2718
|
+
this.store = store;
|
|
2547
2719
|
this.state = state ?? {
|
|
2548
2720
|
predicates: [],
|
|
2549
2721
|
groupClauses: [],
|
|
@@ -2559,6 +2731,16 @@ var TableQuery = class _TableQuery {
|
|
|
2559
2731
|
isDistinct: false
|
|
2560
2732
|
};
|
|
2561
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
|
+
}
|
|
2562
2744
|
where(column, operator, value) {
|
|
2563
2745
|
const newPredicates = buildWherePredicates(column, operator, value);
|
|
2564
2746
|
return new _TableQuery(
|
|
@@ -2569,7 +2751,8 @@ var TableQuery = class _TableQuery {
|
|
|
2569
2751
|
...this.state,
|
|
2570
2752
|
predicates: [...this.state.predicates, ...newPredicates]
|
|
2571
2753
|
},
|
|
2572
|
-
this.getWebSocketTransport
|
|
2754
|
+
this.getWebSocketTransport,
|
|
2755
|
+
this.store
|
|
2573
2756
|
);
|
|
2574
2757
|
}
|
|
2575
2758
|
/**
|
|
@@ -2588,7 +2771,7 @@ var TableQuery = class _TableQuery {
|
|
|
2588
2771
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2589
2772
|
...this.state,
|
|
2590
2773
|
groupClauses: [...this.state.groupClauses, sub]
|
|
2591
|
-
}, this.getWebSocketTransport);
|
|
2774
|
+
}, this.getWebSocketTransport, this.store);
|
|
2592
2775
|
}
|
|
2593
2776
|
/**
|
|
2594
2777
|
* Sets the primary sort column for the query.
|
|
@@ -2613,7 +2796,7 @@ var TableQuery = class _TableQuery {
|
|
|
2613
2796
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2614
2797
|
...this.state,
|
|
2615
2798
|
orderByClauses: [orderByClause]
|
|
2616
|
-
}, this.getWebSocketTransport);
|
|
2799
|
+
}, this.getWebSocketTransport, this.store);
|
|
2617
2800
|
}
|
|
2618
2801
|
/**
|
|
2619
2802
|
* Sets the primary sort column to descending order.
|
|
@@ -2659,7 +2842,7 @@ var TableQuery = class _TableQuery {
|
|
|
2659
2842
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2660
2843
|
...this.state,
|
|
2661
2844
|
orderByClauses: [...this.state.orderByClauses, orderByClause]
|
|
2662
|
-
}, this.getWebSocketTransport);
|
|
2845
|
+
}, this.getWebSocketTransport, this.store);
|
|
2663
2846
|
}
|
|
2664
2847
|
/**
|
|
2665
2848
|
* Sets the maximum number of rows to return.
|
|
@@ -2676,7 +2859,7 @@ var TableQuery = class _TableQuery {
|
|
|
2676
2859
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2677
2860
|
...this.state,
|
|
2678
2861
|
limitValue: count
|
|
2679
|
-
}, this.getWebSocketTransport);
|
|
2862
|
+
}, this.getWebSocketTransport, this.store);
|
|
2680
2863
|
}
|
|
2681
2864
|
/**
|
|
2682
2865
|
* Sets the number of rows to skip.
|
|
@@ -2693,7 +2876,7 @@ var TableQuery = class _TableQuery {
|
|
|
2693
2876
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2694
2877
|
...this.state,
|
|
2695
2878
|
offsetValue: count
|
|
2696
|
-
}, this.getWebSocketTransport);
|
|
2879
|
+
}, this.getWebSocketTransport, this.store);
|
|
2697
2880
|
}
|
|
2698
2881
|
/**
|
|
2699
2882
|
* Requests cross-partition access for this query.
|
|
@@ -2708,10 +2891,21 @@ var TableQuery = class _TableQuery {
|
|
|
2708
2891
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2709
2892
|
...this.state,
|
|
2710
2893
|
crossPartitionAccess: true
|
|
2711
|
-
}, this.getWebSocketTransport);
|
|
2894
|
+
}, this.getWebSocketTransport, this.store);
|
|
2895
|
+
}
|
|
2896
|
+
/**
|
|
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 });
|
|
2712
2906
|
}
|
|
2713
2907
|
/**
|
|
2714
|
-
*
|
|
2908
|
+
* Selects specific columns to return.
|
|
2715
2909
|
* If not called, all columns are returned.
|
|
2716
2910
|
*
|
|
2717
2911
|
* When T is a specific row type, only keys of T are accepted as column names.
|
|
@@ -2733,7 +2927,7 @@ var TableQuery = class _TableQuery {
|
|
|
2733
2927
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2734
2928
|
...this.state,
|
|
2735
2929
|
selectColumns: columns.length > 0 ? columns : null
|
|
2736
|
-
}, this.getWebSocketTransport);
|
|
2930
|
+
}, this.getWebSocketTransport, this.store);
|
|
2737
2931
|
}
|
|
2738
2932
|
/**
|
|
2739
2933
|
* Return only distinct (de-duplicated) rows for the given columns — SQL `SELECT DISTINCT`.
|
|
@@ -2763,7 +2957,7 @@ var TableQuery = class _TableQuery {
|
|
|
2763
2957
|
...this.state,
|
|
2764
2958
|
selectColumns: columns,
|
|
2765
2959
|
isDistinct: true
|
|
2766
|
-
}, this.getWebSocketTransport);
|
|
2960
|
+
}, this.getWebSocketTransport, this.store);
|
|
2767
2961
|
}
|
|
2768
2962
|
/**
|
|
2769
2963
|
* Adds server-side computed columns to the query result.
|
|
@@ -2792,7 +2986,7 @@ var TableQuery = class _TableQuery {
|
|
|
2792
2986
|
return new _TableQuery(this.transport, this.tableName, this.database, {
|
|
2793
2987
|
...this.state,
|
|
2794
2988
|
selectExprs: projections
|
|
2795
|
-
}, this.getWebSocketTransport);
|
|
2989
|
+
}, this.getWebSocketTransport, this.store);
|
|
2796
2990
|
}
|
|
2797
2991
|
join(rightTable, leftColumnOrColumns, rightColumnOrColumns) {
|
|
2798
2992
|
return this.addJoinClause(
|
|
@@ -2850,7 +3044,8 @@ var TableQuery = class _TableQuery {
|
|
|
2850
3044
|
}
|
|
2851
3045
|
]
|
|
2852
3046
|
},
|
|
2853
|
-
this.getWebSocketTransport
|
|
3047
|
+
this.getWebSocketTransport,
|
|
3048
|
+
this.store
|
|
2854
3049
|
);
|
|
2855
3050
|
}
|
|
2856
3051
|
/**
|
|
@@ -2886,7 +3081,8 @@ var TableQuery = class _TableQuery {
|
|
|
2886
3081
|
...this.state,
|
|
2887
3082
|
groupByColumns: [...columns]
|
|
2888
3083
|
},
|
|
2889
|
-
this.getWebSocketTransport
|
|
3084
|
+
this.getWebSocketTransport,
|
|
3085
|
+
this.store
|
|
2890
3086
|
);
|
|
2891
3087
|
}
|
|
2892
3088
|
/**
|
|
@@ -2920,8 +3116,11 @@ var TableQuery = class _TableQuery {
|
|
|
2920
3116
|
onSnapshot: options.onSnapshot,
|
|
2921
3117
|
onChange: options.onChange,
|
|
2922
3118
|
onError: options.onError,
|
|
2923
|
-
conflate: options.conflate
|
|
2924
|
-
|
|
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);
|
|
2925
3124
|
subscription.start();
|
|
2926
3125
|
return subscription;
|
|
2927
3126
|
}
|
|
@@ -3036,7 +3235,8 @@ var TableQuery = class _TableQuery {
|
|
|
3036
3235
|
...this.state,
|
|
3037
3236
|
joinClauses: [...this.state.joinClauses, joinClause]
|
|
3038
3237
|
},
|
|
3039
|
-
this.getWebSocketTransport
|
|
3238
|
+
this.getWebSocketTransport,
|
|
3239
|
+
this.store
|
|
3040
3240
|
);
|
|
3041
3241
|
}
|
|
3042
3242
|
addAggregate(op, column) {
|
|
@@ -3057,7 +3257,8 @@ var TableQuery = class _TableQuery {
|
|
|
3057
3257
|
}
|
|
3058
3258
|
]
|
|
3059
3259
|
},
|
|
3060
|
-
this.getWebSocketTransport
|
|
3260
|
+
this.getWebSocketTransport,
|
|
3261
|
+
this.store
|
|
3061
3262
|
);
|
|
3062
3263
|
}
|
|
3063
3264
|
requireWebSocketTransport() {
|
|
@@ -3087,17 +3288,23 @@ var TableQuery = class _TableQuery {
|
|
|
3087
3288
|
* ```
|
|
3088
3289
|
*/
|
|
3089
3290
|
async execute() {
|
|
3291
|
+
if (this.state.atLeast) {
|
|
3292
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3293
|
+
}
|
|
3090
3294
|
const request = this.buildRequest();
|
|
3091
3295
|
const path = `${databasePath2(this.database)}/query`;
|
|
3092
3296
|
const response = await this.transport.post(path, request);
|
|
3093
3297
|
const rows = columnarToRows(response);
|
|
3094
3298
|
const stats = response.stats;
|
|
3095
|
-
return { rows, stats };
|
|
3299
|
+
return { rows, stats, token: response.token };
|
|
3096
3300
|
}
|
|
3097
3301
|
/**
|
|
3098
3302
|
* Executes the query and returns the raw columnar JSON payload (no row-object conversion).
|
|
3099
3303
|
*/
|
|
3100
3304
|
async toColumnar() {
|
|
3305
|
+
if (this.state.atLeast) {
|
|
3306
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3307
|
+
}
|
|
3101
3308
|
const request = this.buildRequest();
|
|
3102
3309
|
const path = `${databasePath2(this.database)}/query`;
|
|
3103
3310
|
return this.transport.post(path, request);
|
|
@@ -3127,8 +3334,12 @@ var TableQuery = class _TableQuery {
|
|
|
3127
3334
|
limitValue: 0,
|
|
3128
3335
|
selectColumns: []
|
|
3129
3336
|
},
|
|
3130
|
-
this.getWebSocketTransport
|
|
3337
|
+
this.getWebSocketTransport,
|
|
3338
|
+
this.store
|
|
3131
3339
|
);
|
|
3340
|
+
if (this.state.atLeast) {
|
|
3341
|
+
this.store?.observe(this.database, this.state.atLeast);
|
|
3342
|
+
}
|
|
3132
3343
|
const request = countQuery.buildRequest();
|
|
3133
3344
|
const path = `${databasePath2(this.database)}/query`;
|
|
3134
3345
|
const response = await this.transport.post(path, request);
|
|
@@ -3175,7 +3386,8 @@ var TableQuery = class _TableQuery {
|
|
|
3175
3386
|
const response = await this.transport.post(path, body);
|
|
3176
3387
|
const result = {
|
|
3177
3388
|
rowsInserted: response.rowsInserted,
|
|
3178
|
-
executionMs: response.executionMs
|
|
3389
|
+
executionMs: response.executionMs,
|
|
3390
|
+
token: response.token
|
|
3179
3391
|
};
|
|
3180
3392
|
if (response.generatedValues !== void 0) {
|
|
3181
3393
|
result.generatedValues = response.generatedValues;
|
|
@@ -3225,7 +3437,8 @@ var TableQuery = class _TableQuery {
|
|
|
3225
3437
|
const response = await this.transport.post(path, body);
|
|
3226
3438
|
const result = {
|
|
3227
3439
|
rowsInserted: response.rowsInserted,
|
|
3228
|
-
executionMs: response.executionMs
|
|
3440
|
+
executionMs: response.executionMs,
|
|
3441
|
+
token: response.token
|
|
3229
3442
|
};
|
|
3230
3443
|
if (response.generatedValues !== void 0) {
|
|
3231
3444
|
result.generatedValues = response.generatedValues;
|
|
@@ -3277,6 +3490,7 @@ var TableQuery = class _TableQuery {
|
|
|
3277
3490
|
return {
|
|
3278
3491
|
rowsAffected: response.rowsUpdated,
|
|
3279
3492
|
executionMs: response.executionMs,
|
|
3493
|
+
token: response.token,
|
|
3280
3494
|
...response.rows ? { rows: columnarToRows(response.rows) } : {},
|
|
3281
3495
|
...response.rowsTruncated ? { rowsTruncated: true } : {}
|
|
3282
3496
|
};
|
|
@@ -3327,6 +3541,7 @@ var TableQuery = class _TableQuery {
|
|
|
3327
3541
|
rowsAffected: response.rowsDeleted,
|
|
3328
3542
|
executionMs: response.executionMs,
|
|
3329
3543
|
hasMore: response.hasMore,
|
|
3544
|
+
token: response.token,
|
|
3330
3545
|
...response.rows ? { rows: columnarToRows(response.rows) } : {},
|
|
3331
3546
|
...response.rowsTruncated ? { rowsTruncated: true } : {}
|
|
3332
3547
|
};
|
|
@@ -3346,7 +3561,8 @@ var TableQuery = class _TableQuery {
|
|
|
3346
3561
|
return {
|
|
3347
3562
|
rowsAffected: response.rowsDeleted,
|
|
3348
3563
|
executionMs: response.executionMs,
|
|
3349
|
-
hasMore: false
|
|
3564
|
+
hasMore: false,
|
|
3565
|
+
token: response.token
|
|
3350
3566
|
};
|
|
3351
3567
|
}
|
|
3352
3568
|
/**
|
|
@@ -3359,7 +3575,14 @@ var TableQuery = class _TableQuery {
|
|
|
3359
3575
|
throw new Error("batch() requires a non-empty operations array");
|
|
3360
3576
|
}
|
|
3361
3577
|
const wireOperations = operations.map((op, index) => {
|
|
3362
|
-
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
|
+
);
|
|
3363
3586
|
const scoped = op.where(base);
|
|
3364
3587
|
const where = scoped.buildWhereClause();
|
|
3365
3588
|
if (!where) {
|
|
@@ -4727,12 +4950,12 @@ function raiseDeprecationWarnings(sink, warnings) {
|
|
|
4727
4950
|
continue;
|
|
4728
4951
|
}
|
|
4729
4952
|
const sunset = warning.sunsetAt != null ? ` sunsetAt=${warning.sunsetAt}` : "";
|
|
4730
|
-
const
|
|
4953
|
+
const name = warning.name != null && warning.name.length > 0 ? ` name=${warning.name}` : "";
|
|
4731
4954
|
sink({
|
|
4732
4955
|
code: warning.code,
|
|
4733
|
-
|
|
4956
|
+
name: warning.name,
|
|
4734
4957
|
sunsetAt: warning.sunsetAt,
|
|
4735
|
-
message: `${warning.code}:${
|
|
4958
|
+
message: `${warning.code}:${name}${sunset}`.trim()
|
|
4736
4959
|
});
|
|
4737
4960
|
}
|
|
4738
4961
|
}
|
|
@@ -4745,21 +4968,31 @@ function emptyStats() {
|
|
|
4745
4968
|
};
|
|
4746
4969
|
}
|
|
4747
4970
|
var NamedQueriesApi = class {
|
|
4748
|
-
constructor(transport, database, onWarning, getStreamingTransport) {
|
|
4971
|
+
constructor(transport, database, onWarning, getStreamingTransport, store) {
|
|
4749
4972
|
this.transport = transport;
|
|
4750
4973
|
this.database = database;
|
|
4751
4974
|
this.onWarning = onWarning;
|
|
4752
4975
|
this.getStreamingTransport = getStreamingTransport;
|
|
4976
|
+
this.store = store;
|
|
4753
4977
|
}
|
|
4754
|
-
async execute(
|
|
4755
|
-
if (typeof
|
|
4756
|
-
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");
|
|
4757
4981
|
}
|
|
4758
4982
|
const prefix = databasePath2(this.database);
|
|
4759
|
-
const path = `${prefix}/named-queries/${encodeURIComponent(
|
|
4983
|
+
const path = `${prefix}/named-queries/${encodeURIComponent(name)}/query?format=columnar`;
|
|
4984
|
+
const body = {
|
|
4985
|
+
args: args ?? {}
|
|
4986
|
+
};
|
|
4987
|
+
if (options?.orderByIndex !== void 0) {
|
|
4988
|
+
body.orderByIndex = options.orderByIndex;
|
|
4989
|
+
}
|
|
4990
|
+
if (options?.atLeast !== void 0) {
|
|
4991
|
+
this.store?.observe(this.database, options.atLeast);
|
|
4992
|
+
}
|
|
4760
4993
|
const response = await this.transport.post(
|
|
4761
4994
|
path,
|
|
4762
|
-
|
|
4995
|
+
body,
|
|
4763
4996
|
{ signal: options?.signal }
|
|
4764
4997
|
);
|
|
4765
4998
|
const rows = columnarToRows(response);
|
|
@@ -4767,7 +5000,9 @@ var NamedQueriesApi = class {
|
|
|
4767
5000
|
return {
|
|
4768
5001
|
rows,
|
|
4769
5002
|
stats: response.stats,
|
|
4770
|
-
warnings: response.warnings
|
|
5003
|
+
warnings: response.warnings,
|
|
5004
|
+
totalMatches: response.totalMatches,
|
|
5005
|
+
token: response.token
|
|
4771
5006
|
};
|
|
4772
5007
|
}
|
|
4773
5008
|
async batch(items, options) {
|
|
@@ -4785,6 +5020,9 @@ var NamedQueriesApi = class {
|
|
|
4785
5020
|
400
|
|
4786
5021
|
);
|
|
4787
5022
|
}
|
|
5023
|
+
if (options?.atLeast !== void 0) {
|
|
5024
|
+
this.store?.observe(this.database, options.atLeast);
|
|
5025
|
+
}
|
|
4788
5026
|
const prefix = databasePath2(this.database);
|
|
4789
5027
|
const path = `${prefix}/named-queries/batch?format=columnar`;
|
|
4790
5028
|
const envelope = await this.transport.post(
|
|
@@ -4806,33 +5044,42 @@ var NamedQueriesApi = class {
|
|
|
4806
5044
|
data: slot.data ?? [],
|
|
4807
5045
|
rowCount: slot.rowCount ?? 0,
|
|
4808
5046
|
stats: slot.stats ?? emptyStats(),
|
|
4809
|
-
warnings: slot.warnings
|
|
5047
|
+
warnings: slot.warnings,
|
|
5048
|
+
totalMatches: slot.totalMatches,
|
|
5049
|
+
token: slot.token
|
|
4810
5050
|
};
|
|
4811
5051
|
const result = {
|
|
4812
5052
|
rows: columnarToRows(columnar),
|
|
4813
5053
|
stats: columnar.stats,
|
|
4814
|
-
warnings: slot.warnings
|
|
5054
|
+
warnings: slot.warnings,
|
|
5055
|
+
totalMatches: slot.totalMatches,
|
|
5056
|
+
token: slot.token
|
|
4815
5057
|
};
|
|
4816
5058
|
raiseDeprecationWarnings(this.onWarning, slot.warnings);
|
|
4817
5059
|
return { isError: false, result };
|
|
4818
5060
|
});
|
|
4819
5061
|
}
|
|
4820
|
-
subscribe(
|
|
4821
|
-
if (typeof
|
|
4822
|
-
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");
|
|
4823
5065
|
}
|
|
4824
5066
|
const subscription = new TableSubscription(
|
|
4825
5067
|
this.getStreamingTransport(),
|
|
4826
|
-
{ kind: "named",
|
|
5068
|
+
{ kind: "named", name, args, orderByIndex: options.orderByIndex },
|
|
4827
5069
|
{
|
|
4828
5070
|
onSnapshot: options.onSnapshot,
|
|
4829
5071
|
onChange: options.onChange,
|
|
4830
5072
|
onError: options.onError,
|
|
4831
|
-
conflate: options.conflate
|
|
5073
|
+
conflate: options.conflate,
|
|
5074
|
+
atLeast: options.atLeast,
|
|
5075
|
+
waitMs: options.waitMs,
|
|
5076
|
+
onExceeded: options.onExceeded
|
|
4832
5077
|
},
|
|
4833
5078
|
(warnings) => {
|
|
4834
5079
|
raiseDeprecationWarnings(this.onWarning, warnings);
|
|
4835
|
-
}
|
|
5080
|
+
},
|
|
5081
|
+
this.store,
|
|
5082
|
+
this.database
|
|
4836
5083
|
);
|
|
4837
5084
|
subscription.start();
|
|
4838
5085
|
return subscription;
|
|
@@ -4844,12 +5091,12 @@ var NamedMutationsApi = class {
|
|
|
4844
5091
|
this.database = database;
|
|
4845
5092
|
this.onWarning = onWarning;
|
|
4846
5093
|
}
|
|
4847
|
-
async execute(
|
|
4848
|
-
if (typeof
|
|
4849
|
-
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");
|
|
4850
5097
|
}
|
|
4851
5098
|
const prefix = databasePath2(this.database);
|
|
4852
|
-
const path = `${prefix}/named-mutations/${encodeURIComponent(
|
|
5099
|
+
const path = `${prefix}/named-mutations/${encodeURIComponent(name)}/execute`;
|
|
4853
5100
|
const wire = await this.transport.post(path, {
|
|
4854
5101
|
args: args ?? {}
|
|
4855
5102
|
});
|
|
@@ -4910,6 +5157,7 @@ var WebSocketTransport = class {
|
|
|
4910
5157
|
// Serialized-send queue: each send appends to this tail.
|
|
4911
5158
|
this._sendTail = Promise.resolve();
|
|
4912
5159
|
this._lastVersion = 0;
|
|
5160
|
+
this._lastToken = null;
|
|
4913
5161
|
this._reconnectAttempt = 0;
|
|
4914
5162
|
this._disposed = false;
|
|
4915
5163
|
this._missedPings = 0;
|
|
@@ -4927,6 +5175,7 @@ var WebSocketTransport = class {
|
|
|
4927
5175
|
this._pingIntervalMs = options.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS;
|
|
4928
5176
|
this._maxMissedHeartbeats = options.maxMissedHeartbeats ?? DEFAULT_MAX_MISSED_HEARTBEATS;
|
|
4929
5177
|
this._enableCompression = options.enableCompression ?? true;
|
|
5178
|
+
this._store = options.consistencyTokenStore;
|
|
4930
5179
|
this._wireMode = options.wireMode ?? "json";
|
|
4931
5180
|
this._authHandler?.setOnAccessTokenRefreshed((token) => {
|
|
4932
5181
|
if (this._handshakeComplete && this._ws?.readyState === WS_READY_STATE_OPEN) {
|
|
@@ -4935,10 +5184,14 @@ var WebSocketTransport = class {
|
|
|
4935
5184
|
});
|
|
4936
5185
|
}
|
|
4937
5186
|
// ─── Public API ────────────────────────────────────────────────────────────
|
|
4938
|
-
/** Latest
|
|
5187
|
+
/** Latest change-event sequence from the most recent server `heartbeat` message. */
|
|
4939
5188
|
get lastVersion() {
|
|
4940
5189
|
return this._lastVersion;
|
|
4941
5190
|
}
|
|
5191
|
+
/** Consistency token from the most recent server `heartbeat` (ADR 0042 D-13). */
|
|
5192
|
+
get lastToken() {
|
|
5193
|
+
return this._lastToken;
|
|
5194
|
+
}
|
|
4942
5195
|
/**
|
|
4943
5196
|
* Registers a handler for incoming server messages with the given channel id.
|
|
4944
5197
|
* Use `"__global__"` to receive broadcast messages that carry no `id`.
|
|
@@ -5126,6 +5379,10 @@ var WebSocketTransport = class {
|
|
|
5126
5379
|
}
|
|
5127
5380
|
case "heartbeat":
|
|
5128
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
|
+
}
|
|
5129
5386
|
break;
|
|
5130
5387
|
case "pong":
|
|
5131
5388
|
this._missedPings = 0;
|
|
@@ -5291,16 +5548,21 @@ var LongPollTransport = class {
|
|
|
5291
5548
|
this._connected = false;
|
|
5292
5549
|
this._pollTask = null;
|
|
5293
5550
|
this._lastVersion = 0;
|
|
5551
|
+
this._lastToken = null;
|
|
5294
5552
|
this._serverUrl = serverUrl;
|
|
5295
5553
|
this._database = database;
|
|
5296
5554
|
this._authHandler = options.authHandler;
|
|
5297
5555
|
this._onReconnected = options.onReconnected;
|
|
5298
5556
|
this._waitMs = Math.max(1, options.waitMs ?? DEFAULT_WAIT_MS);
|
|
5299
5557
|
this._fetch = options.fetchImpl ?? localNetworkFetch;
|
|
5558
|
+
this._store = options.consistencyTokenStore;
|
|
5300
5559
|
}
|
|
5301
5560
|
get lastVersion() {
|
|
5302
5561
|
return this._lastVersion;
|
|
5303
5562
|
}
|
|
5563
|
+
get lastToken() {
|
|
5564
|
+
return this._lastToken;
|
|
5565
|
+
}
|
|
5304
5566
|
registerHandler(id, handler) {
|
|
5305
5567
|
this._handlers.set(id, handler);
|
|
5306
5568
|
}
|
|
@@ -5423,6 +5685,10 @@ var LongPollTransport = class {
|
|
|
5423
5685
|
for (const msg of payload.messages) {
|
|
5424
5686
|
if (msg.type === "heartbeat") {
|
|
5425
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
|
+
}
|
|
5426
5692
|
}
|
|
5427
5693
|
const id = "id" in msg ? msg.id : void 0;
|
|
5428
5694
|
if (id !== void 0 && id !== null) {
|
|
@@ -5502,6 +5768,9 @@ var FallbackStreamingTransport = class {
|
|
|
5502
5768
|
get lastVersion() {
|
|
5503
5769
|
return this._active.lastVersion;
|
|
5504
5770
|
}
|
|
5771
|
+
get lastToken() {
|
|
5772
|
+
return this._active.lastToken;
|
|
5773
|
+
}
|
|
5505
5774
|
registerHandler(id, handler) {
|
|
5506
5775
|
this._handlers.set(id, handler);
|
|
5507
5776
|
this._active.registerHandler(id, handler);
|
|
@@ -5581,6 +5850,7 @@ var AoudaClient = class {
|
|
|
5581
5850
|
this.baseUrl = normalizeBaseUrl(options.serverUrl);
|
|
5582
5851
|
this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
5583
5852
|
this.database = options.database.trim();
|
|
5853
|
+
this._store = options.consistencyTokenStore ?? new MemoryConsistencyTokenStore();
|
|
5584
5854
|
if (!Number.isFinite(this.timeout) || this.timeout <= 0) {
|
|
5585
5855
|
throw new Error("timeout must be a finite positive number");
|
|
5586
5856
|
}
|
|
@@ -5615,7 +5885,9 @@ var AoudaClient = class {
|
|
|
5615
5885
|
}
|
|
5616
5886
|
const httpTransport = new HttpTransport({
|
|
5617
5887
|
baseUrl: this.baseUrl,
|
|
5618
|
-
timeout: this.timeout
|
|
5888
|
+
timeout: this.timeout,
|
|
5889
|
+
database: this.database,
|
|
5890
|
+
consistencyTokenStore: this._store
|
|
5619
5891
|
});
|
|
5620
5892
|
const activeAuth = options.serverAuth ?? options.appAuth;
|
|
5621
5893
|
if (activeAuth) {
|
|
@@ -5675,7 +5947,8 @@ var AoudaClient = class {
|
|
|
5675
5947
|
this.transport,
|
|
5676
5948
|
this.database,
|
|
5677
5949
|
onNamedArtifactWarning,
|
|
5678
|
-
() => this._getOrCreateWebSocketTransport()
|
|
5950
|
+
() => this._getOrCreateWebSocketTransport(),
|
|
5951
|
+
this._store
|
|
5679
5952
|
);
|
|
5680
5953
|
this._namedMutations = new NamedMutationsApi(
|
|
5681
5954
|
this.transport,
|
|
@@ -5774,7 +6047,8 @@ var AoudaClient = class {
|
|
|
5774
6047
|
name,
|
|
5775
6048
|
this.database,
|
|
5776
6049
|
void 0,
|
|
5777
|
-
() => this._getOrCreateWebSocketTransport()
|
|
6050
|
+
() => this._getOrCreateWebSocketTransport(),
|
|
6051
|
+
this._store
|
|
5778
6052
|
);
|
|
5779
6053
|
}
|
|
5780
6054
|
/**
|
|
@@ -5826,13 +6100,26 @@ var AoudaClient = class {
|
|
|
5826
6100
|
return this._materializedQueries;
|
|
5827
6101
|
}
|
|
5828
6102
|
/**
|
|
5829
|
-
*
|
|
6103
|
+
* Named-query execute, read-only batch, and subscribe by unique schema name.
|
|
5830
6104
|
*/
|
|
5831
6105
|
get namedQueries() {
|
|
5832
6106
|
return this._namedQueries;
|
|
5833
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
|
+
}
|
|
5834
6121
|
/**
|
|
5835
|
-
*
|
|
6122
|
+
* Named-mutation execute by unique schema name. No batch.
|
|
5836
6123
|
*/
|
|
5837
6124
|
get namedMutations() {
|
|
5838
6125
|
return this._namedMutations;
|
|
@@ -5959,13 +6246,15 @@ var AoudaClient = class {
|
|
|
5959
6246
|
const primary = new WebSocketTransport(this.baseUrl, this.database, {
|
|
5960
6247
|
authHandler: this._authHandler,
|
|
5961
6248
|
enableCompression: this._streamingEnableCompression,
|
|
5962
|
-
wireMode: this._streamingWireMode
|
|
6249
|
+
wireMode: this._streamingWireMode,
|
|
6250
|
+
consistencyTokenStore: this._store
|
|
5963
6251
|
});
|
|
5964
6252
|
if (this._streamingEnableLongPollFallback) {
|
|
5965
6253
|
this._wsTransport = new FallbackStreamingTransport(primary, () => {
|
|
5966
6254
|
return new LongPollTransport(this.baseUrl, this.database, {
|
|
5967
6255
|
authHandler: this._authHandler,
|
|
5968
|
-
waitMs: this._streamingLongPollWaitMs
|
|
6256
|
+
waitMs: this._streamingLongPollWaitMs,
|
|
6257
|
+
consistencyTokenStore: this._store
|
|
5969
6258
|
});
|
|
5970
6259
|
});
|
|
5971
6260
|
} else {
|
|
@@ -6262,6 +6551,7 @@ export {
|
|
|
6262
6551
|
MaterializedQueriesApi,
|
|
6263
6552
|
MaterializedQueryState,
|
|
6264
6553
|
MaterializedQueryType,
|
|
6554
|
+
MemoryConsistencyTokenStore,
|
|
6265
6555
|
MetricsAdminApi,
|
|
6266
6556
|
NamedMutationsApi,
|
|
6267
6557
|
NamedQueriesApi,
|
|
@@ -6277,10 +6567,12 @@ export {
|
|
|
6277
6567
|
applyLocalNetworkAccess,
|
|
6278
6568
|
coerceColumnarValue,
|
|
6279
6569
|
columnarToRows,
|
|
6570
|
+
compareOrdinal,
|
|
6280
6571
|
createAoudaClient,
|
|
6281
6572
|
createAoudaClusterMcpToolSet,
|
|
6282
6573
|
installLocalNetworkFetch,
|
|
6283
6574
|
localNetworkFetch,
|
|
6575
|
+
maxToken,
|
|
6284
6576
|
resolveTargetAddressSpace,
|
|
6285
6577
|
version
|
|
6286
6578
|
};
|