@ferricstore/ferricstore 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -2
- package/dist/index.cjs +2273 -600
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +193 -30
- package/dist/index.d.ts +193 -30
- package/dist/index.js +2275 -605
- package/dist/index.js.map +1 -1
- package/docs/api/assets/hierarchy.js +1 -1
- package/docs/api/assets/navigation.js +1 -1
- package/docs/api/assets/search.js +1 -1
- package/docs/api/classes/ClaimHydrationError.html +4 -4
- package/docs/api/classes/ConnectionClosedError.html +5 -5
- package/docs/api/classes/FerricStoreClient.html +6 -2
- package/docs/api/classes/FerricStoreError.html +5 -5
- package/docs/api/classes/FlowAlreadyExistsError.html +5 -5
- package/docs/api/classes/FlowBatchError.html +5 -5
- package/docs/api/classes/FlowNotFoundError.html +5 -5
- package/docs/api/classes/FlowQueryError.html +42 -0
- package/docs/api/classes/FlowWrongStateError.html +5 -5
- package/docs/api/classes/InvalidCommandError.html +5 -5
- package/docs/api/classes/LeaseRenewalError.html +5 -5
- package/docs/api/classes/LockHeldError.html +5 -5
- package/docs/api/classes/LockNotOwnedError.html +5 -5
- package/docs/api/classes/NativeAdapter.html +3 -3
- package/docs/api/classes/OverloadedError.html +5 -5
- package/docs/api/classes/QueueCompletionError.html +5 -5
- package/docs/api/classes/RequestTimeoutError.html +5 -5
- package/docs/api/classes/RerouteError.html +5 -5
- package/docs/api/classes/StaleLeaseError.html +5 -5
- package/docs/api/classes/StalePolicyGenerationError.html +5 -5
- package/docs/api/functions/projectFlowQuery.html +1 -0
- package/docs/api/hierarchy.html +1 -1
- package/docs/api/index.html +30 -3
- package/docs/api/interfaces/AdminListOptions.html +1 -1
- package/docs/api/interfaces/CancelOptions.html +1 -1
- package/docs/api/interfaces/CompleteOptions.html +1 -1
- package/docs/api/interfaces/CompleteOutcome.html +1 -1
- package/docs/api/interfaces/CreateManyOptions.html +1 -1
- package/docs/api/interfaces/EffectCompensateOptions.html +1 -1
- package/docs/api/interfaces/EffectConfirmOptions.html +1 -1
- package/docs/api/interfaces/EffectFailOptions.html +1 -1
- package/docs/api/interfaces/EffectStatusOptions.html +1 -1
- package/docs/api/interfaces/FailOptions.html +1 -1
- package/docs/api/interfaces/FailOutcome.html +1 -1
- package/docs/api/interfaces/FerricStoreClientFromUrlOptions.html +1 -1
- package/docs/api/interfaces/FerricStoreClientOptions.html +1 -1
- package/docs/api/interfaces/FlowEventProjectionField.html +4 -0
- package/docs/api/interfaces/FlowExplainResult.html +10 -0
- package/docs/api/interfaces/FlowPolicyOptions.html +1 -1
- package/docs/api/interfaces/FlowQueryCountResult.html +7 -0
- package/docs/api/interfaces/FlowQueryErrorPosition.html +4 -0
- package/docs/api/interfaces/FlowQueryIndex.html +9 -0
- package/docs/api/interfaces/FlowQueryIndexFormat.html +7 -0
- package/docs/api/interfaces/FlowQueryIndexRegistry.html +3 -0
- package/docs/api/interfaces/FlowQueryIndexStatus.html +8 -0
- package/docs/api/interfaces/FlowQueryPage.html +3 -0
- package/docs/api/interfaces/FlowQueryQuality.html +5 -0
- package/docs/api/interfaces/FlowQueryRecordsResult.html +8 -0
- package/docs/api/interfaces/FlowQueryUsage.html +12 -0
- package/docs/api/interfaces/FlowRunProjectionField.html +4 -0
- package/docs/api/interfaces/HistoryOptions.html +2 -2
- package/docs/api/interfaces/InvocationCreateOptions.html +1 -1
- package/docs/api/interfaces/LeaseMutationOptions.html +1 -1
- package/docs/api/interfaces/LimitListOptions.html +1 -1
- package/docs/api/interfaces/MutateOptions.html +1 -1
- package/docs/api/interfaces/NamedValueMutation.html +1 -1
- package/docs/api/interfaces/ProtocolCommand.html +2 -2
- package/docs/api/interfaces/ReadOptions.html +5 -3
- package/docs/api/interfaces/ReclaimOptions.html +1 -1
- package/docs/api/interfaces/RequestContextOptions.html +1 -1
- package/docs/api/interfaces/RetryOptions.html +1 -1
- package/docs/api/interfaces/RetryOutcome.html +1 -1
- package/docs/api/interfaces/SearchOptions.html +4 -3
- package/docs/api/interfaces/StepContinueOptions.html +1 -1
- package/docs/api/interfaces/TDigestCreateOptions.html +1 -1
- package/docs/api/interfaces/TDigestMergeOptions.html +1 -1
- package/docs/api/interfaces/TransitionOptions.html +1 -1
- package/docs/api/interfaces/TransitionOutcome.html +1 -1
- package/docs/api/modules.html +1 -1
- package/docs/api/types/ConnectionRequestDisposition.html +1 -1
- package/docs/api/types/FlowProjectionField.html +1 -0
- package/docs/api/types/FlowProjectionShape.html +1 -0
- package/docs/api/types/FlowQueryInteger.html +1 -0
- package/docs/api/types/FlowQueryParameter.html +1 -0
- package/docs/api/types/FlowQueryParameters.html +1 -0
- package/docs/api/types/FlowQueryRecord.html +1 -0
- package/docs/api/types/FlowQueryResult.html +1 -0
- package/docs/api/types/ManagementPairs.html +1 -1
- package/docs/api/types/SearchStateMeta.html +1 -1
- package/docs/api/variables/COMMAND_OPCODES.html +1 -1
- package/docs/api/variables/FERRICSTORE_MINIMUM_SERVER_VERSION.html +1 -1
- package/docs/api/variables/FERRICSTORE_NATIVE_PROTOCOL_VERSION.html +1 -1
- package/docs/api/variables/FERRICSTORE_SDK_VERSION.html +1 -1
- package/docs/api/variables/FlowProjection.html +1 -0
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -1182,10 +1182,151 @@ var NativeHeartbeat = class {
|
|
|
1182
1182
|
};
|
|
1183
1183
|
|
|
1184
1184
|
// src/protocol.ts
|
|
1185
|
-
import { Buffer as
|
|
1185
|
+
import { Buffer as Buffer27 } from "buffer";
|
|
1186
1186
|
|
|
1187
|
-
// src/
|
|
1187
|
+
// src/flow-query-request.ts
|
|
1188
1188
|
import { Buffer as Buffer4 } from "buffer";
|
|
1189
|
+
var FLOW_QUERY_LANGUAGE_VERSION = "FQL1";
|
|
1190
|
+
var FLOW_QUERY_MAX_BYTES = 16 * 1024;
|
|
1191
|
+
var FLOW_QUERY_MAX_PARAMETERS = 64;
|
|
1192
|
+
var FLOW_QUERY_MAX_PARAMETER_NAME_BYTES = 128;
|
|
1193
|
+
var MIN_I64 = -(1n << 63n);
|
|
1194
|
+
var MAX_I64 = (1n << 63n) - 1n;
|
|
1195
|
+
var INDEX_ID = /^[A-Za-z0-9_.:-]{1,64}$/u;
|
|
1196
|
+
function flowQueryArgs(query, params = {}) {
|
|
1197
|
+
validateFlowQueryText(query);
|
|
1198
|
+
const entries = flowQueryParameterEntries(params);
|
|
1199
|
+
const args = ["FLOW.QUERY", FLOW_QUERY_LANGUAGE_VERSION, query];
|
|
1200
|
+
for (const [name, value] of entries) args.push(name, value);
|
|
1201
|
+
return args;
|
|
1202
|
+
}
|
|
1203
|
+
function flowQueryPayload(args) {
|
|
1204
|
+
if (args.length < 2) throw new TypeError("FLOW.QUERY requires version and query");
|
|
1205
|
+
if ((args.length - 2) % 2 !== 0) {
|
|
1206
|
+
throw new TypeError("FLOW.QUERY parameters must be name/value pairs");
|
|
1207
|
+
}
|
|
1208
|
+
const version = commandText(args[0], "FLOW.QUERY version");
|
|
1209
|
+
if (version !== FLOW_QUERY_LANGUAGE_VERSION) {
|
|
1210
|
+
throw new TypeError(`FLOW.QUERY requires version ${FLOW_QUERY_LANGUAGE_VERSION}`);
|
|
1211
|
+
}
|
|
1212
|
+
const query = commandText(args[1], "FLOW.QUERY query");
|
|
1213
|
+
validateFlowQueryText(query);
|
|
1214
|
+
const parameterCount = (args.length - 2) / 2;
|
|
1215
|
+
if (parameterCount > FLOW_QUERY_MAX_PARAMETERS) {
|
|
1216
|
+
throw new TypeError(`FLOW.QUERY accepts at most ${FLOW_QUERY_MAX_PARAMETERS} named parameters`);
|
|
1217
|
+
}
|
|
1218
|
+
const params = /* @__PURE__ */ Object.create(null);
|
|
1219
|
+
for (let index = 2; index < args.length; index += 2) {
|
|
1220
|
+
const name = commandText(args[index], "FLOW.QUERY parameter name");
|
|
1221
|
+
validateFlowQueryParameterName(name);
|
|
1222
|
+
if (Object.hasOwn(params, name)) {
|
|
1223
|
+
throw new TypeError(`FLOW.QUERY parameter ${JSON.stringify(name)} is duplicated`);
|
|
1224
|
+
}
|
|
1225
|
+
params[name] = normalizeFlowQueryParameter(args[index + 1], name);
|
|
1226
|
+
}
|
|
1227
|
+
return {
|
|
1228
|
+
version,
|
|
1229
|
+
query,
|
|
1230
|
+
...parameterCount === 0 ? {} : { params }
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
function validateFlowQueryText(query) {
|
|
1234
|
+
if (typeof query !== "string") throw new TypeError("FLOW.QUERY query must be text");
|
|
1235
|
+
if (query.trim().length === 0) throw new TypeError("FLOW.QUERY query must not be empty");
|
|
1236
|
+
validateUnicodeScalarText(query, "FLOW.QUERY query");
|
|
1237
|
+
if (Buffer4.byteLength(query, "utf8") > FLOW_QUERY_MAX_BYTES) {
|
|
1238
|
+
throw new TypeError(`FLOW.QUERY query exceeds ${FLOW_QUERY_MAX_BYTES} bytes`);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
function validateFlowQueryIndexId(indexId) {
|
|
1242
|
+
if (typeof indexId !== "string" || !INDEX_ID.test(indexId)) {
|
|
1243
|
+
throw new TypeError(
|
|
1244
|
+
"query index id must be 1..64 ASCII letters, digits, '_', '-', ':', or '.'"
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
function hasFlowExplainPrefix(query) {
|
|
1249
|
+
const source = query.trimStart();
|
|
1250
|
+
const prefix = source.slice(0, 7);
|
|
1251
|
+
return prefix.toUpperCase() === "EXPLAIN" && (source.length === 7 || /[\t\n\r ]/u.test(source[7] ?? ""));
|
|
1252
|
+
}
|
|
1253
|
+
function flowQueryParameterEntries(params) {
|
|
1254
|
+
if (typeof params !== "object" || params == null || Array.isArray(params)) {
|
|
1255
|
+
throw new TypeError("FLOW.QUERY params must be a plain object");
|
|
1256
|
+
}
|
|
1257
|
+
const prototype = Object.getPrototypeOf(params);
|
|
1258
|
+
if (prototype !== null && prototype !== Object.prototype) {
|
|
1259
|
+
throw new TypeError("FLOW.QUERY params must be a plain object");
|
|
1260
|
+
}
|
|
1261
|
+
const keys = Reflect.ownKeys(params);
|
|
1262
|
+
if (keys.some((key) => typeof key !== "string")) {
|
|
1263
|
+
throw new TypeError("FLOW.QUERY parameter names must be strings");
|
|
1264
|
+
}
|
|
1265
|
+
if (keys.length > FLOW_QUERY_MAX_PARAMETERS) {
|
|
1266
|
+
throw new TypeError(`FLOW.QUERY accepts at most ${FLOW_QUERY_MAX_PARAMETERS} named parameters`);
|
|
1267
|
+
}
|
|
1268
|
+
const names = keys.sort();
|
|
1269
|
+
return names.map((name) => {
|
|
1270
|
+
validateFlowQueryParameterName(name);
|
|
1271
|
+
return [name, normalizeFlowQueryParameter(params[name], name)];
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
function validateFlowQueryParameterName(name) {
|
|
1275
|
+
validateUnicodeScalarText(name, "FLOW.QUERY parameter name");
|
|
1276
|
+
const size = Buffer4.byteLength(name, "utf8");
|
|
1277
|
+
if (size === 0 || size > FLOW_QUERY_MAX_PARAMETER_NAME_BYTES) {
|
|
1278
|
+
throw new TypeError(
|
|
1279
|
+
`FLOW.QUERY parameter names must be 1..${FLOW_QUERY_MAX_PARAMETER_NAME_BYTES} bytes`
|
|
1280
|
+
);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
function normalizeFlowQueryParameter(value, name) {
|
|
1284
|
+
if (typeof value === "string") {
|
|
1285
|
+
validateUnicodeScalarText(value, `FLOW.QUERY parameter ${JSON.stringify(name)}`);
|
|
1286
|
+
return value;
|
|
1287
|
+
}
|
|
1288
|
+
if (Buffer4.isBuffer(value)) return value;
|
|
1289
|
+
if (value instanceof Uint8Array) return Buffer4.from(value);
|
|
1290
|
+
if (typeof value === "boolean") return value;
|
|
1291
|
+
if (typeof value === "bigint" && value >= MIN_I64 && value <= MAX_I64) return value;
|
|
1292
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1293
|
+
if (!Number.isInteger(value) || Number.isSafeInteger(value)) return value;
|
|
1294
|
+
}
|
|
1295
|
+
throw new TypeError(
|
|
1296
|
+
`FLOW.QUERY parameter ${JSON.stringify(name)} must be text, bytes, boolean, a finite float, or a signed 64-bit integer`
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
function commandText(value, context) {
|
|
1300
|
+
if (typeof value === "string") {
|
|
1301
|
+
validateUnicodeScalarText(value, context);
|
|
1302
|
+
return value;
|
|
1303
|
+
}
|
|
1304
|
+
if (Buffer4.isBuffer(value) || value instanceof Uint8Array) {
|
|
1305
|
+
try {
|
|
1306
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
1307
|
+
} catch (error) {
|
|
1308
|
+
throw new TypeError(`${context} must be valid UTF-8`, { cause: error });
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
throw new TypeError(`${context} must be text`);
|
|
1312
|
+
}
|
|
1313
|
+
function validateUnicodeScalarText(value, context) {
|
|
1314
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1315
|
+
const code = value.charCodeAt(index);
|
|
1316
|
+
if (code >= 55296 && code <= 56319) {
|
|
1317
|
+
const low = value.charCodeAt(index + 1);
|
|
1318
|
+
if (!(low >= 56320 && low <= 57343)) {
|
|
1319
|
+
throw new TypeError(`${context} must be valid UTF-8`);
|
|
1320
|
+
}
|
|
1321
|
+
index += 1;
|
|
1322
|
+
} else if (code >= 56320 && code <= 57343) {
|
|
1323
|
+
throw new TypeError(`${context} must be valid UTF-8`);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/command-grammar.ts
|
|
1329
|
+
import { Buffer as Buffer5 } from "buffer";
|
|
1189
1330
|
|
|
1190
1331
|
// src/command-metadata-flow.ts
|
|
1191
1332
|
var flowStateIdCommands = /* @__PURE__ */ new Set([
|
|
@@ -1576,20 +1717,15 @@ var typeScopedFlowCommands = /* @__PURE__ */ new Set([
|
|
|
1576
1717
|
"FLOW.ATTRIBUTE_VALUES",
|
|
1577
1718
|
"FLOW.ATTRIBUTES",
|
|
1578
1719
|
"FLOW.BUDGET.LIST",
|
|
1579
|
-
"FLOW.FAILURES",
|
|
1580
1720
|
"FLOW.GOVERNANCE.OVERVIEW",
|
|
1581
1721
|
"FLOW.INFO",
|
|
1582
1722
|
"FLOW.LIMIT.LIST",
|
|
1583
|
-
"FLOW.LIST",
|
|
1584
1723
|
"FLOW.POLICY.GET",
|
|
1585
1724
|
"FLOW.POLICY.SET",
|
|
1586
1725
|
"FLOW.RETENTION_CLEANUP",
|
|
1587
1726
|
"FLOW.SCHEDULE.FIRE_DUE",
|
|
1588
1727
|
"FLOW.SCHEDULE.LIST",
|
|
1589
|
-
"FLOW.
|
|
1590
|
-
"FLOW.STATS",
|
|
1591
|
-
"FLOW.STUCK",
|
|
1592
|
-
"FLOW.TERMINALS"
|
|
1728
|
+
"FLOW.STATS"
|
|
1593
1729
|
]);
|
|
1594
1730
|
var flowScheduleCommands = /* @__PURE__ */ new Set([
|
|
1595
1731
|
"FLOW.SCHEDULE.CREATE",
|
|
@@ -1632,8 +1768,8 @@ var secondKeySubcommands = /* @__PURE__ */ new Map([
|
|
|
1632
1768
|
]);
|
|
1633
1769
|
function commandToken(value) {
|
|
1634
1770
|
if (typeof value === "string") return value.toUpperCase();
|
|
1635
|
-
if (
|
|
1636
|
-
return
|
|
1771
|
+
if (Buffer5.isBuffer(value) || value instanceof Uint8Array) {
|
|
1772
|
+
return Buffer5.from(value).toString("utf8").toUpperCase();
|
|
1637
1773
|
}
|
|
1638
1774
|
return void 0;
|
|
1639
1775
|
}
|
|
@@ -1736,7 +1872,7 @@ function safeIntegerArgument(value) {
|
|
|
1736
1872
|
if (typeof value === "bigint") {
|
|
1737
1873
|
return value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
1738
1874
|
}
|
|
1739
|
-
const source = typeof value === "string" ? value :
|
|
1875
|
+
const source = typeof value === "string" ? value : Buffer5.isBuffer(value) || value instanceof Uint8Array ? Buffer5.from(value).toString("utf8") : void 0;
|
|
1740
1876
|
if (source == null || !/^[+-]?\d+$/u.test(source)) return void 0;
|
|
1741
1877
|
const parsed = BigInt(source);
|
|
1742
1878
|
return parsed >= BigInt(Number.MIN_SAFE_INTEGER) && parsed <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(parsed) : void 0;
|
|
@@ -1789,7 +1925,7 @@ function hasOwnCommandArgument(args, index, end, section) {
|
|
|
1789
1925
|
}
|
|
1790
1926
|
|
|
1791
1927
|
// src/protocol-core.ts
|
|
1792
|
-
import { Buffer as
|
|
1928
|
+
import { Buffer as Buffer9 } from "buffer";
|
|
1793
1929
|
|
|
1794
1930
|
// src/protocol-constants.ts
|
|
1795
1931
|
import "buffer";
|
|
@@ -1887,7 +2023,6 @@ var COMMAND_OPCODES = {
|
|
|
1887
2023
|
"FLOW.VALUE.PUT": 523,
|
|
1888
2024
|
"FLOW.VALUE.MGET": 524,
|
|
1889
2025
|
"FLOW.SIGNAL": 525,
|
|
1890
|
-
"FLOW.LIST": 526,
|
|
1891
2026
|
"FLOW.CREATE_MANY": 527,
|
|
1892
2027
|
"FLOW.COMPLETE_MANY": 528,
|
|
1893
2028
|
"FLOW.TRANSITION_MANY": 529,
|
|
@@ -1896,13 +2031,7 @@ var COMMAND_OPCODES = {
|
|
|
1896
2031
|
"FLOW.CANCEL_MANY": 532,
|
|
1897
2032
|
"FLOW.RECLAIM": 533,
|
|
1898
2033
|
"FLOW.REWIND": 534,
|
|
1899
|
-
"FLOW.TERMINALS": 535,
|
|
1900
|
-
"FLOW.FAILURES": 536,
|
|
1901
|
-
"FLOW.BY_PARENT": 537,
|
|
1902
|
-
"FLOW.BY_ROOT": 538,
|
|
1903
|
-
"FLOW.BY_CORRELATION": 539,
|
|
1904
2034
|
"FLOW.INFO": 540,
|
|
1905
|
-
"FLOW.STUCK": 541,
|
|
1906
2035
|
"FLOW.POLICY.SET": 542,
|
|
1907
2036
|
"FLOW.POLICY.GET": 543,
|
|
1908
2037
|
"FLOW.SPAWN_CHILDREN": 544,
|
|
@@ -1921,7 +2050,7 @@ var COMMAND_OPCODES = {
|
|
|
1921
2050
|
"FLOW.STATS": 557,
|
|
1922
2051
|
"FLOW.ATTRIBUTES": 558,
|
|
1923
2052
|
"FLOW.ATTRIBUTE_VALUES": 559,
|
|
1924
|
-
"FLOW.
|
|
2053
|
+
"FLOW.QUERY": 561,
|
|
1925
2054
|
"FLOW.EFFECT.RESERVE": 576,
|
|
1926
2055
|
"FLOW.EFFECT.CONFIRM": 577,
|
|
1927
2056
|
"FLOW.EFFECT.FAIL": 578,
|
|
@@ -2010,7 +2139,7 @@ var OPCODES = {
|
|
|
2010
2139
|
flowStepContinue: COMMAND_OPCODES["FLOW.STEP_CONTINUE"],
|
|
2011
2140
|
flowStartAndClaim: COMMAND_OPCODES["FLOW.START_AND_CLAIM"],
|
|
2012
2141
|
flowRunStepsMany: COMMAND_OPCODES["FLOW.RUN_STEPS_MANY"],
|
|
2013
|
-
|
|
2142
|
+
flowQuery: COMMAND_OPCODES["FLOW.QUERY"]
|
|
2014
2143
|
};
|
|
2015
2144
|
var COMPACT_FLOW_CLAIM_JOBS = 128;
|
|
2016
2145
|
var COMPACT_OK_LIST = 129;
|
|
@@ -2037,11 +2166,12 @@ var COMPACT_FLOW_TRANSITION_MANY_REQUEST = 155;
|
|
|
2037
2166
|
var COMPACT_FLOW_TRANSITION_MANY_OK_REQUEST = 156;
|
|
2038
2167
|
var COMPACT_FLOW_VALUE_MGET_REQUEST = 157;
|
|
2039
2168
|
var COMPACT_FLOW_CREATE_MANY_MIXED_REQUEST = 158;
|
|
2040
|
-
var
|
|
2169
|
+
var COMPACT_FLOW_QUERY_RESULT = 160;
|
|
2041
2170
|
var COMPACT_PIPELINE_DECODED = /* @__PURE__ */ Symbol("ferricstore.compactPipelineDecoded");
|
|
2042
2171
|
var NULL_U32 = 4294967295;
|
|
2043
|
-
var
|
|
2044
|
-
var
|
|
2172
|
+
var MIN_I642 = -9223372036854775808n;
|
|
2173
|
+
var MAX_I642 = 9223372036854775807n;
|
|
2174
|
+
var MAX_U64 = 18446744073709551615n;
|
|
2045
2175
|
var MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
2046
2176
|
var MIN_SAFE_INTEGER_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
|
|
2047
2177
|
var FLOW_RECORD_FIELD_KEYS = [
|
|
@@ -2090,16 +2220,16 @@ var FLOW_RECORD_FIELD_KEYS = [
|
|
|
2090
2220
|
];
|
|
2091
2221
|
|
|
2092
2222
|
// src/protocol-text.ts
|
|
2093
|
-
import { Buffer as
|
|
2223
|
+
import { Buffer as Buffer7 } from "buffer";
|
|
2094
2224
|
function toBuffer(value) {
|
|
2095
|
-
if (
|
|
2096
|
-
if (value instanceof Uint8Array) return
|
|
2097
|
-
if (typeof value === "string") return
|
|
2225
|
+
if (Buffer7.isBuffer(value)) return value;
|
|
2226
|
+
if (value instanceof Uint8Array) return Buffer7.from(value);
|
|
2227
|
+
if (typeof value === "string") return Buffer7.from(value);
|
|
2098
2228
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2099
|
-
return
|
|
2229
|
+
return Buffer7.from(String(value));
|
|
2100
2230
|
}
|
|
2101
|
-
if (typeof value === "symbol") return
|
|
2102
|
-
if (value == null) return
|
|
2231
|
+
if (typeof value === "symbol") return Buffer7.from(value.description ?? value.toString());
|
|
2232
|
+
if (value == null) return Buffer7.alloc(0);
|
|
2103
2233
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2104
2234
|
}
|
|
2105
2235
|
function asText(value) {
|
|
@@ -2107,14 +2237,14 @@ function asText(value) {
|
|
|
2107
2237
|
}
|
|
2108
2238
|
function optionalText(value) {
|
|
2109
2239
|
if (value == null || value === "") return void 0;
|
|
2110
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" ||
|
|
2240
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || Buffer7.isBuffer(value) || value instanceof Uint8Array) {
|
|
2111
2241
|
return asText(value);
|
|
2112
2242
|
}
|
|
2113
2243
|
return void 0;
|
|
2114
2244
|
}
|
|
2115
2245
|
function commandTokenIs(value, expected) {
|
|
2116
2246
|
if (typeof value === "string") return value.toUpperCase() === expected;
|
|
2117
|
-
if (
|
|
2247
|
+
if (Buffer7.isBuffer(value) || value instanceof Uint8Array) {
|
|
2118
2248
|
return asText(value).toUpperCase() === expected;
|
|
2119
2249
|
}
|
|
2120
2250
|
return false;
|
|
@@ -2128,7 +2258,7 @@ function commandNameIs(value, expected) {
|
|
|
2128
2258
|
}
|
|
2129
2259
|
|
|
2130
2260
|
// src/request-context.ts
|
|
2131
|
-
import { Buffer as
|
|
2261
|
+
import { Buffer as Buffer8 } from "buffer";
|
|
2132
2262
|
var requestContextCommands = /* @__PURE__ */ new Set([
|
|
2133
2263
|
"INVOCATION.CREATE",
|
|
2134
2264
|
"INVOCATION.DEFINITION.GET",
|
|
@@ -2183,9 +2313,9 @@ function requestContextCommandToken(value) {
|
|
|
2183
2313
|
const upper = value.toUpperCase();
|
|
2184
2314
|
return isRequestContextCommand(upper) ? upper : void 0;
|
|
2185
2315
|
}
|
|
2186
|
-
if (
|
|
2316
|
+
if (Buffer8.isBuffer(value) || value instanceof Uint8Array) {
|
|
2187
2317
|
if (value[0] !== 73 && value[0] !== 105) return void 0;
|
|
2188
|
-
const command =
|
|
2318
|
+
const command = Buffer8.from(value).toString("utf8").toUpperCase();
|
|
2189
2319
|
return isRequestContextCommand(command) ? command : void 0;
|
|
2190
2320
|
}
|
|
2191
2321
|
return void 0;
|
|
@@ -2216,12 +2346,12 @@ function requestContextText(context, fieldName) {
|
|
|
2216
2346
|
return value;
|
|
2217
2347
|
}
|
|
2218
2348
|
function isPlainObject(value) {
|
|
2219
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2349
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer8.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2220
2350
|
}
|
|
2221
2351
|
function commandToken2(value) {
|
|
2222
2352
|
if (typeof value === "string") return value.toUpperCase();
|
|
2223
|
-
if (
|
|
2224
|
-
return
|
|
2353
|
+
if (Buffer8.isBuffer(value) || value instanceof Uint8Array) {
|
|
2354
|
+
return Buffer8.from(value).toString("utf8").toUpperCase();
|
|
2225
2355
|
}
|
|
2226
2356
|
return "";
|
|
2227
2357
|
}
|
|
@@ -2311,17 +2441,17 @@ function requestFrameTooLarge(maxBytes) {
|
|
|
2311
2441
|
);
|
|
2312
2442
|
}
|
|
2313
2443
|
function binaryValueByteLength(value) {
|
|
2314
|
-
if (
|
|
2315
|
-
if (typeof value === "string") return
|
|
2444
|
+
if (Buffer9.isBuffer(value) || value instanceof Uint8Array) return value.byteLength;
|
|
2445
|
+
if (typeof value === "string") return Buffer9.byteLength(value);
|
|
2316
2446
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2317
|
-
return
|
|
2447
|
+
return Buffer9.byteLength(String(value));
|
|
2318
2448
|
}
|
|
2319
|
-
if (typeof value === "symbol") return
|
|
2449
|
+
if (typeof value === "symbol") return Buffer9.byteLength(value.description ?? value.toString());
|
|
2320
2450
|
if (value == null) return 0;
|
|
2321
2451
|
return toBuffer(value).byteLength;
|
|
2322
2452
|
}
|
|
2323
2453
|
function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
2324
|
-
if (
|
|
2454
|
+
if (Buffer9.isBuffer(value)) {
|
|
2325
2455
|
value.copy(output, offset);
|
|
2326
2456
|
return;
|
|
2327
2457
|
}
|
|
@@ -2340,7 +2470,7 @@ function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
|
2340
2470
|
} else {
|
|
2341
2471
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2342
2472
|
}
|
|
2343
|
-
output.write(text3, offset, knownByteLength ??
|
|
2473
|
+
output.write(text3, offset, knownByteLength ?? Buffer9.byteLength(text3), "utf8");
|
|
2344
2474
|
}
|
|
2345
2475
|
function compactBinaryEncodedLength(value) {
|
|
2346
2476
|
return 4 + compactBinaryByteLength(value);
|
|
@@ -2353,10 +2483,10 @@ function compactBinaryByteLength(value) {
|
|
|
2353
2483
|
return byteLength;
|
|
2354
2484
|
}
|
|
2355
2485
|
function isCompactBinaryArgument(value) {
|
|
2356
|
-
return typeof value === "string" ||
|
|
2486
|
+
return typeof value === "string" || Buffer9.isBuffer(value) || value instanceof Uint8Array;
|
|
2357
2487
|
}
|
|
2358
2488
|
function isCompactBinaryScalar(value) {
|
|
2359
|
-
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" ||
|
|
2489
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" || Buffer9.isBuffer(value) || value instanceof Uint8Array;
|
|
2360
2490
|
}
|
|
2361
2491
|
function compactOptionalBinaryEncodedLength(value) {
|
|
2362
2492
|
return value == null ? 4 : compactBinaryEncodedLength(value);
|
|
@@ -2422,7 +2552,7 @@ function integerArg(value) {
|
|
|
2422
2552
|
throw new FerricStoreError("integer command argument must be an integer");
|
|
2423
2553
|
}
|
|
2424
2554
|
const integer2 = BigInt(source);
|
|
2425
|
-
if (integer2 <
|
|
2555
|
+
if (integer2 < MIN_I642 || integer2 > MAX_I642) {
|
|
2426
2556
|
throw new FerricStoreError("integer command argument exceeds the signed 64-bit range");
|
|
2427
2557
|
}
|
|
2428
2558
|
return integer2 >= MIN_SAFE_INTEGER_BIGINT && integer2 <= MAX_SAFE_INTEGER_BIGINT ? Number(integer2) : integer2;
|
|
@@ -2453,7 +2583,7 @@ function independentMode(value) {
|
|
|
2453
2583
|
return 0;
|
|
2454
2584
|
}
|
|
2455
2585
|
function optionalI64(value) {
|
|
2456
|
-
return typeof value === "number" ? BigInt(value) :
|
|
2586
|
+
return typeof value === "number" ? BigInt(value) : MIN_I642;
|
|
2457
2587
|
}
|
|
2458
2588
|
function compactClaimReturnMode(value) {
|
|
2459
2589
|
const mode = value == null ? "" : asText(value).toUpperCase();
|
|
@@ -2487,18 +2617,18 @@ function setOwnValue2(target, key, value) {
|
|
|
2487
2617
|
}
|
|
2488
2618
|
|
|
2489
2619
|
// src/protocol-flow-options.ts
|
|
2490
|
-
import { Buffer as
|
|
2620
|
+
import { Buffer as Buffer10 } from "buffer";
|
|
2491
2621
|
|
|
2492
2622
|
// src/protocol-flow-option-value.ts
|
|
2493
|
-
function setFlowOptionValue(payload,
|
|
2494
|
-
if (!repeat || !Object.hasOwn(payload,
|
|
2495
|
-
setOwnValue2(payload,
|
|
2623
|
+
function setFlowOptionValue(payload, field3, value, repeat) {
|
|
2624
|
+
if (!repeat || !Object.hasOwn(payload, field3)) {
|
|
2625
|
+
setOwnValue2(payload, field3, value);
|
|
2496
2626
|
return;
|
|
2497
2627
|
}
|
|
2498
|
-
const previous = payload[
|
|
2628
|
+
const previous = payload[field3];
|
|
2499
2629
|
setOwnValue2(
|
|
2500
2630
|
payload,
|
|
2501
|
-
|
|
2631
|
+
field3,
|
|
2502
2632
|
Array.isArray(previous) ? [...previous, value] : [previous, value]
|
|
2503
2633
|
);
|
|
2504
2634
|
}
|
|
@@ -2541,44 +2671,30 @@ function optionMap(args) {
|
|
|
2541
2671
|
index += 3;
|
|
2542
2672
|
continue;
|
|
2543
2673
|
}
|
|
2544
|
-
const
|
|
2674
|
+
const field3 = OPTION_FIELDS[token] ?? token.toLowerCase();
|
|
2545
2675
|
if (!hasOwnCommandArgument(args, index + 1, args.length, "Flow options")) {
|
|
2546
2676
|
throw new FerricStoreError(`${token} requires a value`);
|
|
2547
2677
|
}
|
|
2548
2678
|
const value = args[index + 1];
|
|
2549
|
-
if (BOOL_OPTION_FIELDS.has(
|
|
2679
|
+
if (BOOL_OPTION_FIELDS.has(field3) && !isBoolToken(value)) {
|
|
2550
2680
|
return void 0;
|
|
2551
2681
|
}
|
|
2552
|
-
setOwnValue2(payload,
|
|
2682
|
+
setOwnValue2(payload, field3, BOOL_OPTION_FIELDS.has(field3) ? boolArg(value) : value);
|
|
2553
2683
|
index += 2;
|
|
2554
2684
|
}
|
|
2555
2685
|
return payload;
|
|
2556
2686
|
}
|
|
2557
|
-
function ensureObjectField(payload,
|
|
2558
|
-
const value = payload[
|
|
2687
|
+
function ensureObjectField(payload, field3) {
|
|
2688
|
+
const value = payload[field3];
|
|
2559
2689
|
if (isPlainObject2(value)) {
|
|
2560
2690
|
return value;
|
|
2561
2691
|
}
|
|
2562
2692
|
const next = {};
|
|
2563
|
-
setOwnValue2(payload,
|
|
2693
|
+
setOwnValue2(payload, field3, next);
|
|
2564
2694
|
return next;
|
|
2565
2695
|
}
|
|
2566
|
-
function normalizeFlowSearchStateMeta(payload) {
|
|
2567
|
-
const stateMeta = payload.state_meta;
|
|
2568
|
-
if (!isPlainObject2(stateMeta) || Object.keys(stateMeta).length === 0) {
|
|
2569
|
-
return;
|
|
2570
|
-
}
|
|
2571
|
-
if (Object.values(stateMeta).every(isPlainObject2)) {
|
|
2572
|
-
return;
|
|
2573
|
-
}
|
|
2574
|
-
const state = payload.state;
|
|
2575
|
-
if (state == null) {
|
|
2576
|
-
throw new FerricStoreError("FLOW.SEARCH STATE_META filters require STATE or nested state metadata");
|
|
2577
|
-
}
|
|
2578
|
-
payload.state_meta = { [asText(state)]: stateMeta };
|
|
2579
|
-
}
|
|
2580
2696
|
function isPlainObject2(value) {
|
|
2581
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2697
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer10.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2582
2698
|
}
|
|
2583
2699
|
function parseFlowOptions(args, start, end, config) {
|
|
2584
2700
|
const payload = {};
|
|
@@ -2672,9 +2788,9 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2672
2788
|
case "TRANSITION_TO":
|
|
2673
2789
|
case "TO_EVENT":
|
|
2674
2790
|
case "EXPECT_STATE": {
|
|
2675
|
-
const
|
|
2791
|
+
const field3 = token === "IDEMPOTENCY" ? "idempotency_key" : token.toLowerCase();
|
|
2676
2792
|
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options")) return void 0;
|
|
2677
|
-
setFlowOptionValue(payload,
|
|
2793
|
+
setFlowOptionValue(payload, field3, args[index + 1], token === "IF_STATE");
|
|
2678
2794
|
index += 2;
|
|
2679
2795
|
break;
|
|
2680
2796
|
}
|
|
@@ -2682,8 +2798,8 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2682
2798
|
case "RESULT":
|
|
2683
2799
|
case "ERROR":
|
|
2684
2800
|
case "REASON": {
|
|
2685
|
-
const
|
|
2686
|
-
if (!putScalar(payload,
|
|
2801
|
+
const field3 = token === "LEASE_TOKEN" ? "lease_token" : token.toLowerCase();
|
|
2802
|
+
if (!putScalar(payload, field3, args, index + 1, end)) return void 0;
|
|
2687
2803
|
index += 2;
|
|
2688
2804
|
break;
|
|
2689
2805
|
}
|
|
@@ -2705,8 +2821,8 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2705
2821
|
case "VALUE_REF":
|
|
2706
2822
|
case "STATE_META": {
|
|
2707
2823
|
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options") || !hasOwnCommandArgument(args, index + 2, end, "Flow options")) return void 0;
|
|
2708
|
-
const
|
|
2709
|
-
const values = ensureObjectField(payload,
|
|
2824
|
+
const field3 = token === "ATTRIBUTE" ? "attributes" : token === "ATTRIBUTE_MERGE" ? "attributes_merge" : token === "VALUE_REF" ? "value_refs" : "state_meta";
|
|
2825
|
+
const values = ensureObjectField(payload, field3);
|
|
2710
2826
|
setOwnValue2(values, asText(args[index + 1]), args[index + 2]);
|
|
2711
2827
|
index += 3;
|
|
2712
2828
|
break;
|
|
@@ -2715,8 +2831,8 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2715
2831
|
case "OVERRIDE_VALUE":
|
|
2716
2832
|
case "ATTRIBUTE_DELETE": {
|
|
2717
2833
|
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options")) return void 0;
|
|
2718
|
-
const
|
|
2719
|
-
const values = ensureArrayField(payload,
|
|
2834
|
+
const field3 = token === "DROP_VALUE" ? "drop_values" : token === "OVERRIDE_VALUE" ? "override_values" : "attributes_delete";
|
|
2835
|
+
const values = ensureArrayField(payload, field3);
|
|
2720
2836
|
values.push(args[index + 1]);
|
|
2721
2837
|
index += 2;
|
|
2722
2838
|
break;
|
|
@@ -2833,13 +2949,13 @@ function putScalar(payload, key, args, index, end) {
|
|
|
2833
2949
|
setOwnValue2(payload, key, args[index]);
|
|
2834
2950
|
return true;
|
|
2835
2951
|
}
|
|
2836
|
-
function ensureArrayField(payload,
|
|
2837
|
-
const value = payload[
|
|
2952
|
+
function ensureArrayField(payload, field3) {
|
|
2953
|
+
const value = payload[field3];
|
|
2838
2954
|
if (Array.isArray(value)) {
|
|
2839
2955
|
return value;
|
|
2840
2956
|
}
|
|
2841
2957
|
const next = [];
|
|
2842
|
-
setOwnValue2(payload,
|
|
2958
|
+
setOwnValue2(payload, field3, next);
|
|
2843
2959
|
return next;
|
|
2844
2960
|
}
|
|
2845
2961
|
function putNumber(payload, key, args, index, end) {
|
|
@@ -3060,8 +3176,8 @@ function flowHistoryPayload(args) {
|
|
|
3060
3176
|
case "CONSISTENT_PROJECTION":
|
|
3061
3177
|
case "VALUES": {
|
|
3062
3178
|
if (!isBoolToken(value)) return void 0;
|
|
3063
|
-
const
|
|
3064
|
-
payload[
|
|
3179
|
+
const field3 = token === "REV" ? "rev" : token === "INCLUDE_COLD" ? "include_cold" : token === "CONSISTENT_PROJECTION" ? "consistent_projection" : "values";
|
|
3180
|
+
payload[field3] = boolArg(value);
|
|
3065
3181
|
break;
|
|
3066
3182
|
}
|
|
3067
3183
|
default:
|
|
@@ -3073,9 +3189,9 @@ function flowHistoryPayload(args) {
|
|
|
3073
3189
|
function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
3074
3190
|
if (args.length < leadingFields.length) return void 0;
|
|
3075
3191
|
const payload = {};
|
|
3076
|
-
for (const [index,
|
|
3192
|
+
for (const [index, field3] of leadingFields.entries()) {
|
|
3077
3193
|
hasOwnCommandArgument(args, index, args.length, "Flow admin arguments");
|
|
3078
|
-
setOwnValue2(payload,
|
|
3194
|
+
setOwnValue2(payload, field3, args[index]);
|
|
3079
3195
|
}
|
|
3080
3196
|
for (let index = leadingFields.length; index < args.length; ) {
|
|
3081
3197
|
hasOwnCommandArgument(args, index, args.length, "Flow admin arguments");
|
|
@@ -3083,15 +3199,15 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3083
3199
|
if (token == null) return void 0;
|
|
3084
3200
|
if (["ATTRIBUTE", "ATTRIBUTE_MERGE", "STATE_META", "VALUE", "VALUE_REF"].includes(token)) {
|
|
3085
3201
|
if (!hasOwnCommandArgument(args, index + 1, args.length, "Flow admin arguments") || !hasOwnCommandArgument(args, index + 2, args.length, "Flow admin arguments")) return void 0;
|
|
3086
|
-
const
|
|
3087
|
-
setOwnValue2(ensureObjectField(payload,
|
|
3202
|
+
const field4 = token === "ATTRIBUTE" ? "attributes" : token === "ATTRIBUTE_MERGE" ? "attributes_merge" : token === "STATE_META" ? "state_meta" : token === "VALUE" ? "values" : "value_refs";
|
|
3203
|
+
setOwnValue2(ensureObjectField(payload, field4), asText(args[index + 1]), args[index + 2]);
|
|
3088
3204
|
index += 3;
|
|
3089
3205
|
continue;
|
|
3090
3206
|
}
|
|
3091
3207
|
if (token === "ATTRIBUTE_DELETE" || token === "DROP_VALUE" || token === "OVERRIDE_VALUE") {
|
|
3092
3208
|
if (!hasOwnCommandArgument(args, index + 1, args.length, "Flow admin arguments")) return void 0;
|
|
3093
|
-
const
|
|
3094
|
-
ensureArrayField(payload,
|
|
3209
|
+
const field4 = token === "ATTRIBUTE_DELETE" ? "attributes_delete" : token === "DROP_VALUE" ? "drop_values" : "override_values";
|
|
3210
|
+
ensureArrayField(payload, field4).push(args[index + 1]);
|
|
3095
3211
|
index += 2;
|
|
3096
3212
|
continue;
|
|
3097
3213
|
}
|
|
@@ -3110,13 +3226,13 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3110
3226
|
index += 2 + count;
|
|
3111
3227
|
continue;
|
|
3112
3228
|
}
|
|
3113
|
-
const
|
|
3114
|
-
if (
|
|
3229
|
+
const field3 = FLOW_ADMIN_FIELDS[token];
|
|
3230
|
+
if (field3 == null || !hasOwnCommandArgument(args, index + 1, args.length, "Flow admin arguments")) {
|
|
3115
3231
|
return void 0;
|
|
3116
3232
|
}
|
|
3117
3233
|
const rawValue = args[index + 1];
|
|
3118
|
-
if (FLOW_ADMIN_BOOLEAN_FIELDS.has(
|
|
3119
|
-
setOwnValue2(payload,
|
|
3234
|
+
if (FLOW_ADMIN_BOOLEAN_FIELDS.has(field3) && !isBoolToken(rawValue)) return void 0;
|
|
3235
|
+
setOwnValue2(payload, field3, FLOW_ADMIN_BOOLEAN_FIELDS.has(field3) ? boolArg(rawValue) : rawValue);
|
|
3120
3236
|
index += 2;
|
|
3121
3237
|
}
|
|
3122
3238
|
const serverBlockMs = opcode === COMMAND_OPCODES["FLOW.SCHEDULE.FIRE_DUE"] && payload.block_ms != null ? blockDurationMs(payload.block_ms, 1) : void 0;
|
|
@@ -3124,7 +3240,7 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3124
3240
|
}
|
|
3125
3241
|
|
|
3126
3242
|
// src/protocol-flow-compact.ts
|
|
3127
|
-
import { Buffer as
|
|
3243
|
+
import { Buffer as Buffer12 } from "buffer";
|
|
3128
3244
|
|
|
3129
3245
|
// src/protocol-flow-compact-common.ts
|
|
3130
3246
|
function compactManyRequestTag(value, regularTag, okOnSuccessTag) {
|
|
@@ -3233,7 +3349,7 @@ function parseNamedCountMap(values, start) {
|
|
|
3233
3349
|
}
|
|
3234
3350
|
|
|
3235
3351
|
// src/protocol-flow-compact-transition.ts
|
|
3236
|
-
import { Buffer as
|
|
3352
|
+
import { Buffer as Buffer11 } from "buffer";
|
|
3237
3353
|
function compactFlowTransitionManyPayload(partition, fromState, toState, rawItems, mixed, options, maxBodyBytes) {
|
|
3238
3354
|
if ("payload" in options || "priority" in options || "state_meta" in options || "values" in options || "value_refs" in options || "drop_values" in options || "override_values" in options || "attributes_merge" in options || "attributes_delete" in options || typeof options.now_ms !== "number" || !Number.isSafeInteger(options.now_ms) || options.now_ms < 0) {
|
|
3239
3355
|
return void 0;
|
|
@@ -3285,7 +3401,7 @@ function compactFlowTransitionManyPayload(partition, fromState, toState, rawItem
|
|
|
3285
3401
|
total += 4 + idLength + 4 + itemPartitionLength + 8 + 4 + leaseLength;
|
|
3286
3402
|
}
|
|
3287
3403
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3288
|
-
const out =
|
|
3404
|
+
const out = Buffer11.allocUnsafe(total);
|
|
3289
3405
|
let offset = 0;
|
|
3290
3406
|
out.writeUInt8(tag, offset);
|
|
3291
3407
|
offset += 1;
|
|
@@ -3343,7 +3459,7 @@ function compactFlowCreateManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3343
3459
|
}
|
|
3344
3460
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3345
3461
|
const tag = mixed ? COMPACT_FLOW_CREATE_MANY_MIXED_REQUEST : auto ? COMPACT_FLOW_CREATE_MANY_REQUEST : COMPACT_FLOW_CREATE_MANY_PARTITION_REQUEST;
|
|
3346
|
-
const out =
|
|
3462
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3347
3463
|
let offset = 0;
|
|
3348
3464
|
out.writeUInt8(tag, offset++);
|
|
3349
3465
|
offset = writeBinary(out, offset, toBuffer(options.type));
|
|
@@ -3388,7 +3504,7 @@ function compactFlowClaimDuePayload(type, options, maxBodyBytes) {
|
|
|
3388
3504
|
total += 1;
|
|
3389
3505
|
}
|
|
3390
3506
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3391
|
-
const out =
|
|
3507
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3392
3508
|
let offset = 0;
|
|
3393
3509
|
out.writeUInt8(COMPACT_FLOW_CLAIM_DUE_REQUEST, offset++);
|
|
3394
3510
|
offset = writeBinary(out, offset, toBuffer(type));
|
|
@@ -3442,7 +3558,7 @@ function compactFlowCompleteManyPayload(opcode, partition, rawItems, mixed, auto
|
|
|
3442
3558
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3443
3559
|
}
|
|
3444
3560
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3445
|
-
const out =
|
|
3561
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3446
3562
|
let offset = 0;
|
|
3447
3563
|
out.writeUInt8(
|
|
3448
3564
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_COMPLETE_MANY_OK_REQUEST : COMPACT_FLOW_COMPLETE_MANY_REQUEST,
|
|
@@ -3489,7 +3605,7 @@ function compactFlowRetryManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3489
3605
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3490
3606
|
}
|
|
3491
3607
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3492
|
-
const out =
|
|
3608
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3493
3609
|
let offset = 0;
|
|
3494
3610
|
out.writeUInt8(
|
|
3495
3611
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_RETRY_MANY_OK_REQUEST : COMPACT_FLOW_RETRY_MANY_REQUEST,
|
|
@@ -3577,7 +3693,7 @@ function compactFlowCancelManyPayload(args, maxBodyBytes) {
|
|
|
3577
3693
|
total += 4 + idLength + 4 + itemPartitionLength + 8;
|
|
3578
3694
|
}
|
|
3579
3695
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3580
|
-
const out =
|
|
3696
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3581
3697
|
let offset = 0;
|
|
3582
3698
|
out.writeUInt8(tag, offset);
|
|
3583
3699
|
offset += 1;
|
|
@@ -3600,6 +3716,7 @@ function compactFlowCancelManyPayload(args, maxBodyBytes) {
|
|
|
3600
3716
|
offset += 8;
|
|
3601
3717
|
}
|
|
3602
3718
|
return {
|
|
3719
|
+
compactResponseItems: count,
|
|
3603
3720
|
flags: FLAG_CUSTOM_PAYLOAD,
|
|
3604
3721
|
opcode: COMMAND_OPCODES["FLOW.CANCEL_MANY"],
|
|
3605
3722
|
payload: out
|
|
@@ -3613,7 +3730,7 @@ function isOptionalSafeIntegerNumber(value) {
|
|
|
3613
3730
|
}
|
|
3614
3731
|
|
|
3615
3732
|
// src/protocol-flow-compact-single.ts
|
|
3616
|
-
import { Buffer as
|
|
3733
|
+
import { Buffer as Buffer13 } from "buffer";
|
|
3617
3734
|
function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
3618
3735
|
if (refs.length > 4294967295 || maxBytes != null && (typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 0)) return void 0;
|
|
3619
3736
|
const minimum = 13 + refs.length * 4;
|
|
@@ -3630,7 +3747,7 @@ function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
|
3630
3747
|
total += 4 + byteLength;
|
|
3631
3748
|
}
|
|
3632
3749
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3633
|
-
const out =
|
|
3750
|
+
const out = Buffer13.allocUnsafe(total);
|
|
3634
3751
|
let offset = 0;
|
|
3635
3752
|
out.writeUInt8(COMPACT_FLOW_VALUE_MGET_REQUEST, offset);
|
|
3636
3753
|
offset += 1;
|
|
@@ -3643,47 +3760,6 @@ function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
|
3643
3760
|
}
|
|
3644
3761
|
return { flags: FLAG_CUSTOM_PAYLOAD, opcode: OPCODES.flowValueMGet, payload: out };
|
|
3645
3762
|
}
|
|
3646
|
-
function compactFlowListPayload(args, maxBodyBytes) {
|
|
3647
|
-
const type = args[0];
|
|
3648
|
-
if (!isCompactBinaryArgument(type)) return void 0;
|
|
3649
|
-
let state;
|
|
3650
|
-
let count = 100;
|
|
3651
|
-
let returnMode = 0;
|
|
3652
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3653
|
-
for (let index = 1; index < args.length; index += 2) {
|
|
3654
|
-
if (index + 1 >= args.length) return void 0;
|
|
3655
|
-
const token = asText(args[index]).toUpperCase();
|
|
3656
|
-
if (seen.has(token)) return void 0;
|
|
3657
|
-
seen.add(token);
|
|
3658
|
-
if (token === "STATE") {
|
|
3659
|
-
if (!isCompactBinaryArgument(args[index + 1])) return void 0;
|
|
3660
|
-
state = args[index + 1];
|
|
3661
|
-
} else if (token === "COUNT") {
|
|
3662
|
-
const value = safeIntegerNumberArg(args[index + 1]);
|
|
3663
|
-
if (value <= 0) return void 0;
|
|
3664
|
-
count = value;
|
|
3665
|
-
} else if (token === "RETURN") {
|
|
3666
|
-
if (!commandTokenIs(args[index + 1], "META")) return void 0;
|
|
3667
|
-
returnMode = 1;
|
|
3668
|
-
} else {
|
|
3669
|
-
return void 0;
|
|
3670
|
-
}
|
|
3671
|
-
}
|
|
3672
|
-
const typeLength = compactBinaryByteLength(type);
|
|
3673
|
-
const stateLength = state == null ? 0 : compactBinaryByteLength(state);
|
|
3674
|
-
const total = 1 + 4 + typeLength + 4 + stateLength + 8 + 1;
|
|
3675
|
-
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3676
|
-
const out = Buffer12.allocUnsafe(total);
|
|
3677
|
-
let offset = 0;
|
|
3678
|
-
out.writeUInt8(COMPACT_FLOW_LIST_REQUEST, offset);
|
|
3679
|
-
offset += 1;
|
|
3680
|
-
offset = writeBinaryValue(out, offset, type, typeLength);
|
|
3681
|
-
offset = writeOptionalBinaryValue(out, offset, state, stateLength);
|
|
3682
|
-
out.writeBigInt64BE(BigInt(count), offset);
|
|
3683
|
-
offset += 8;
|
|
3684
|
-
out.writeUInt8(returnMode, offset);
|
|
3685
|
-
return { flags: FLAG_CUSTOM_PAYLOAD, opcode: COMMAND_OPCODES["FLOW.LIST"], payload: out };
|
|
3686
|
-
}
|
|
3687
3763
|
|
|
3688
3764
|
// src/protocol-flow-routing.ts
|
|
3689
3765
|
function withFlowPartitionRouting(command, payload) {
|
|
@@ -3732,15 +3808,6 @@ function expandFlowClaimStates(args) {
|
|
|
3732
3808
|
}
|
|
3733
3809
|
|
|
3734
3810
|
// src/protocol-flow.ts
|
|
3735
|
-
function hasFlowCommandOnlyOption(command, args) {
|
|
3736
|
-
if (command !== "FLOW.SEARCH") return false;
|
|
3737
|
-
for (let index = 1; index < args.length; ) {
|
|
3738
|
-
const token = asText(args[index]).toUpperCase();
|
|
3739
|
-
if (token === "INDEXED_STATE_META") return true;
|
|
3740
|
-
index += token === "ATTRIBUTE" || token === "STATE_META" ? 3 : 2;
|
|
3741
|
-
}
|
|
3742
|
-
return false;
|
|
3743
|
-
}
|
|
3744
3811
|
function flowCreatePayload(args) {
|
|
3745
3812
|
if (args.length < 7) return void 0;
|
|
3746
3813
|
const id = args[0];
|
|
@@ -3797,9 +3864,9 @@ function flowValueMGetPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3797
3864
|
}
|
|
3798
3865
|
if (allowCompact) {
|
|
3799
3866
|
const compact = compactFlowValueMGetPayload(refs, payload.max_bytes, maxBodyBytes);
|
|
3800
|
-
if (compact != null) return compact;
|
|
3867
|
+
if (compact != null) return { ...compact, compactResponseItems: refs.length };
|
|
3801
3868
|
}
|
|
3802
|
-
return { opcode: OPCODES.flowValueMGet, payload };
|
|
3869
|
+
return { compactResponseItems: refs.length, opcode: OPCODES.flowValueMGet, payload };
|
|
3803
3870
|
}
|
|
3804
3871
|
function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
3805
3872
|
if (args.length < 2) return void 0;
|
|
@@ -3835,7 +3902,7 @@ function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3835
3902
|
if (items2 == null) return void 0;
|
|
3836
3903
|
const payload2 = { ...options, items: items2 };
|
|
3837
3904
|
if (!auto && !mixed) payload2.partition_key = partition;
|
|
3838
|
-
return { opcode: OPCODES.flowCreateMany, payload: payload2 };
|
|
3905
|
+
return { compactResponseItems: items2.length, opcode: OPCODES.flowCreateMany, payload: payload2 };
|
|
3839
3906
|
}
|
|
3840
3907
|
const rawItems = denseCommandArgumentTail(args, itemsIndex + 1, "ITEMS");
|
|
3841
3908
|
const width = mixed ? 3 : 2;
|
|
@@ -3849,7 +3916,9 @@ function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3849
3916
|
options,
|
|
3850
3917
|
maxBodyBytes
|
|
3851
3918
|
);
|
|
3852
|
-
if (compact != null)
|
|
3919
|
+
if (compact != null) {
|
|
3920
|
+
return { ...compact, compactResponseItems: rawItems.length / width };
|
|
3921
|
+
}
|
|
3853
3922
|
}
|
|
3854
3923
|
const items = [];
|
|
3855
3924
|
for (let index = 0; index < rawItems.length; index += width) {
|
|
@@ -3861,7 +3930,7 @@ function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3861
3930
|
}
|
|
3862
3931
|
const payload = { ...options, items };
|
|
3863
3932
|
if (!auto && !mixed) payload.partition_key = partition;
|
|
3864
|
-
return { opcode: OPCODES.flowCreateMany, payload };
|
|
3933
|
+
return { compactResponseItems: items.length, opcode: OPCODES.flowCreateMany, payload };
|
|
3865
3934
|
}
|
|
3866
3935
|
function flowClaimDuePayload(args, maxBodyBytes, allowCompact) {
|
|
3867
3936
|
if (args.length < 1) return void 0;
|
|
@@ -4024,7 +4093,9 @@ function flowClaimedManyPayload(command, opcode, args, maxBodyBytes = Number.MAX
|
|
|
4024
4093
|
if (rawItems.length === 0 || rawItems.length % width !== 0) return void 0;
|
|
4025
4094
|
if (allowCompact) {
|
|
4026
4095
|
const compact = command === "FLOW.RETRY_MANY" ? compactFlowRetryManyPayload(partition, rawItems, mixed, auto, options, maxBodyBytes) : compactFlowCompleteManyPayload(opcode, partition, rawItems, mixed, auto, options, maxBodyBytes);
|
|
4027
|
-
if (compact != null)
|
|
4096
|
+
if (compact != null) {
|
|
4097
|
+
return { ...compact, compactResponseItems: rawItems.length / width };
|
|
4098
|
+
}
|
|
4028
4099
|
}
|
|
4029
4100
|
const items = [];
|
|
4030
4101
|
for (let index = 0; index < rawItems.length; index += width) {
|
|
@@ -4036,7 +4107,7 @@ function flowClaimedManyPayload(command, opcode, args, maxBodyBytes = Number.MAX
|
|
|
4036
4107
|
}
|
|
4037
4108
|
const payload = { ...options, items };
|
|
4038
4109
|
if (!auto && !mixed) payload.partition_key = partition;
|
|
4039
|
-
return { opcode, payload };
|
|
4110
|
+
return { compactResponseItems: items.length, opcode, payload };
|
|
4040
4111
|
}
|
|
4041
4112
|
function flowTransitionManyPayload(args, maxBodyBytes, allowCompact) {
|
|
4042
4113
|
if (args.length < 4) return void 0;
|
|
@@ -4076,7 +4147,9 @@ function flowTransitionManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
4076
4147
|
options,
|
|
4077
4148
|
maxBodyBytes
|
|
4078
4149
|
) : void 0;
|
|
4079
|
-
if (compact != null)
|
|
4150
|
+
if (compact != null) {
|
|
4151
|
+
return { ...compact, compactResponseItems: rawItems.length / width };
|
|
4152
|
+
}
|
|
4080
4153
|
}
|
|
4081
4154
|
const items = [];
|
|
4082
4155
|
for (let index = 0; index < rawItems.length; index += width) {
|
|
@@ -4096,7 +4169,11 @@ function flowTransitionManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
4096
4169
|
items
|
|
4097
4170
|
};
|
|
4098
4171
|
if (!mixed) payload.partition_key = args[0];
|
|
4099
|
-
return {
|
|
4172
|
+
return {
|
|
4173
|
+
compactResponseItems: items.length,
|
|
4174
|
+
opcode: OPCODES.flowTransitionMany,
|
|
4175
|
+
payload
|
|
4176
|
+
};
|
|
4100
4177
|
}
|
|
4101
4178
|
function flowSpawnChildrenPayload(args) {
|
|
4102
4179
|
if (args.length < 2) return void 0;
|
|
@@ -4139,13 +4216,6 @@ function flowSpawnChildrenPayload(args) {
|
|
|
4139
4216
|
payload: { id: args[0], ...options, children }
|
|
4140
4217
|
};
|
|
4141
4218
|
}
|
|
4142
|
-
function flowSearchPayload(args) {
|
|
4143
|
-
if (args.length < 1) return void 0;
|
|
4144
|
-
const payload = optionMap(args.slice(1));
|
|
4145
|
-
if (payload == null) return void 0;
|
|
4146
|
-
normalizeFlowSearchStateMeta(payload);
|
|
4147
|
-
return { opcode: OPCODES.flowSearch, payload: { type: args[0], ...payload } };
|
|
4148
|
-
}
|
|
4149
4219
|
|
|
4150
4220
|
// src/protocol-flow-signal.ts
|
|
4151
4221
|
function flowSignalPayload(args) {
|
|
@@ -4171,7 +4241,7 @@ function flowSignalPayload(args) {
|
|
|
4171
4241
|
}
|
|
4172
4242
|
|
|
4173
4243
|
// src/protocol-flow-policy.ts
|
|
4174
|
-
import { Buffer as
|
|
4244
|
+
import { Buffer as Buffer14 } from "buffer";
|
|
4175
4245
|
var BACKOFF_FIELDS = {
|
|
4176
4246
|
BASE_MS: "base_ms",
|
|
4177
4247
|
MAX_MS: "max_ms",
|
|
@@ -4301,7 +4371,7 @@ function maxActiveOption(value) {
|
|
|
4301
4371
|
return integerOption(value);
|
|
4302
4372
|
}
|
|
4303
4373
|
function isBinaryArgument(value) {
|
|
4304
|
-
return typeof value === "string" ||
|
|
4374
|
+
return typeof value === "string" || Buffer14.isBuffer(value) || value instanceof Uint8Array;
|
|
4305
4375
|
}
|
|
4306
4376
|
function objectField(target, name) {
|
|
4307
4377
|
const existing = Object.hasOwn(target, name) ? target[name] : void 0;
|
|
@@ -4373,7 +4443,7 @@ function commandRequiresOrderedPipelineExecution(args) {
|
|
|
4373
4443
|
}
|
|
4374
4444
|
|
|
4375
4445
|
// src/protocol-compact-request.ts
|
|
4376
|
-
import { Buffer as
|
|
4446
|
+
import { Buffer as Buffer15 } from "buffer";
|
|
4377
4447
|
function compactMsetPayload(args, maxBodyBytes) {
|
|
4378
4448
|
if (args.length % 2 !== 0) throw new FerricStoreError("MSET requires key/value pairs");
|
|
4379
4449
|
const minimum = 6 + args.length * 4;
|
|
@@ -4392,7 +4462,7 @@ function compactMsetPayload(args, maxBodyBytes) {
|
|
|
4392
4462
|
total += 4 + byteLength;
|
|
4393
4463
|
}
|
|
4394
4464
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4395
|
-
const out =
|
|
4465
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4396
4466
|
let offset = writeCompactPipelineHeader(out, 1, args.length / 2);
|
|
4397
4467
|
for (let index = 0; index < args.length; index += 1) {
|
|
4398
4468
|
offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
|
|
@@ -4416,7 +4486,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
|
|
|
4416
4486
|
total += 4 + byteLength;
|
|
4417
4487
|
}
|
|
4418
4488
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4419
|
-
const out =
|
|
4489
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4420
4490
|
let offset = writeCompactPipelineHeader(out, mode, args.length);
|
|
4421
4491
|
for (let index = 0; index < args.length; index += 1) {
|
|
4422
4492
|
offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
|
|
@@ -4426,7 +4496,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
|
|
|
4426
4496
|
function compactPipelinePayload(commands, maxBodyBytes) {
|
|
4427
4497
|
if (commands.length === 0) {
|
|
4428
4498
|
assertCompactPayloadFits(6, maxBodyBytes);
|
|
4429
|
-
const out =
|
|
4499
|
+
const out = Buffer15.allocUnsafe(6);
|
|
4430
4500
|
writeCompactPipelineHeader(out, 128 | 2, 0);
|
|
4431
4501
|
return out;
|
|
4432
4502
|
}
|
|
@@ -4468,7 +4538,7 @@ function compactSetPipelinePayload(commands, maxBodyBytes) {
|
|
|
4468
4538
|
total += 8 + keyByteLength + valueByteLength;
|
|
4469
4539
|
}
|
|
4470
4540
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4471
|
-
const out =
|
|
4541
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4472
4542
|
let offset = writeCompactPipelineHeader(out, 128 | 1, commands.length);
|
|
4473
4543
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4474
4544
|
offset = writeBinaryValue(out, offset, argumentValues[index * 2], argumentByteLengths[index * 2] ?? 0);
|
|
@@ -4503,7 +4573,7 @@ function compactGetPipelinePayload(commands, maxBodyBytes) {
|
|
|
4503
4573
|
total += 4 + keyByteLength;
|
|
4504
4574
|
}
|
|
4505
4575
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4506
|
-
const out =
|
|
4576
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4507
4577
|
let offset = writeCompactPipelineHeader(out, 128 | 2, commands.length);
|
|
4508
4578
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4509
4579
|
offset = writeBinaryValue(out, offset, keys[index], keyByteLengths[index] ?? 0);
|
|
@@ -4544,7 +4614,7 @@ function writeCompactPipelineHeader(out, mode, count) {
|
|
|
4544
4614
|
}
|
|
4545
4615
|
|
|
4546
4616
|
// src/protocol-kv.ts
|
|
4547
|
-
import { Buffer as
|
|
4617
|
+
import { Buffer as Buffer16 } from "buffer";
|
|
4548
4618
|
function collectionProtocolCommand(command, args) {
|
|
4549
4619
|
switch (command) {
|
|
4550
4620
|
case "CAS":
|
|
@@ -4615,8 +4685,8 @@ function stringSetPayload(args) {
|
|
|
4615
4685
|
if (value == null || token === "EX" && value > Math.floor(Number.MAX_SAFE_INTEGER / 1e3)) {
|
|
4616
4686
|
return void 0;
|
|
4617
4687
|
}
|
|
4618
|
-
const
|
|
4619
|
-
setOwnValue2(payload,
|
|
4688
|
+
const field3 = token === "EX" || token === "PX" ? "ttl" : token.toLowerCase();
|
|
4689
|
+
setOwnValue2(payload, field3, token === "EX" ? value * 1e3 : value);
|
|
4620
4690
|
expirySeen = true;
|
|
4621
4691
|
index += 2;
|
|
4622
4692
|
} else if (token === "NX") {
|
|
@@ -4715,25 +4785,25 @@ function hashSetCommand(args) {
|
|
|
4715
4785
|
if (!isBinaryCommandArgument(args[0]) || args.length < 3 || args.length % 2 !== 1) return void 0;
|
|
4716
4786
|
const fields = /* @__PURE__ */ Object.create(null);
|
|
4717
4787
|
for (let index = 1; index < args.length; index += 2) {
|
|
4718
|
-
const
|
|
4788
|
+
const field3 = args[index];
|
|
4719
4789
|
const value = args[index + 1];
|
|
4720
|
-
if (typeof
|
|
4721
|
-
setOwnValue2(fields,
|
|
4790
|
+
if (typeof field3 !== "string" || !isBinaryCommandArgument(value)) return void 0;
|
|
4791
|
+
setOwnValue2(fields, field3, value);
|
|
4722
4792
|
}
|
|
4723
4793
|
return { opcode: COMMAND_OPCODES.HSET, payload: { fields, key: args[0] } };
|
|
4724
4794
|
}
|
|
4725
4795
|
function keyOnlyCommand(opcode, args) {
|
|
4726
4796
|
return args.length === 1 && isBinaryCommandArgument(args[0]) ? { opcode, payload: { key: args[0] } } : void 0;
|
|
4727
4797
|
}
|
|
4728
|
-
function binaryFieldsCommand(opcode, args,
|
|
4798
|
+
function binaryFieldsCommand(opcode, args, field3, length) {
|
|
4729
4799
|
if (args.length !== length || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1])) return void 0;
|
|
4730
|
-
return { opcode, payload: { [
|
|
4800
|
+
return { opcode, payload: { [field3]: args[1], key: args[0] } };
|
|
4731
4801
|
}
|
|
4732
|
-
function binaryListCommand(opcode, args,
|
|
4802
|
+
function binaryListCommand(opcode, args, field3) {
|
|
4733
4803
|
if (!isBinaryCommandArgument(args[0]) || args.length < 2) return void 0;
|
|
4734
4804
|
const values = args.slice(1);
|
|
4735
4805
|
if (!values.every(isBinaryCommandArgument)) return void 0;
|
|
4736
|
-
return { opcode, payload: { [
|
|
4806
|
+
return { opcode, payload: { [field3]: values, key: args[0] } };
|
|
4737
4807
|
}
|
|
4738
4808
|
function listPopCommand(opcode, args) {
|
|
4739
4809
|
if (!isBinaryCommandArgument(args[0]) || args.length !== 1 && args.length !== 2) return void 0;
|
|
@@ -4791,17 +4861,35 @@ function parsedNumber(value) {
|
|
|
4791
4861
|
}
|
|
4792
4862
|
}
|
|
4793
4863
|
function isBinaryCommandArgument(value) {
|
|
4794
|
-
return typeof value === "string" ||
|
|
4864
|
+
return typeof value === "string" || Buffer16.isBuffer(value);
|
|
4795
4865
|
}
|
|
4796
4866
|
function isDirectKvValueArgument(value) {
|
|
4797
4867
|
return isBinaryCommandArgument(value) || typeof value === "object" && value != null;
|
|
4798
4868
|
}
|
|
4799
4869
|
function binaryToken(value) {
|
|
4800
|
-
return typeof value === "string" ? value.toUpperCase() :
|
|
4870
|
+
return typeof value === "string" ? value.toUpperCase() : Buffer16.isBuffer(value) ? value.toString("utf8").toUpperCase() : void 0;
|
|
4871
|
+
}
|
|
4872
|
+
|
|
4873
|
+
// src/protocol-value.ts
|
|
4874
|
+
import { Buffer as Buffer17 } from "buffer";
|
|
4875
|
+
|
|
4876
|
+
// src/protocol-map-key.ts
|
|
4877
|
+
import { isUtf8 } from "buffer";
|
|
4878
|
+
function setProtocolMapEntry(target, encodedKey, value) {
|
|
4879
|
+
if (typeof encodedKey === "string" && !encodedKey.isWellFormed()) {
|
|
4880
|
+
throw new FerricStoreError("native protocol map key must be valid UTF-8");
|
|
4881
|
+
}
|
|
4882
|
+
if (typeof encodedKey !== "string" && !isUtf8(encodedKey)) {
|
|
4883
|
+
throw new FerricStoreError("native protocol map key must be valid UTF-8");
|
|
4884
|
+
}
|
|
4885
|
+
const key = typeof encodedKey === "string" ? encodedKey : encodedKey.toString("utf8");
|
|
4886
|
+
if (Object.hasOwn(target, key)) {
|
|
4887
|
+
throw new FerricStoreError(`native protocol response contains duplicate map key ${JSON.stringify(key)}`);
|
|
4888
|
+
}
|
|
4889
|
+
setOwnValue2(target, key, value);
|
|
4801
4890
|
}
|
|
4802
4891
|
|
|
4803
4892
|
// src/protocol-value.ts
|
|
4804
|
-
import { Buffer as Buffer16 } from "buffer";
|
|
4805
4893
|
function planValueWithLimit(value, maxBytes) {
|
|
4806
4894
|
const budget = {
|
|
4807
4895
|
maxBytes,
|
|
@@ -4856,7 +4944,7 @@ function planContainerValue(value, budget, ancestors, depth) {
|
|
|
4856
4944
|
let byteLength = 5;
|
|
4857
4945
|
let index = 0;
|
|
4858
4946
|
for (const [key, item] of entries) {
|
|
4859
|
-
const keyByteLength =
|
|
4947
|
+
const keyByteLength = Buffer17.byteLength(key);
|
|
4860
4948
|
consumeEncodeBytes(budget, 4 + keyByteLength);
|
|
4861
4949
|
const valuePlan = planValueAt(item, budget, ancestors, depth + 1);
|
|
4862
4950
|
entryPlans[index] = { key, keyByteLength, value: valuePlan };
|
|
@@ -4895,17 +4983,21 @@ function planScalarValue(value, budget) {
|
|
|
4895
4983
|
return { byteLength: 9, tag: 3, value: BigInt(value) };
|
|
4896
4984
|
}
|
|
4897
4985
|
if (typeof value === "bigint") {
|
|
4898
|
-
if (value
|
|
4899
|
-
|
|
4986
|
+
if (value >= MIN_I642 && value <= MAX_I642) {
|
|
4987
|
+
consumeEncodeBytes(budget, 9);
|
|
4988
|
+
return { byteLength: 9, tag: 3, value };
|
|
4900
4989
|
}
|
|
4901
|
-
|
|
4902
|
-
|
|
4990
|
+
if (value > MAX_I642 && value <= MAX_U64) {
|
|
4991
|
+
consumeEncodeBytes(budget, 9);
|
|
4992
|
+
return { byteLength: 9, tag: 8, value };
|
|
4993
|
+
}
|
|
4994
|
+
throw new FerricStoreError("integer exceeds the signed or unsigned 64-bit native range");
|
|
4903
4995
|
}
|
|
4904
4996
|
if (typeof value === "number") {
|
|
4905
4997
|
consumeEncodeBytes(budget, 9);
|
|
4906
4998
|
return { byteLength: 9, tag: 7, value };
|
|
4907
4999
|
}
|
|
4908
|
-
if (typeof value === "string" ||
|
|
5000
|
+
if (typeof value === "string" || Buffer17.isBuffer(value) || value instanceof Uint8Array) {
|
|
4909
5001
|
const valueByteLength = binaryValueByteLength(value);
|
|
4910
5002
|
const byteLength = 5 + valueByteLength;
|
|
4911
5003
|
consumeEncodeBytes(budget, byteLength);
|
|
@@ -4929,7 +5021,7 @@ function writeValuePlan(output, start, plan) {
|
|
|
4929
5021
|
offset += 4;
|
|
4930
5022
|
if (typeof plan.value === "string") {
|
|
4931
5023
|
output.write(plan.value, offset, plan.valueByteLength, "utf8");
|
|
4932
|
-
} else if (
|
|
5024
|
+
} else if (Buffer17.isBuffer(plan.value)) {
|
|
4933
5025
|
plan.value.copy(output, offset);
|
|
4934
5026
|
} else {
|
|
4935
5027
|
output.set(plan.value, offset);
|
|
@@ -4954,6 +5046,9 @@ function writeValuePlan(output, start, plan) {
|
|
|
4954
5046
|
case 7:
|
|
4955
5047
|
output.writeDoubleBE(plan.value, offset);
|
|
4956
5048
|
return offset + 8;
|
|
5049
|
+
case 8:
|
|
5050
|
+
output.writeBigUInt64BE(plan.value, offset);
|
|
5051
|
+
return offset + 8;
|
|
4957
5052
|
}
|
|
4958
5053
|
}
|
|
4959
5054
|
function consumeEncodeBytes(budget, bytes2) {
|
|
@@ -5011,7 +5106,7 @@ function decodeValueAt(data, offset, limits, budget, depth) {
|
|
|
5011
5106
|
const key = readBinary(data, offset);
|
|
5012
5107
|
offset = key.offset;
|
|
5013
5108
|
const item = decodeValueAt(data, offset, limits, budget, depth + 1);
|
|
5014
|
-
|
|
5109
|
+
setProtocolMapEntry(value, key.value, item.value);
|
|
5015
5110
|
offset = item.offset;
|
|
5016
5111
|
}
|
|
5017
5112
|
return { value, offset };
|
|
@@ -5020,6 +5115,14 @@ function decodeValueAt(data, offset, limits, budget, depth) {
|
|
|
5020
5115
|
requireAvailable(data, offset, 8);
|
|
5021
5116
|
return { value: data.readDoubleBE(offset), offset: offset + 8 };
|
|
5022
5117
|
}
|
|
5118
|
+
if (tag === 8) {
|
|
5119
|
+
requireAvailable(data, offset, 8);
|
|
5120
|
+
const integer2 = data.readBigUInt64BE(offset);
|
|
5121
|
+
return {
|
|
5122
|
+
value: integer2 <= MAX_SAFE_INTEGER_BIGINT ? Number(integer2) : integer2,
|
|
5123
|
+
offset: offset + 8
|
|
5124
|
+
};
|
|
5125
|
+
}
|
|
5023
5126
|
throw new FerricStoreError(`unknown protocol value tag ${tag}`);
|
|
5024
5127
|
}
|
|
5025
5128
|
function decodeValueWithBudget(data, offset, budget) {
|
|
@@ -5063,20 +5166,20 @@ function requireAvailable(data, offset, size) {
|
|
|
5063
5166
|
}
|
|
5064
5167
|
|
|
5065
5168
|
// src/key-slot-validation.ts
|
|
5066
|
-
import { Buffer as
|
|
5169
|
+
import { Buffer as Buffer19 } from "buffer";
|
|
5067
5170
|
|
|
5068
5171
|
// src/topology-utilities.ts
|
|
5069
|
-
import { Buffer as
|
|
5172
|
+
import { Buffer as Buffer18 } from "buffer";
|
|
5070
5173
|
function isPlainObject3(value) {
|
|
5071
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
5174
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer18.isBuffer(value);
|
|
5072
5175
|
}
|
|
5073
5176
|
function getField(source, ...keys) {
|
|
5074
5177
|
if (source instanceof Map) {
|
|
5075
5178
|
for (const key of keys) {
|
|
5076
5179
|
if (source.has(key)) return source.get(key);
|
|
5077
|
-
const bufferKey =
|
|
5180
|
+
const bufferKey = Buffer18.from(key);
|
|
5078
5181
|
for (const [itemKey, value] of source.entries()) {
|
|
5079
|
-
if (
|
|
5182
|
+
if (Buffer18.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
|
|
5080
5183
|
}
|
|
5081
5184
|
}
|
|
5082
5185
|
return void 0;
|
|
@@ -5090,14 +5193,14 @@ function getField(source, ...keys) {
|
|
|
5090
5193
|
}
|
|
5091
5194
|
function textOrUndefined(value) {
|
|
5092
5195
|
if (typeof value === "string") return value;
|
|
5093
|
-
if (
|
|
5196
|
+
if (Buffer18.isBuffer(value)) return value.toString("utf8");
|
|
5094
5197
|
return void 0;
|
|
5095
5198
|
}
|
|
5096
5199
|
function numberOrUndefined(value) {
|
|
5097
5200
|
return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
|
|
5098
5201
|
}
|
|
5099
|
-
function nativeEventName(
|
|
5100
|
-
return textOrUndefined(getField(
|
|
5202
|
+
function nativeEventName(event2) {
|
|
5203
|
+
return textOrUndefined(getField(event2.value, "event"))?.toUpperCase();
|
|
5101
5204
|
}
|
|
5102
5205
|
function endpointFromRange(item) {
|
|
5103
5206
|
const endpointValue = getField(item, "endpoint");
|
|
@@ -5265,7 +5368,7 @@ function stringHashRange(key) {
|
|
|
5265
5368
|
var validatedCommands = /* @__PURE__ */ new WeakSet();
|
|
5266
5369
|
function assertAtomicKeyValueCommandSharesSlot(args) {
|
|
5267
5370
|
const value = args[0];
|
|
5268
|
-
const command = (typeof value === "string" ? value :
|
|
5371
|
+
const command = (typeof value === "string" ? value : Buffer19.isBuffer(value) ? value.toString("utf8") : "").toUpperCase();
|
|
5269
5372
|
if (command === "MSET" || command === "MSETNX") {
|
|
5270
5373
|
assertKeyValueCommandSharesSlot(args, command);
|
|
5271
5374
|
}
|
|
@@ -5275,7 +5378,7 @@ function assertKeyValueCommandSharesSlot(args, command) {
|
|
|
5275
5378
|
let expectedSlot;
|
|
5276
5379
|
for (let index = 1; index < args.length; index += 2) {
|
|
5277
5380
|
const key = args[index];
|
|
5278
|
-
if (typeof key !== "string" && !
|
|
5381
|
+
if (typeof key !== "string" && !Buffer19.isBuffer(key)) return;
|
|
5279
5382
|
const slot = routingSlotForKey(key);
|
|
5280
5383
|
expectedSlot ??= slot;
|
|
5281
5384
|
if (slot !== expectedSlot) {
|
|
@@ -5286,62 +5389,202 @@ function assertKeyValueCommandSharesSlot(args, command) {
|
|
|
5286
5389
|
}
|
|
5287
5390
|
|
|
5288
5391
|
// src/protocol-response.ts
|
|
5289
|
-
import { Buffer as
|
|
5392
|
+
import { Buffer as Buffer26 } from "buffer";
|
|
5290
5393
|
|
|
5291
5394
|
// src/protocol-compact-response.ts
|
|
5292
|
-
import { Buffer as
|
|
5395
|
+
import { Buffer as Buffer25 } from "buffer";
|
|
5293
5396
|
|
|
5294
5397
|
// src/native-negotiation.ts
|
|
5295
|
-
import { Buffer as
|
|
5398
|
+
import { Buffer as Buffer20 } from "buffer";
|
|
5296
5399
|
var EMPTY_COMPACT_RESPONSE_OPCODES = /* @__PURE__ */ new Map();
|
|
5297
5400
|
function nativeNegotiation(value) {
|
|
5298
5401
|
const capabilities = field(value, "capabilities") ?? value;
|
|
5299
5402
|
const limits = field(capabilities, "limits");
|
|
5300
|
-
const
|
|
5403
|
+
const rawResponseCodecs = field(capabilities, "response_codecs");
|
|
5404
|
+
const responseCodecs = rawResponseCodecs == null ? void 0 : requiredMap(rawResponseCodecs, "HELLO response_codecs");
|
|
5405
|
+
const schemas = requiredMap(field(capabilities, "schemas"), "HELLO schemas");
|
|
5301
5406
|
const maxResponseBytes = positiveSafeInteger3(field(limits, "max_response_bytes"));
|
|
5302
5407
|
return {
|
|
5303
5408
|
compactResponseOpcodes: parseCompactResponseOpcodes(
|
|
5304
5409
|
field(responseCodecs, "compact_response_opcodes")
|
|
5305
5410
|
),
|
|
5411
|
+
flowQuery: parseFlowQueryNegotiation(capabilities, schemas),
|
|
5306
5412
|
...maxResponseBytes == null ? {} : { maxResponseBytes }
|
|
5307
5413
|
};
|
|
5308
5414
|
}
|
|
5415
|
+
var REQUIRED_FLOW_QUERY_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
5416
|
+
"flow_query_v1",
|
|
5417
|
+
"flow_query_result_projection_v1",
|
|
5418
|
+
"flow_explain_v1",
|
|
5419
|
+
"flow_explain_analyze_v1",
|
|
5420
|
+
"flow_composite_index_v1",
|
|
5421
|
+
"flow_query_index_status_v1"
|
|
5422
|
+
]);
|
|
5423
|
+
var REQUIRED_FLOW_QUERY_SHAPES = /* @__PURE__ */ new Set([
|
|
5424
|
+
"runs_by_run_id_record",
|
|
5425
|
+
"runs_by_partition_and_run_id_record",
|
|
5426
|
+
"runs_by_partition_predicates_ordered_records",
|
|
5427
|
+
"runs_by_partition_type_state_ordered_records",
|
|
5428
|
+
"runs_by_partition_type_terminals_ordered_records",
|
|
5429
|
+
"runs_by_partition_metadata_ordered_records",
|
|
5430
|
+
"runs_by_partition_type_running_lease_deadline_ordered_records",
|
|
5431
|
+
"runs_by_partition_parent_ordered_records",
|
|
5432
|
+
"runs_by_partition_root_ordered_records",
|
|
5433
|
+
"runs_by_partition_correlation_ordered_records",
|
|
5434
|
+
"runs_by_partition_predicates_count",
|
|
5435
|
+
"events_by_run_id_ordered_records"
|
|
5436
|
+
]);
|
|
5437
|
+
function parseFlowQueryNegotiation(capabilities, schemas) {
|
|
5438
|
+
const manifest = requiredMap(field(capabilities, "flow_query"), "HELLO flow_query");
|
|
5439
|
+
const requestContract = requiredBoundedText(manifest, "request_contract");
|
|
5440
|
+
const resultContract = requiredBoundedText(manifest, "result_contract");
|
|
5441
|
+
const explainContract = requiredBoundedText(manifest, "explain_contract");
|
|
5442
|
+
const indexStatusContract = requiredBoundedText(manifest, "index_status_contract");
|
|
5443
|
+
requireEqual(requestContract, "ferric.flow.query.request/v1", "flow_query request_contract");
|
|
5444
|
+
requireEqual(resultContract, "ferric.flow.query.result/v1", "flow_query result_contract");
|
|
5445
|
+
requireEqual(explainContract, "ferric.flow.explain/v1", "flow_query explain_contract");
|
|
5446
|
+
requireEqual(
|
|
5447
|
+
indexStatusContract,
|
|
5448
|
+
"ferric.flow.query.indexes/v1",
|
|
5449
|
+
"flow_query index_status_contract"
|
|
5450
|
+
);
|
|
5451
|
+
const queryCapabilities = boundedTextSet(manifest, "capabilities", 64);
|
|
5452
|
+
const languageVersions = boundedTextSet(manifest, "language_versions", 16);
|
|
5453
|
+
const shapes = boundedTextSet(manifest, "shapes", 128);
|
|
5454
|
+
requireMembers(queryCapabilities, REQUIRED_FLOW_QUERY_CAPABILITIES, "flow_query capability");
|
|
5455
|
+
requireMembers(languageVersions, /* @__PURE__ */ new Set(["FQL1"]), "flow_query language");
|
|
5456
|
+
requireMembers(shapes, REQUIRED_FLOW_QUERY_SHAPES, "flow_query shape");
|
|
5457
|
+
const schema = requiredMap(field(schemas, "FLOW.QUERY"), "HELLO FLOW.QUERY schema");
|
|
5458
|
+
const fields = boundedTextSet(schema, "fields", 64);
|
|
5459
|
+
requireMembers(
|
|
5460
|
+
fields,
|
|
5461
|
+
/* @__PURE__ */ new Set(["version", "query", "params", "deadline_ms"]),
|
|
5462
|
+
"FLOW.QUERY schema field"
|
|
5463
|
+
);
|
|
5464
|
+
const required = boundedTextSet(schema, "required", 16);
|
|
5465
|
+
if (required.size !== 2 || !required.has("version") || !required.has("query")) {
|
|
5466
|
+
throw incompatibleServer("FLOW.QUERY schema must require exactly version and query");
|
|
5467
|
+
}
|
|
5468
|
+
return {
|
|
5469
|
+
requestContract: "ferric.flow.query.request/v1",
|
|
5470
|
+
resultContract: "ferric.flow.query.result/v1",
|
|
5471
|
+
explainContract: "ferric.flow.explain/v1",
|
|
5472
|
+
indexStatusContract: "ferric.flow.query.indexes/v1",
|
|
5473
|
+
capabilities: queryCapabilities,
|
|
5474
|
+
languageVersions,
|
|
5475
|
+
shapes
|
|
5476
|
+
};
|
|
5477
|
+
}
|
|
5478
|
+
function requiredMap(value, context) {
|
|
5479
|
+
if (value instanceof Map) return value;
|
|
5480
|
+
if (typeof value === "object" && value != null && !Array.isArray(value) && !Buffer20.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
5481
|
+
return value;
|
|
5482
|
+
}
|
|
5483
|
+
throw incompatibleServer(`${context} is missing or invalid`);
|
|
5484
|
+
}
|
|
5485
|
+
function requiredBoundedText(mapping, name) {
|
|
5486
|
+
const value = strictText(field(mapping, name));
|
|
5487
|
+
if (value == null || value.length === 0 || Buffer20.byteLength(value) > 256) {
|
|
5488
|
+
throw incompatibleServer(`HELLO flow_query ${name} must be bounded non-empty text`);
|
|
5489
|
+
}
|
|
5490
|
+
return value;
|
|
5491
|
+
}
|
|
5492
|
+
function boundedTextSet(mapping, name, maximum) {
|
|
5493
|
+
const raw = field(mapping, name);
|
|
5494
|
+
if (!Array.isArray(raw) || raw.length < 1 || raw.length > maximum) {
|
|
5495
|
+
throw incompatibleServer(`HELLO ${name} must contain 1..${maximum} entries`);
|
|
5496
|
+
}
|
|
5497
|
+
const result = /* @__PURE__ */ new Set();
|
|
5498
|
+
for (let index = 0; index < raw.length; index += 1) {
|
|
5499
|
+
if (!Object.hasOwn(raw, index)) throw incompatibleServer(`HELLO ${name} must be dense`);
|
|
5500
|
+
const item = strictText(raw[index]);
|
|
5501
|
+
if (item == null || item.length === 0 || Buffer20.byteLength(item) > 256) {
|
|
5502
|
+
throw incompatibleServer(`HELLO ${name} contains invalid text`);
|
|
5503
|
+
}
|
|
5504
|
+
if (result.has(item)) throw incompatibleServer(`HELLO ${name} contains duplicate ${item}`);
|
|
5505
|
+
result.add(item);
|
|
5506
|
+
}
|
|
5507
|
+
return result;
|
|
5508
|
+
}
|
|
5509
|
+
function requireMembers(actual, required, context) {
|
|
5510
|
+
for (const item of required) {
|
|
5511
|
+
if (!actual.has(item)) throw incompatibleServer(`missing ${context} ${JSON.stringify(item)}`);
|
|
5512
|
+
}
|
|
5513
|
+
}
|
|
5514
|
+
function requireEqual(actual, expected, context) {
|
|
5515
|
+
if (actual !== expected) throw incompatibleServer(`${context} must be ${JSON.stringify(expected)}`);
|
|
5516
|
+
}
|
|
5517
|
+
function strictText(value) {
|
|
5518
|
+
if (typeof value === "string") return value;
|
|
5519
|
+
if (Buffer20.isBuffer(value) || value instanceof Uint8Array) {
|
|
5520
|
+
try {
|
|
5521
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
5522
|
+
} catch {
|
|
5523
|
+
return void 0;
|
|
5524
|
+
}
|
|
5525
|
+
}
|
|
5526
|
+
return void 0;
|
|
5527
|
+
}
|
|
5528
|
+
function incompatibleServer(message) {
|
|
5529
|
+
return new FerricStoreError(`incompatible FerricStore server: ${message}`);
|
|
5530
|
+
}
|
|
5309
5531
|
function compactResponseOpcodeSupports(capabilities, codec, opcode) {
|
|
5310
5532
|
return capabilities?.get(codec)?.has(opcode) === true;
|
|
5311
5533
|
}
|
|
5312
5534
|
function parseCompactResponseOpcodes(value) {
|
|
5535
|
+
if (value == null) return EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
5313
5536
|
const entries = mapEntries(value);
|
|
5314
|
-
if (entries == null)
|
|
5537
|
+
if (entries == null) {
|
|
5538
|
+
throw incompatibleServer("HELLO compact_response_opcodes must be a map");
|
|
5539
|
+
}
|
|
5540
|
+
if (entries.length > 32) {
|
|
5541
|
+
throw incompatibleServer("HELLO compact_response_opcodes supports at most 32 codecs");
|
|
5542
|
+
}
|
|
5315
5543
|
const result = /* @__PURE__ */ new Map();
|
|
5544
|
+
let totalOpcodes = 0;
|
|
5316
5545
|
for (const [rawName, rawOpcodes] of entries) {
|
|
5317
|
-
const name =
|
|
5318
|
-
if (name == null || name.length === 0 ||
|
|
5546
|
+
const name = strictText(rawName);
|
|
5547
|
+
if (name == null || name.length === 0 || Buffer20.byteLength(name) > 128) {
|
|
5548
|
+
throw incompatibleServer("HELLO compact_response_opcodes contains an invalid codec name");
|
|
5549
|
+
}
|
|
5550
|
+
if (result.has(name)) {
|
|
5551
|
+
throw incompatibleServer(`HELLO compact_response_opcodes contains duplicate codec ${name}`);
|
|
5552
|
+
}
|
|
5553
|
+
if (!Array.isArray(rawOpcodes)) {
|
|
5554
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} must be an array`);
|
|
5555
|
+
}
|
|
5556
|
+
totalOpcodes += rawOpcodes.length;
|
|
5557
|
+
if (totalOpcodes > 1024) {
|
|
5558
|
+
throw incompatibleServer("HELLO compact_response_opcodes supports at most 1024 opcodes");
|
|
5559
|
+
}
|
|
5319
5560
|
const opcodes = /* @__PURE__ */ new Set();
|
|
5320
|
-
let valid = true;
|
|
5321
5561
|
for (let index = 0; index < rawOpcodes.length; index += 1) {
|
|
5322
5562
|
if (!Object.hasOwn(rawOpcodes, index)) {
|
|
5323
|
-
|
|
5324
|
-
break;
|
|
5563
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} must be dense`);
|
|
5325
5564
|
}
|
|
5326
|
-
const opcode =
|
|
5565
|
+
const opcode = strictUnsigned16(rawOpcodes[index]);
|
|
5327
5566
|
if (opcode == null) {
|
|
5328
|
-
|
|
5329
|
-
|
|
5567
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} has invalid opcode`);
|
|
5568
|
+
}
|
|
5569
|
+
if (opcodes.has(opcode)) {
|
|
5570
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} has duplicate opcode`);
|
|
5330
5571
|
}
|
|
5331
5572
|
opcodes.add(opcode);
|
|
5332
5573
|
}
|
|
5333
|
-
|
|
5574
|
+
result.set(name, opcodes);
|
|
5334
5575
|
}
|
|
5335
5576
|
return result;
|
|
5336
5577
|
}
|
|
5337
5578
|
function mapEntries(value) {
|
|
5338
5579
|
if (value instanceof Map) return [...value.entries()];
|
|
5339
|
-
if (typeof value !== "object" || value == null || Array.isArray(value)) return void 0;
|
|
5580
|
+
if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer20.isBuffer(value) || value instanceof Uint8Array) return void 0;
|
|
5340
5581
|
return Object.entries(value);
|
|
5341
5582
|
}
|
|
5342
|
-
function
|
|
5343
|
-
|
|
5344
|
-
|
|
5583
|
+
function strictUnsigned16(value) {
|
|
5584
|
+
if (typeof value === "bigint") {
|
|
5585
|
+
return value >= 0n && value <= 0xffffn ? Number(value) : void 0;
|
|
5586
|
+
}
|
|
5587
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 65535 ? value : void 0;
|
|
5345
5588
|
}
|
|
5346
5589
|
function positiveSafeInteger3(value) {
|
|
5347
5590
|
const parsed = nonNegativeSafeInteger2(value);
|
|
@@ -5360,8 +5603,8 @@ function nonNegativeSafeInteger2(value) {
|
|
|
5360
5603
|
}
|
|
5361
5604
|
function text2(value) {
|
|
5362
5605
|
if (typeof value === "string") return value;
|
|
5363
|
-
if (
|
|
5364
|
-
return
|
|
5606
|
+
if (Buffer20.isBuffer(value) || value instanceof Uint8Array) {
|
|
5607
|
+
return Buffer20.from(value).toString("utf8");
|
|
5365
5608
|
}
|
|
5366
5609
|
return void 0;
|
|
5367
5610
|
}
|
|
@@ -5432,7 +5675,7 @@ function readCompactBinaryMap(data, offset, budget) {
|
|
|
5432
5675
|
for (let index = 0; index < count; index += 1) {
|
|
5433
5676
|
const key = readBinary(data, offset);
|
|
5434
5677
|
const value = readBinary(data, key.offset);
|
|
5435
|
-
|
|
5678
|
+
setProtocolMapEntry(values, key.value, value.value);
|
|
5436
5679
|
offset = value.offset;
|
|
5437
5680
|
}
|
|
5438
5681
|
return { value: values, offset };
|
|
@@ -5448,52 +5691,287 @@ function requireCompactContainer(count, budget) {
|
|
|
5448
5691
|
consumeDecodeItems(count, budget);
|
|
5449
5692
|
}
|
|
5450
5693
|
|
|
5451
|
-
// src/protocol-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
const
|
|
5457
|
-
if (
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
if (tag === COMPACT_KV_GET && supports(hints, "kv_get_v1", opcode)) {
|
|
5465
|
-
return { found: true, value: decodeCompactKvGet(body) };
|
|
5466
|
-
}
|
|
5467
|
-
if ((tag === COMPACT_KV_MGET || tag === COMPACT_KV_MGET_FIXED) && (supports(hints, "kv_mget_v1", opcode) || pipelineValues)) {
|
|
5468
|
-
const values = tag === COMPACT_KV_MGET ? decodeCompactMget(body, budget) : decodeCompactMgetFixed(body, budget);
|
|
5469
|
-
return {
|
|
5470
|
-
found: true,
|
|
5471
|
-
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
5472
|
-
};
|
|
5473
|
-
}
|
|
5474
|
-
if (tag === COMPACT_INTEGER_LIST && pipelineValues) {
|
|
5475
|
-
return { found: true, value: markCompactPipelineDecoded(decodeCompactIntegerList(body, budget)) };
|
|
5476
|
-
}
|
|
5477
|
-
if (tag === COMPACT_BINARY_LIST_LIST && pipelineValues) {
|
|
5478
|
-
return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryListList(body, budget)) };
|
|
5694
|
+
// src/protocol-error-message.ts
|
|
5695
|
+
import { Buffer as Buffer22 } from "buffer";
|
|
5696
|
+
var MAX_ERROR_MESSAGE_CHARS = 4096;
|
|
5697
|
+
var MAX_ERROR_TEXT_BYTES = MAX_ERROR_MESSAGE_CHARS * 4;
|
|
5698
|
+
function protocolErrorMessage(status, value) {
|
|
5699
|
+
const direct = errorText(value);
|
|
5700
|
+
if (direct != null) return truncate(direct);
|
|
5701
|
+
return truncate(`ERR native request failed status=${status}: ${errorDescription(value)}`);
|
|
5702
|
+
}
|
|
5703
|
+
function errorText(value) {
|
|
5704
|
+
if (typeof value === "string") return value;
|
|
5705
|
+
if (Buffer22.isBuffer(value) || value instanceof Uint8Array) {
|
|
5706
|
+
return boundedBinaryText(value);
|
|
5479
5707
|
}
|
|
5480
|
-
if (
|
|
5481
|
-
|
|
5708
|
+
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5709
|
+
const message = value.message;
|
|
5710
|
+
if (typeof message === "string") return message;
|
|
5711
|
+
if (Buffer22.isBuffer(message) || message instanceof Uint8Array) {
|
|
5712
|
+
return boundedBinaryText(message);
|
|
5713
|
+
}
|
|
5714
|
+
if (message == null || typeof message !== "object") return String(message);
|
|
5482
5715
|
}
|
|
5483
|
-
|
|
5484
|
-
|
|
5716
|
+
return void 0;
|
|
5717
|
+
}
|
|
5718
|
+
function boundedBinaryText(value) {
|
|
5719
|
+
const bytes2 = Buffer22.isBuffer(value) ? value : Buffer22.from(value.buffer, value.byteOffset, value.byteLength);
|
|
5720
|
+
return bytes2.subarray(0, MAX_ERROR_TEXT_BYTES).toString("utf8");
|
|
5721
|
+
}
|
|
5722
|
+
function errorDescription(value) {
|
|
5723
|
+
if (Array.isArray(value)) return `[array length=${value.length}]`;
|
|
5724
|
+
if (value instanceof Map) return `[map size=${value.size}]`;
|
|
5725
|
+
if (typeof value === "object" && value != null) return "[object]";
|
|
5726
|
+
return String(value);
|
|
5727
|
+
}
|
|
5728
|
+
function truncate(value) {
|
|
5729
|
+
return value.length <= MAX_ERROR_MESSAGE_CHARS ? value : `${value.slice(0, MAX_ERROR_MESSAGE_CHARS - 1)}\u2026`;
|
|
5730
|
+
}
|
|
5731
|
+
|
|
5732
|
+
// src/protocol-flow-query-result.ts
|
|
5733
|
+
import { Buffer as Buffer24 } from "buffer";
|
|
5734
|
+
|
|
5735
|
+
// src/protocol-binary-detacher.ts
|
|
5736
|
+
import { Buffer as Buffer23 } from "buffer";
|
|
5737
|
+
var MIN_PINNED_BACKING_BYTES = 64;
|
|
5738
|
+
function detachDecodedBinary(value, backingBytes) {
|
|
5739
|
+
if (Buffer23.isBuffer(value)) return detachBuffer(value, backingBytes);
|
|
5740
|
+
if (Array.isArray(value)) {
|
|
5741
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
5742
|
+
value[index] = detachDecodedBinary(value[index], backingBytes);
|
|
5743
|
+
}
|
|
5744
|
+
return value;
|
|
5485
5745
|
}
|
|
5486
|
-
if (
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
found: true,
|
|
5490
|
-
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
5491
|
-
};
|
|
5746
|
+
if (!isDecodedRecord(value)) return value;
|
|
5747
|
+
for (const key of Object.keys(value)) {
|
|
5748
|
+
setOwnValue2(value, key, detachDecodedBinary(value[key], backingBytes));
|
|
5492
5749
|
}
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5750
|
+
return value;
|
|
5751
|
+
}
|
|
5752
|
+
function detachBuffer(value, backingBytes) {
|
|
5753
|
+
if (backingBytes <= Math.max(MIN_PINNED_BACKING_BYTES, value.byteLength * 2)) {
|
|
5754
|
+
return value;
|
|
5755
|
+
}
|
|
5756
|
+
if (value.byteLength === 0) return Buffer23.alloc(0);
|
|
5757
|
+
const detached = Buffer23.allocUnsafeSlow(value.byteLength);
|
|
5758
|
+
value.copy(detached);
|
|
5759
|
+
return detached;
|
|
5760
|
+
}
|
|
5761
|
+
function isDecodedRecord(value) {
|
|
5762
|
+
if (typeof value !== "object" || value == null) return false;
|
|
5763
|
+
const prototype = Object.getPrototypeOf(value);
|
|
5764
|
+
return prototype === Object.prototype || prototype === null;
|
|
5765
|
+
}
|
|
5766
|
+
|
|
5767
|
+
// src/protocol-flow-query-result.ts
|
|
5768
|
+
var CONTRACT = "ferric.flow.query.result/v1";
|
|
5769
|
+
var MAX_RECORDS = 100;
|
|
5770
|
+
var MAX_CURSOR_BYTES = 4096;
|
|
5771
|
+
var RECORD_FIELDS = [
|
|
5772
|
+
"id",
|
|
5773
|
+
"type",
|
|
5774
|
+
"state",
|
|
5775
|
+
"version",
|
|
5776
|
+
"priority",
|
|
5777
|
+
"partition_key",
|
|
5778
|
+
"created_at_ms",
|
|
5779
|
+
"updated_at_ms",
|
|
5780
|
+
"next_run_at_ms",
|
|
5781
|
+
"lease_deadline_ms",
|
|
5782
|
+
"attempts",
|
|
5783
|
+
"run_state",
|
|
5784
|
+
"max_active_ms",
|
|
5785
|
+
"parent_flow_id",
|
|
5786
|
+
"root_flow_id",
|
|
5787
|
+
"correlation_id",
|
|
5788
|
+
"attributes",
|
|
5789
|
+
"state_meta",
|
|
5790
|
+
"event_id",
|
|
5791
|
+
"fields"
|
|
5792
|
+
];
|
|
5793
|
+
var RECORD_FIELD_MASK = (1 << RECORD_FIELDS.length) - 1;
|
|
5794
|
+
var QUALITY_VALUES = [
|
|
5795
|
+
["authoritative", "projected_exact", "exact", "not_applicable"],
|
|
5796
|
+
["current", "projection_watermark", "not_applicable"],
|
|
5797
|
+
["complete", "unavailable"],
|
|
5798
|
+
["none", "complete", "authenticated_seek", "live_seek"]
|
|
5799
|
+
];
|
|
5800
|
+
var QUALITY_FIELDS = ["exactness", "freshness", "coverage", "pagination"];
|
|
5801
|
+
var USAGE_FIELDS = [
|
|
5802
|
+
"range_seeks",
|
|
5803
|
+
"range_pages",
|
|
5804
|
+
"scanned_entries",
|
|
5805
|
+
"scanned_bytes",
|
|
5806
|
+
"hydrated_records",
|
|
5807
|
+
"residual_checks",
|
|
5808
|
+
"duplicate_entries",
|
|
5809
|
+
"result_records",
|
|
5810
|
+
"response_bytes",
|
|
5811
|
+
"memory_high_water_bytes",
|
|
5812
|
+
"wall_time_us"
|
|
5813
|
+
];
|
|
5814
|
+
function decodeCompactFlowQueryResult(data, budget) {
|
|
5815
|
+
requireAvailable(data, 0, 2 + QUALITY_FIELDS.length + USAGE_FIELDS.length * 8);
|
|
5816
|
+
if (data.readUInt8(0) !== COMPACT_FLOW_QUERY_RESULT) {
|
|
5817
|
+
throw new FerricStoreError("expected compact FLOW.QUERY result");
|
|
5818
|
+
}
|
|
5819
|
+
const kind = data.readUInt8(1);
|
|
5820
|
+
let offset = 2;
|
|
5821
|
+
const quality = {};
|
|
5822
|
+
for (let index = 0; index < QUALITY_FIELDS.length; index += 1) {
|
|
5823
|
+
const field3 = QUALITY_FIELDS[index];
|
|
5824
|
+
const values = QUALITY_VALUES[index];
|
|
5825
|
+
if (field3 == null || values == null) throw new FerricStoreError("invalid compact FLOW.QUERY quality schema");
|
|
5826
|
+
const value = values[data.readUInt8(offset)];
|
|
5827
|
+
if (value == null) throw new FerricStoreError("invalid compact FLOW.QUERY quality code");
|
|
5828
|
+
quality[field3] = Buffer24.from(value);
|
|
5829
|
+
offset += 1;
|
|
5830
|
+
}
|
|
5831
|
+
const usage = {};
|
|
5832
|
+
for (const field3 of USAGE_FIELDS) {
|
|
5833
|
+
const read = readU64(data, offset);
|
|
5834
|
+
usage[field3] = read.value;
|
|
5835
|
+
offset = read.offset;
|
|
5836
|
+
}
|
|
5837
|
+
let result;
|
|
5838
|
+
if (kind === 0) {
|
|
5839
|
+
const page = readPage(data, offset);
|
|
5840
|
+
offset = page.offset;
|
|
5841
|
+
requireAvailable(data, offset, 4);
|
|
5842
|
+
const count = data.readUInt32BE(offset);
|
|
5843
|
+
offset += 4;
|
|
5844
|
+
if (count > MAX_RECORDS) throw new FerricStoreError("compact FLOW.QUERY page exceeds 100 records");
|
|
5845
|
+
consumeDecodeItems(count, budget);
|
|
5846
|
+
const records = new Array(count);
|
|
5847
|
+
for (let index = 0; index < count; index += 1) {
|
|
5848
|
+
const read = readRecord(data, offset, budget);
|
|
5849
|
+
records[index] = read.value;
|
|
5850
|
+
offset = read.offset;
|
|
5851
|
+
}
|
|
5852
|
+
result = { version: Buffer24.from(CONTRACT), records, page: page.value, quality, usage };
|
|
5853
|
+
} else if (kind === 1) {
|
|
5854
|
+
const count = readU64(data, offset);
|
|
5855
|
+
offset = count.offset;
|
|
5856
|
+
result = {
|
|
5857
|
+
version: Buffer24.from(CONTRACT),
|
|
5858
|
+
result: { kind: Buffer24.from("count"), value: count.value },
|
|
5859
|
+
quality,
|
|
5860
|
+
usage
|
|
5861
|
+
};
|
|
5862
|
+
} else {
|
|
5863
|
+
throw new FerricStoreError(`unsupported compact FLOW.QUERY result kind ${kind}`);
|
|
5864
|
+
}
|
|
5865
|
+
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact FLOW.QUERY result bytes");
|
|
5866
|
+
if (BigInt(usage.response_bytes) !== BigInt(data.byteLength)) {
|
|
5867
|
+
throw new FerricStoreError("compact FLOW.QUERY response_bytes does not match its payload");
|
|
5868
|
+
}
|
|
5869
|
+
return result;
|
|
5870
|
+
}
|
|
5871
|
+
function readPage(data, offset) {
|
|
5872
|
+
requireAvailable(data, offset, 5);
|
|
5873
|
+
const hasMoreCode = data.readUInt8(offset);
|
|
5874
|
+
const size = data.readUInt32BE(offset + 1);
|
|
5875
|
+
offset += 5;
|
|
5876
|
+
if (hasMoreCode === 0 && size === NULL_U32) {
|
|
5877
|
+
return { value: { has_more: false, cursor: null }, offset };
|
|
5878
|
+
}
|
|
5879
|
+
if (hasMoreCode !== 1 || size === 0 || size === NULL_U32 || size > MAX_CURSOR_BYTES) {
|
|
5880
|
+
throw new FerricStoreError("invalid compact FLOW.QUERY page cursor");
|
|
5881
|
+
}
|
|
5882
|
+
requireAvailable(data, offset, size);
|
|
5883
|
+
return {
|
|
5884
|
+
value: {
|
|
5885
|
+
has_more: true,
|
|
5886
|
+
cursor: detachDecodedBinary(data.subarray(offset, offset + size), data.byteLength)
|
|
5887
|
+
},
|
|
5888
|
+
offset: offset + size
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
function readRecord(data, offset, budget) {
|
|
5892
|
+
requireAvailable(data, offset, 4);
|
|
5893
|
+
const bitmap = data.readUInt32BE(offset);
|
|
5894
|
+
offset += 4;
|
|
5895
|
+
if ((bitmap & ~RECORD_FIELD_MASK) !== 0) {
|
|
5896
|
+
throw new FerricStoreError("compact FLOW.QUERY record contains reserved fields");
|
|
5897
|
+
}
|
|
5898
|
+
consumeDecodeItems(populationCount(bitmap), budget);
|
|
5899
|
+
const record = {};
|
|
5900
|
+
for (let index = 0; index < RECORD_FIELDS.length; index += 1) {
|
|
5901
|
+
if ((bitmap & 1 << index) === 0) continue;
|
|
5902
|
+
const field3 = RECORD_FIELDS[index];
|
|
5903
|
+
if (field3 == null) throw new FerricStoreError("invalid compact FLOW.QUERY record schema");
|
|
5904
|
+
const read = decodeValueWithBudget(data, offset, budget);
|
|
5905
|
+
setOwnValue2(record, field3, detachDecodedBinary(read.value, data.byteLength));
|
|
5906
|
+
offset = read.offset;
|
|
5907
|
+
}
|
|
5908
|
+
return { value: record, offset };
|
|
5909
|
+
}
|
|
5910
|
+
function readU64(data, offset) {
|
|
5911
|
+
requireAvailable(data, offset, 8);
|
|
5912
|
+
const value = data.readBigUInt64BE(offset);
|
|
5913
|
+
return {
|
|
5914
|
+
value: value <= MAX_SAFE_INTEGER_BIGINT ? Number(value) : value,
|
|
5915
|
+
offset: offset + 8
|
|
5916
|
+
};
|
|
5917
|
+
}
|
|
5918
|
+
function populationCount(value) {
|
|
5919
|
+
let remaining = value >>> 0;
|
|
5920
|
+
let count = 0;
|
|
5921
|
+
while (remaining !== 0) {
|
|
5922
|
+
remaining &= remaining - 1;
|
|
5923
|
+
count += 1;
|
|
5924
|
+
}
|
|
5925
|
+
return count;
|
|
5926
|
+
}
|
|
5927
|
+
|
|
5928
|
+
// src/protocol-compact-response.ts
|
|
5929
|
+
function tryDecodeCompactResponse(opcode, body, hints) {
|
|
5930
|
+
if (body.byteLength === 0) return { found: false, value: void 0 };
|
|
5931
|
+
const budget = { remainingItems: DEFAULT_MAX_VALUE_ITEMS };
|
|
5932
|
+
const tag = body.readUInt8(0);
|
|
5933
|
+
validateCompactResponseItems(tag, opcode, body, hints);
|
|
5934
|
+
const pipelineValues = opcode === OPCODES.pipeline && supports(hints, "pipeline_v1", opcode);
|
|
5935
|
+
if (tag === COMPACT_OK_LIST && (supports(hints, "ok_list_v1", opcode) || pipelineValues)) {
|
|
5936
|
+
const values = decodeCompactOkList(body, budget);
|
|
5937
|
+
return {
|
|
5938
|
+
found: true,
|
|
5939
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values.length === 1 ? "OK" : values
|
|
5940
|
+
};
|
|
5941
|
+
}
|
|
5942
|
+
if (tag === COMPACT_KV_GET && supports(hints, "kv_get_v1", opcode)) {
|
|
5943
|
+
return { found: true, value: decodeCompactKvGet(body) };
|
|
5944
|
+
}
|
|
5945
|
+
if ((tag === COMPACT_KV_MGET || tag === COMPACT_KV_MGET_FIXED) && (supports(hints, "kv_mget_v1", opcode) || pipelineValues)) {
|
|
5946
|
+
const values = tag === COMPACT_KV_MGET ? decodeCompactMget(body, budget) : decodeCompactMgetFixed(body, budget);
|
|
5947
|
+
return {
|
|
5948
|
+
found: true,
|
|
5949
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
5950
|
+
};
|
|
5951
|
+
}
|
|
5952
|
+
if (tag === COMPACT_INTEGER_LIST && pipelineValues) {
|
|
5953
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactIntegerList(body, budget)) };
|
|
5954
|
+
}
|
|
5955
|
+
if (tag === COMPACT_BINARY_LIST_LIST && pipelineValues) {
|
|
5956
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryListList(body, budget)) };
|
|
5957
|
+
}
|
|
5958
|
+
if (tag === COMPACT_BINARY_MAP_LIST && pipelineValues) {
|
|
5959
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryMapList(body, budget)) };
|
|
5960
|
+
}
|
|
5961
|
+
if (tag === COMPACT_PIPELINE_RESPONSE && pipelineValues) {
|
|
5962
|
+
return { found: true, value: decodeCompactPipeline(body, budget, hints.pipelineClaimModes) };
|
|
5963
|
+
}
|
|
5964
|
+
if (tag === COMPACT_FLOW_CLAIM_JOBS && (supports(hints, "flow_claim_jobs_v1", opcode) || pipelineValues)) {
|
|
5965
|
+
const values = decodeCompactClaimJobs(body, budget, hints.compactClaimMode);
|
|
5966
|
+
return {
|
|
5967
|
+
found: true,
|
|
5968
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5971
|
+
if (tag === COMPACT_FLOW_RECORD && supports(hints, "flow_record_v1", opcode)) {
|
|
5972
|
+
const read = readCompactFlowRecord(body, 0, budget);
|
|
5973
|
+
if (read.offset !== body.byteLength) throw new FerricStoreError("trailing compact Flow record bytes");
|
|
5974
|
+
return { found: true, value: read.value };
|
|
5497
5975
|
}
|
|
5498
5976
|
if (tag === COMPACT_FLOW_RECORD_LIST && (supports(hints, "flow_record_list_v1", opcode) || pipelineValues)) {
|
|
5499
5977
|
const read = readCompactFlowRecordList(body, 0, budget);
|
|
@@ -5503,6 +5981,9 @@ function tryDecodeCompactResponse(opcode, body, hints) {
|
|
|
5503
5981
|
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(read.value) : read.value
|
|
5504
5982
|
};
|
|
5505
5983
|
}
|
|
5984
|
+
if (tag === COMPACT_FLOW_QUERY_RESULT && supports(hints, "flow_query_result_v1", opcode)) {
|
|
5985
|
+
return { found: true, value: decodeCompactFlowQueryResult(body, budget) };
|
|
5986
|
+
}
|
|
5506
5987
|
return { found: false, value: void 0 };
|
|
5507
5988
|
}
|
|
5508
5989
|
function supports(hints, codec, opcode) {
|
|
@@ -5513,7 +5994,7 @@ function decodeCompactOkList(data, budget) {
|
|
|
5513
5994
|
const count = data.readUInt32BE(1);
|
|
5514
5995
|
requireCompactContainer2(count, budget);
|
|
5515
5996
|
if (data.byteLength !== 5) throw new FerricStoreError("invalid compact OK list response");
|
|
5516
|
-
return Array.from({ length: count }, () =>
|
|
5997
|
+
return Array.from({ length: count }, () => Buffer25.from("OK"));
|
|
5517
5998
|
}
|
|
5518
5999
|
function decodeCompactKvGet(data) {
|
|
5519
6000
|
requireAvailable(data, 0, 2);
|
|
@@ -5559,7 +6040,7 @@ function decodeCompactMgetFixed(data, budget) {
|
|
|
5559
6040
|
if (size === NULL_U32 || data.byteLength !== expected) {
|
|
5560
6041
|
throw new FerricStoreError("invalid compact fixed MGET response");
|
|
5561
6042
|
}
|
|
5562
|
-
if (size === 0) return new Array(count).fill(
|
|
6043
|
+
if (size === 0) return new Array(count).fill(Buffer25.alloc(0));
|
|
5563
6044
|
const values = new Array(count);
|
|
5564
6045
|
for (let index = 0, offset = 9; index < count; index += 1, offset += size) {
|
|
5565
6046
|
values[index] = data.subarray(offset, offset + size);
|
|
@@ -5620,7 +6101,7 @@ function decodeCompactPipeline(data, budget, claimModes) {
|
|
|
5620
6101
|
const read = readBinary(data, offset);
|
|
5621
6102
|
const errorStatus = status === 1 ? "busy" : "error";
|
|
5622
6103
|
values[index] = classifyServerError(
|
|
5623
|
-
|
|
6104
|
+
protocolErrorMessage(status === 1 ? 4 : 1, read.value),
|
|
5624
6105
|
read.value,
|
|
5625
6106
|
void 0,
|
|
5626
6107
|
errorStatus
|
|
@@ -5730,13 +6211,13 @@ function readCompactFlowRecord(data, offset, budget = { remainingItems: DEFAULT_
|
|
|
5730
6211
|
let key;
|
|
5731
6212
|
if (keyId === 0) {
|
|
5732
6213
|
const read2 = readBinary(data, offset);
|
|
5733
|
-
key = read2.value
|
|
6214
|
+
key = read2.value;
|
|
5734
6215
|
offset = read2.offset;
|
|
5735
6216
|
} else {
|
|
5736
6217
|
key = FLOW_RECORD_FIELD_KEYS[keyId] ?? `field_${keyId}`;
|
|
5737
6218
|
}
|
|
5738
6219
|
const read = decodeValueWithBudget(data, offset, budget);
|
|
5739
|
-
|
|
6220
|
+
setProtocolMapEntry(record, key, read.value);
|
|
5740
6221
|
offset = read.offset;
|
|
5741
6222
|
}
|
|
5742
6223
|
return { value: record, offset };
|
|
@@ -5772,15 +6253,29 @@ function requireCompactContainer2(count, budget) {
|
|
|
5772
6253
|
}
|
|
5773
6254
|
consumeDecodeItems(count, budget);
|
|
5774
6255
|
}
|
|
5775
|
-
function
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
if (
|
|
5779
|
-
|
|
5780
|
-
|
|
6256
|
+
function validateCompactResponseItems(tag, opcode, data, hints) {
|
|
6257
|
+
const scalarItems = opcode === OPCODES.set || opcode === OPCODES.mset ? 1 : void 0;
|
|
6258
|
+
const expected = scalarItems ?? hints.compactResponseItems;
|
|
6259
|
+
if (expected == null || !COUNTED_COMPACT_TAGS.has(tag)) return;
|
|
6260
|
+
requireAvailable(data, 0, 5);
|
|
6261
|
+
const actual = data.readUInt32BE(1);
|
|
6262
|
+
if (actual !== expected) {
|
|
6263
|
+
throw new FerricStoreError(
|
|
6264
|
+
`compact response returned ${actual} items; expected ${expected} items`
|
|
6265
|
+
);
|
|
5781
6266
|
}
|
|
5782
|
-
return `ERR native request failed status=${status}: ${String(value)}`;
|
|
5783
6267
|
}
|
|
6268
|
+
var COUNTED_COMPACT_TAGS = /* @__PURE__ */ new Set([
|
|
6269
|
+
COMPACT_FLOW_CLAIM_JOBS,
|
|
6270
|
+
COMPACT_OK_LIST,
|
|
6271
|
+
COMPACT_KV_MGET,
|
|
6272
|
+
COMPACT_FLOW_RECORD_LIST,
|
|
6273
|
+
COMPACT_BINARY_LIST_LIST,
|
|
6274
|
+
COMPACT_BINARY_MAP_LIST,
|
|
6275
|
+
COMPACT_INTEGER_LIST,
|
|
6276
|
+
COMPACT_KV_MGET_FIXED,
|
|
6277
|
+
COMPACT_PIPELINE_RESPONSE
|
|
6278
|
+
]);
|
|
5784
6279
|
|
|
5785
6280
|
// src/protocol-response.ts
|
|
5786
6281
|
function decodeResponse(frame, expectedOpcode, hints = {}) {
|
|
@@ -5798,9 +6293,16 @@ function decodeResponse(frame, expectedOpcode, hints = {}) {
|
|
|
5798
6293
|
}
|
|
5799
6294
|
const status = frame.body.readUInt16BE(0);
|
|
5800
6295
|
const body = frame.body.subarray(2);
|
|
5801
|
-
const
|
|
6296
|
+
const customPayload = (frame.flags & FLAG_CUSTOM_PAYLOAD) !== 0;
|
|
6297
|
+
const value = decodeResponseValue(
|
|
6298
|
+
frame.opcode,
|
|
6299
|
+
body,
|
|
6300
|
+
hints,
|
|
6301
|
+
status === STATUS_OK,
|
|
6302
|
+
customPayload
|
|
6303
|
+
);
|
|
5802
6304
|
if (status === STATUS_OK) return value;
|
|
5803
|
-
const message =
|
|
6305
|
+
const message = protocolErrorMessage(status, value);
|
|
5804
6306
|
throw classifyServerError(message, value, void 0, status);
|
|
5805
6307
|
}
|
|
5806
6308
|
function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
@@ -5839,7 +6341,7 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
5839
6341
|
continue;
|
|
5840
6342
|
}
|
|
5841
6343
|
const error = classifyServerError(
|
|
5842
|
-
|
|
6344
|
+
protocolErrorMessage(status === "busy" ? 4 : 1, payload),
|
|
5843
6345
|
payload,
|
|
5844
6346
|
void 0,
|
|
5845
6347
|
status
|
|
@@ -5854,28 +6356,24 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
5854
6356
|
return out;
|
|
5855
6357
|
}
|
|
5856
6358
|
function pipelineStatus(value) {
|
|
5857
|
-
if (typeof value !== "string" && !
|
|
6359
|
+
if (typeof value !== "string" && !Buffer26.isBuffer(value) && !(value instanceof Uint8Array)) return null;
|
|
5858
6360
|
const status = asText(value).toLowerCase();
|
|
5859
6361
|
return status === "ok" || status === "busy" || status === "error" ? status : null;
|
|
5860
6362
|
}
|
|
5861
|
-
function decodeResponseValue(opcode, body, hints) {
|
|
5862
|
-
|
|
5863
|
-
|
|
6363
|
+
function decodeResponseValue(opcode, body, hints, allowCompact, customPayload) {
|
|
6364
|
+
if (customPayload && allowCompact) {
|
|
6365
|
+
const compact = tryDecodeCompactResponse(opcode, body, hints);
|
|
6366
|
+
if (compact.found) return compact.value;
|
|
6367
|
+
}
|
|
6368
|
+
if (customPayload) {
|
|
6369
|
+
throw new FerricStoreError("unsupported or malformed custom protocol response", { raw: body });
|
|
6370
|
+
}
|
|
5864
6371
|
const decoded = decodeValue(body);
|
|
5865
6372
|
if (decoded.offset !== body.byteLength) {
|
|
5866
6373
|
throw new FerricStoreError("native protocol response has trailing bytes", { raw: body });
|
|
5867
6374
|
}
|
|
5868
6375
|
return decoded.value;
|
|
5869
6376
|
}
|
|
5870
|
-
function errorMessage2(status, value) {
|
|
5871
|
-
if (typeof value === "string") return value;
|
|
5872
|
-
if (Buffer22.isBuffer(value)) return value.toString("utf8");
|
|
5873
|
-
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5874
|
-
const message = value.message;
|
|
5875
|
-
return typeof message === "string" ? message : String(message);
|
|
5876
|
-
}
|
|
5877
|
-
return `ERR native request failed status=${status}: ${String(value)}`;
|
|
5878
|
-
}
|
|
5879
6377
|
|
|
5880
6378
|
// src/protocol.ts
|
|
5881
6379
|
function encodeRequest(command, requestId, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
|
|
@@ -5885,7 +6383,7 @@ function encodeRequest(command, requestId, maxBodyBytes = Number.MAX_SAFE_INTEGE
|
|
|
5885
6383
|
const bodyLength = customPayload ? binaryValueByteLength(command.payload) : plan?.byteLength ?? 0;
|
|
5886
6384
|
if (bodyLength > bodyLimit) throw requestFrameTooLarge(bodyLimit);
|
|
5887
6385
|
const flags = command.flags ?? 0;
|
|
5888
|
-
const frame =
|
|
6386
|
+
const frame = Buffer27.allocUnsafe(HEADER_SIZE + bodyLength);
|
|
5889
6387
|
frame.write(MAGIC, 0, "ascii");
|
|
5890
6388
|
frame.writeUInt8(REQUEST_VERSION, 4);
|
|
5891
6389
|
frame.writeUInt8(flags, 5);
|
|
@@ -5986,18 +6484,18 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5986
6484
|
}
|
|
5987
6485
|
if (command === "SET" && commandArgs2.length >= 2) {
|
|
5988
6486
|
const payload = stringSetPayload(commandArgs2);
|
|
5989
|
-
return payload == null ? commandExec(args) : { opcode: OPCODES.set, payload };
|
|
6487
|
+
return payload == null ? commandExec(args) : { compactResponseItems: 1, opcode: OPCODES.set, payload };
|
|
5990
6488
|
}
|
|
5991
6489
|
if (command === "MGET" && commandArgs2.length > 0) {
|
|
5992
6490
|
const compact = allowCustomPayload ? compactKeyPipelinePayload(OPCODES.mget, commandArgs2, 2, maxBodyBytes) : void 0;
|
|
5993
|
-
if (compact != null) return compact;
|
|
5994
|
-
return commandArgs2.every(isBinaryCommandArgument) ? { opcode: OPCODES.mget, payload: { keys: commandArgs2 } } : commandExec(args);
|
|
6491
|
+
if (compact != null) return { ...compact, compactResponseItems: commandArgs2.length };
|
|
6492
|
+
return commandArgs2.every(isBinaryCommandArgument) ? { compactResponseItems: commandArgs2.length, opcode: OPCODES.mget, payload: { keys: commandArgs2 } } : commandExec(args);
|
|
5995
6493
|
}
|
|
5996
6494
|
if (command === "MSET" && commandArgs2.length >= 2 && commandArgs2.length % 2 === 0) {
|
|
5997
6495
|
const compact = allowCustomPayload ? compactMsetPayload(commandArgs2, maxBodyBytes) : void 0;
|
|
5998
|
-
if (compact != null) return compact;
|
|
6496
|
+
if (compact != null) return { ...compact, compactResponseItems: 1 };
|
|
5999
6497
|
const pairs = typedKeyValuePairs(commandArgs2);
|
|
6000
|
-
return pairs == null ? commandExec(args) : { opcode: OPCODES.mset, payload: { pairs } };
|
|
6498
|
+
return pairs == null ? commandExec(args) : { compactResponseItems: 1, opcode: OPCODES.mset, payload: { pairs } };
|
|
6001
6499
|
}
|
|
6002
6500
|
if (command === "DEL" && commandArgs2.length > 0) {
|
|
6003
6501
|
return commandArgs2.every(isBinaryCommandArgument) ? { opcode: OPCODES.del, payload: { keys: commandArgs2 } } : commandExec(args);
|
|
@@ -6007,8 +6505,8 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
6007
6505
|
if (command === "FLOW.HISTORY") {
|
|
6008
6506
|
return flowHistoryPayload(commandArgs2) ?? commandExec(args);
|
|
6009
6507
|
}
|
|
6010
|
-
if (command === "FLOW.
|
|
6011
|
-
return
|
|
6508
|
+
if (command === "FLOW.QUERY") {
|
|
6509
|
+
return { opcode: OPCODES.flowQuery, payload: flowQueryPayload(commandArgs2) };
|
|
6012
6510
|
}
|
|
6013
6511
|
if (command === "FLOW.POLICY.SET") {
|
|
6014
6512
|
return flowPolicySetPayload(commandArgs2) ?? commandExec(args);
|
|
@@ -6167,24 +6665,17 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
6167
6665
|
if (command === "FLOW.RUN_STEPS_MANY") {
|
|
6168
6666
|
return flowAdminPayload(OPCODES.flowRunStepsMany, commandArgs2) ?? commandExec(args);
|
|
6169
6667
|
}
|
|
6170
|
-
if (command === "FLOW.SEARCH") {
|
|
6171
|
-
if (hasFlowCommandOnlyOption(command, commandArgs2)) {
|
|
6172
|
-
const fallback = commandExec(args);
|
|
6173
|
-
try {
|
|
6174
|
-
const parsed = flowSearchPayload(commandArgs2);
|
|
6175
|
-
return parsed == null ? fallback : withFlowPartitionRouting(fallback, parsed.payload);
|
|
6176
|
-
} catch {
|
|
6177
|
-
return fallback;
|
|
6178
|
-
}
|
|
6179
|
-
}
|
|
6180
|
-
return flowSearchPayload(commandArgs2) ?? commandExec(args);
|
|
6181
|
-
}
|
|
6182
6668
|
return commandExec(args);
|
|
6183
6669
|
}
|
|
6184
6670
|
function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
|
|
6185
6671
|
const compact = compactPipelinePayload(commands, maxBodyBytes);
|
|
6186
6672
|
if (compact != null) {
|
|
6187
|
-
return {
|
|
6673
|
+
return {
|
|
6674
|
+
compactResponseItems: commands.length,
|
|
6675
|
+
flags: FLAG_CUSTOM_PAYLOAD,
|
|
6676
|
+
opcode: OPCODES.pipeline,
|
|
6677
|
+
payload: compact
|
|
6678
|
+
};
|
|
6188
6679
|
}
|
|
6189
6680
|
const protocols = new Array(commands.length);
|
|
6190
6681
|
for (let index = 0; index < commands.length; index += 1) {
|
|
@@ -6223,6 +6714,7 @@ function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
|
|
|
6223
6714
|
const pipelineClaimModes = pipelineProtocols.map((protocol) => protocol.compactClaimMode);
|
|
6224
6715
|
const hasPipelineClaimMode = pipelineClaimModes.some((mode) => mode != null);
|
|
6225
6716
|
return {
|
|
6717
|
+
compactResponseItems: commands.length,
|
|
6226
6718
|
opcode: OPCODES.pipeline,
|
|
6227
6719
|
payload: {
|
|
6228
6720
|
atomicity: "none",
|
|
@@ -6271,7 +6763,7 @@ import "net";
|
|
|
6271
6763
|
import "tls";
|
|
6272
6764
|
|
|
6273
6765
|
// src/client-native-options.ts
|
|
6274
|
-
import { Buffer as
|
|
6766
|
+
import { Buffer as Buffer28 } from "buffer";
|
|
6275
6767
|
|
|
6276
6768
|
// src/string-array-snapshot.ts
|
|
6277
6769
|
function snapshotOwnStringArray(values, name) {
|
|
@@ -6354,7 +6846,7 @@ function snapshotTlsOptions(options) {
|
|
|
6354
6846
|
return Object.freeze(snapshot);
|
|
6355
6847
|
}
|
|
6356
6848
|
function snapshotTlsValue(value, name) {
|
|
6357
|
-
if (
|
|
6849
|
+
if (Buffer28.isBuffer(value)) return Buffer28.from(value);
|
|
6358
6850
|
if (value instanceof Uint8Array) return value.slice();
|
|
6359
6851
|
if (Array.isArray(value)) {
|
|
6360
6852
|
const snapshot = new Array(value.length);
|
|
@@ -7209,7 +7701,7 @@ var NativeResponseHandler = class {
|
|
|
7209
7701
|
compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
|
|
7210
7702
|
});
|
|
7211
7703
|
if (frame.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
|
|
7212
|
-
const
|
|
7704
|
+
const event2 = {
|
|
7213
7705
|
flags: frame.flags,
|
|
7214
7706
|
laneId: frame.laneId,
|
|
7215
7707
|
opcode: frame.opcode,
|
|
@@ -7217,7 +7709,7 @@ var NativeResponseHandler = class {
|
|
|
7217
7709
|
};
|
|
7218
7710
|
if (frame.opcode === OPCODES.goaway) this.options.beginDraining();
|
|
7219
7711
|
try {
|
|
7220
|
-
const callback = this.options.onEvent?.(
|
|
7712
|
+
const callback = this.options.onEvent?.(event2);
|
|
7221
7713
|
if (callback != null) void Promise.resolve(callback).catch(() => void 0);
|
|
7222
7714
|
} catch {
|
|
7223
7715
|
}
|
|
@@ -7381,12 +7873,14 @@ var NativeConnectionCapabilities = class {
|
|
|
7381
7873
|
}
|
|
7382
7874
|
configuredRequestFrameBytes;
|
|
7383
7875
|
compactResponseOpcodes = EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
7876
|
+
flowQuery;
|
|
7384
7877
|
requestFrameBytes;
|
|
7385
7878
|
negotiatedRequestFrameBytes;
|
|
7386
7879
|
apply(value) {
|
|
7387
7880
|
const limits = startupLimits(value);
|
|
7388
7881
|
const negotiation = nativeNegotiation(value);
|
|
7389
7882
|
this.compactResponseOpcodes = negotiation.compactResponseOpcodes;
|
|
7883
|
+
this.flowQuery = negotiation.flowQuery;
|
|
7390
7884
|
if (limits.frameBytes != null) {
|
|
7391
7885
|
this.negotiatedRequestFrameBytes = Math.min(
|
|
7392
7886
|
this.configuredRequestFrameBytes,
|
|
@@ -7406,6 +7900,19 @@ var NativeConnectionCapabilities = class {
|
|
|
7406
7900
|
}
|
|
7407
7901
|
};
|
|
7408
7902
|
|
|
7903
|
+
// src/native-startup-payload.ts
|
|
7904
|
+
function nativeStartupPayload(clientName, events) {
|
|
7905
|
+
const name = clientName ?? "ferricstore-typescript";
|
|
7906
|
+
return {
|
|
7907
|
+
client_name: name,
|
|
7908
|
+
compact_flow_responses: true,
|
|
7909
|
+
compact_response_codecs: ["flow_query_result_v1"],
|
|
7910
|
+
compression: "none",
|
|
7911
|
+
driver_name: name,
|
|
7912
|
+
...events == null || events.length === 0 ? {} : { events: [...events] }
|
|
7913
|
+
};
|
|
7914
|
+
}
|
|
7915
|
+
|
|
7409
7916
|
// src/native-adapter.ts
|
|
7410
7917
|
var NativeAdapter = class _NativeAdapter {
|
|
7411
7918
|
socket;
|
|
@@ -7564,13 +8071,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7564
8071
|
const response = await this.request({
|
|
7565
8072
|
laneId: 0,
|
|
7566
8073
|
opcode: OPCODES.startup,
|
|
7567
|
-
payload:
|
|
7568
|
-
client_name: clientName ?? "ferricstore-typescript",
|
|
7569
|
-
compact_flow_responses: true,
|
|
7570
|
-
compression: "none",
|
|
7571
|
-
driver_name: clientName ?? "ferricstore-typescript",
|
|
7572
|
-
...events == null || events.length === 0 ? {} : { events: [...events] }
|
|
7573
|
-
}
|
|
8074
|
+
payload: nativeStartupPayload(clientName, events)
|
|
7574
8075
|
});
|
|
7575
8076
|
this.applyStartupLimits(response);
|
|
7576
8077
|
const authRequired = field(response, "auth_required");
|
|
@@ -7630,6 +8131,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7630
8131
|
if (!hasFlowControlCredit) this.pendingControlRequests += 1;
|
|
7631
8132
|
this.pending.set(requestId, {
|
|
7632
8133
|
...command.compactClaimMode == null ? {} : { compactClaimMode: command.compactClaimMode },
|
|
8134
|
+
...command.compactResponseItems == null ? {} : { compactResponseItems: command.compactResponseItems },
|
|
7633
8135
|
hasFlowControlCredit,
|
|
7634
8136
|
indefinite: timeoutMs == null,
|
|
7635
8137
|
laneId,
|
|
@@ -7764,7 +8266,7 @@ function executeCommandArgs(executor, args) {
|
|
|
7764
8266
|
import "buffer";
|
|
7765
8267
|
|
|
7766
8268
|
// src/command-retry-policy.ts
|
|
7767
|
-
import { Buffer as
|
|
8269
|
+
import { Buffer as Buffer32 } from "buffer";
|
|
7768
8270
|
function isCasMutation(args) {
|
|
7769
8271
|
const offset = commandName2(args[0]) === "COMMAND_EXEC" ? 1 : 0;
|
|
7770
8272
|
const name = commandName2(args[offset]);
|
|
@@ -7778,8 +8280,8 @@ function isCasMutation(args) {
|
|
|
7778
8280
|
}
|
|
7779
8281
|
function commandName2(value) {
|
|
7780
8282
|
if (typeof value === "string") return value.toUpperCase();
|
|
7781
|
-
if (
|
|
7782
|
-
return
|
|
8283
|
+
if (Buffer32.isBuffer(value) || value instanceof Uint8Array) {
|
|
8284
|
+
return Buffer32.from(value).toString("utf8").toUpperCase();
|
|
7783
8285
|
}
|
|
7784
8286
|
return void 0;
|
|
7785
8287
|
}
|
|
@@ -7994,16 +8496,88 @@ function normalizeNonNegativeInteger2(value, fallback) {
|
|
|
7994
8496
|
import "buffer";
|
|
7995
8497
|
|
|
7996
8498
|
// src/topology-routing.ts
|
|
7997
|
-
import { Buffer as
|
|
8499
|
+
import { Buffer as Buffer35 } from "buffer";
|
|
8500
|
+
|
|
8501
|
+
// src/flow-partition-route-cache.ts
|
|
8502
|
+
import { Buffer as Buffer34 } from "buffer";
|
|
7998
8503
|
import { createHash } from "crypto";
|
|
7999
|
-
var
|
|
8000
|
-
var
|
|
8504
|
+
var AUTO_PREFIX = Buffer34.from("__flow_auto__:", "ascii");
|
|
8505
|
+
var MAX_CACHEABLE_PARTITION_BYTES = 4 * 1024;
|
|
8506
|
+
var MAX_CACHE_BYTES = 1 * 1024 * 1024;
|
|
8507
|
+
var MAX_CACHE_ENTRIES = 1024;
|
|
8508
|
+
var CACHE_ENTRY_OVERHEAD_BYTES = 96;
|
|
8509
|
+
var routeCache = /* @__PURE__ */ new Map();
|
|
8510
|
+
var cacheBytes = 0;
|
|
8511
|
+
var cacheHits = 0;
|
|
8512
|
+
var cacheMisses = 0;
|
|
8513
|
+
function flowLogicalPartitionRoutingKey(value) {
|
|
8514
|
+
if (typeof value !== "string" && !Buffer34.isBuffer(value)) return void 0;
|
|
8515
|
+
const autoBucket = flowAutoBucket(value);
|
|
8516
|
+
if (autoBucket != null) return `{fa:${autoBucket}}`;
|
|
8517
|
+
const bytes2 = Buffer34.isBuffer(value) ? value : Buffer34.from(value);
|
|
8518
|
+
if (bytes2.byteLength > MAX_CACHEABLE_PARTITION_BYTES) return hashRoute(bytes2);
|
|
8519
|
+
const cacheKey = bytes2.toString("base64");
|
|
8520
|
+
const cached = routeCache.get(cacheKey);
|
|
8521
|
+
if (cached != null) {
|
|
8522
|
+
cacheHits += 1;
|
|
8523
|
+
routeCache.delete(cacheKey);
|
|
8524
|
+
routeCache.set(cacheKey, cached);
|
|
8525
|
+
return cached.routeKey;
|
|
8526
|
+
}
|
|
8527
|
+
cacheMisses += 1;
|
|
8528
|
+
const routeKey = hashRoute(bytes2);
|
|
8529
|
+
const entryBytes = estimatedEntryBytes(cacheKey, routeKey);
|
|
8530
|
+
while (routeCache.size >= MAX_CACHE_ENTRIES || routeCache.size > 0 && cacheBytes + entryBytes > MAX_CACHE_BYTES) {
|
|
8531
|
+
evictOldest();
|
|
8532
|
+
}
|
|
8533
|
+
if (entryBytes <= MAX_CACHE_BYTES) {
|
|
8534
|
+
routeCache.set(cacheKey, { bytes: entryBytes, routeKey });
|
|
8535
|
+
cacheBytes += entryBytes;
|
|
8536
|
+
}
|
|
8537
|
+
return routeKey;
|
|
8538
|
+
}
|
|
8539
|
+
function flowAutoBucket(value) {
|
|
8540
|
+
if (typeof value === "string") {
|
|
8541
|
+
const match = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(value);
|
|
8542
|
+
if (match?.[1] == null) return void 0;
|
|
8543
|
+
const bucket2 = Number(match[1]);
|
|
8544
|
+
return bucket2 < 256 ? bucket2 : void 0;
|
|
8545
|
+
}
|
|
8546
|
+
const digitCount = value.byteLength - AUTO_PREFIX.byteLength;
|
|
8547
|
+
if (digitCount < 1 || digitCount > 3) return void 0;
|
|
8548
|
+
for (let index = 0; index < AUTO_PREFIX.byteLength; index += 1) {
|
|
8549
|
+
if (value[index] !== AUTO_PREFIX[index]) return void 0;
|
|
8550
|
+
}
|
|
8551
|
+
if (digitCount > 1 && value[AUTO_PREFIX.byteLength] === 48) return void 0;
|
|
8552
|
+
let bucket = 0;
|
|
8553
|
+
for (let index = AUTO_PREFIX.byteLength; index < value.byteLength; index += 1) {
|
|
8554
|
+
const digit = value[index];
|
|
8555
|
+
if (digit == null || digit < 48 || digit > 57) return void 0;
|
|
8556
|
+
bucket = bucket * 10 + digit - 48;
|
|
8557
|
+
}
|
|
8558
|
+
return bucket < 256 ? bucket : void 0;
|
|
8559
|
+
}
|
|
8560
|
+
function hashRoute(value) {
|
|
8561
|
+
const digest = createHash("sha256").update(value).digest("base64url");
|
|
8562
|
+
return `{f:${digest}}`;
|
|
8563
|
+
}
|
|
8564
|
+
function estimatedEntryBytes(cacheKey, routeKey) {
|
|
8565
|
+
return CACHE_ENTRY_OVERHEAD_BYTES + 2 * (cacheKey.length + routeKey.length);
|
|
8566
|
+
}
|
|
8567
|
+
function evictOldest() {
|
|
8568
|
+
const oldest = routeCache.entries().next().value;
|
|
8569
|
+
if (oldest == null) return;
|
|
8570
|
+
routeCache.delete(oldest[0]);
|
|
8571
|
+
cacheBytes -= oldest[1].bytes;
|
|
8572
|
+
}
|
|
8573
|
+
|
|
8574
|
+
// src/topology-routing.ts
|
|
8001
8575
|
function routingKeyFromProtocolPayload(name, command) {
|
|
8002
8576
|
if (command.opcode < 256 || name === "CLUSTER.KEYSLOT" || name === "SHARDS" || name === "ROUTE") {
|
|
8003
8577
|
return void 0;
|
|
8004
8578
|
}
|
|
8005
8579
|
if (isPlainObject3(command.payload)) {
|
|
8006
|
-
for (const
|
|
8580
|
+
for (const field3 of [
|
|
8007
8581
|
"key",
|
|
8008
8582
|
"partition_key",
|
|
8009
8583
|
"id",
|
|
@@ -8013,8 +8587,8 @@ function routingKeyFromProtocolPayload(name, command) {
|
|
|
8013
8587
|
"correlation_id",
|
|
8014
8588
|
"scope"
|
|
8015
8589
|
]) {
|
|
8016
|
-
const value = getField(command.payload,
|
|
8017
|
-
if (typeof value === "string" ||
|
|
8590
|
+
const value = getField(command.payload, field3);
|
|
8591
|
+
if (typeof value === "string" || Buffer35.isBuffer(value)) {
|
|
8018
8592
|
return value;
|
|
8019
8593
|
}
|
|
8020
8594
|
}
|
|
@@ -8048,6 +8622,7 @@ function flowRoutingData(name, args) {
|
|
|
8048
8622
|
if (flowScheduleCommands.has(name)) {
|
|
8049
8623
|
return void 0;
|
|
8050
8624
|
}
|
|
8625
|
+
if (name === "FLOW.QUERY") return void 0;
|
|
8051
8626
|
if (flowApprovalIdCommands.has(name)) {
|
|
8052
8627
|
const id = flowArgs[0];
|
|
8053
8628
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(id));
|
|
@@ -8061,7 +8636,7 @@ function flowRoutingData(name, args) {
|
|
|
8061
8636
|
if (typeof partition === "string" && partition.toUpperCase() !== "AUTO" && partition.toUpperCase() !== "MIXED") {
|
|
8062
8637
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
8063
8638
|
}
|
|
8064
|
-
if (
|
|
8639
|
+
if (Buffer35.isBuffer(partition)) {
|
|
8065
8640
|
const text3 = partition.toString("utf8").toUpperCase();
|
|
8066
8641
|
if (text3 !== "AUTO" && text3 !== "MIXED") {
|
|
8067
8642
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
@@ -8152,46 +8727,17 @@ function flowPartitionRoutingKeyFromCommand(command, claim) {
|
|
|
8152
8727
|
return { handled: false };
|
|
8153
8728
|
}
|
|
8154
8729
|
function isRoutingKey(value) {
|
|
8155
|
-
return typeof value === "string" ||
|
|
8156
|
-
}
|
|
8157
|
-
function flowLogicalPartitionRoutingKey(value) {
|
|
8158
|
-
if (typeof value !== "string" && !Buffer30.isBuffer(value)) {
|
|
8159
|
-
return void 0;
|
|
8160
|
-
}
|
|
8161
|
-
const bytes2 = Buffer30.isBuffer(value) ? value : Buffer30.from(value);
|
|
8162
|
-
const text3 = bytes2.toString("utf8");
|
|
8163
|
-
const autoMatch = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(text3);
|
|
8164
|
-
if (autoMatch != null) {
|
|
8165
|
-
const bucket = Number(autoMatch[1]);
|
|
8166
|
-
if (bucket < 256) {
|
|
8167
|
-
return `{fa:${bucket}}`;
|
|
8168
|
-
}
|
|
8169
|
-
}
|
|
8170
|
-
const cacheKey = `${Buffer30.isBuffer(value) ? "b" : "s"}:${bytes2.toString("base64")}`;
|
|
8171
|
-
const cached = flowPartitionRouteCache.get(cacheKey);
|
|
8172
|
-
if (cached != null) {
|
|
8173
|
-
flowPartitionRouteCache.delete(cacheKey);
|
|
8174
|
-
flowPartitionRouteCache.set(cacheKey, cached);
|
|
8175
|
-
return cached;
|
|
8176
|
-
}
|
|
8177
|
-
const digest = createHash("sha256").update(bytes2).digest("base64url");
|
|
8178
|
-
const routeKey = `{f:${digest}}`;
|
|
8179
|
-
if (flowPartitionRouteCache.size >= FLOW_PARTITION_ROUTE_CACHE_MAX) {
|
|
8180
|
-
const oldest = flowPartitionRouteCache.keys().next().value;
|
|
8181
|
-
if (oldest != null) flowPartitionRouteCache.delete(oldest);
|
|
8182
|
-
}
|
|
8183
|
-
flowPartitionRouteCache.set(cacheKey, routeKey);
|
|
8184
|
-
return routeKey;
|
|
8730
|
+
return typeof value === "string" || Buffer35.isBuffer(value);
|
|
8185
8731
|
}
|
|
8186
8732
|
function flowAutoIdRoutingKey(value) {
|
|
8187
|
-
if (typeof value !== "string" && !
|
|
8733
|
+
if (typeof value !== "string" && !Buffer35.isBuffer(value)) {
|
|
8188
8734
|
return void 0;
|
|
8189
8735
|
}
|
|
8190
|
-
const bucket = (
|
|
8736
|
+
const bucket = (Buffer35.isBuffer(value) ? crc32(value) : crc32Utf8(value)) & 255;
|
|
8191
8737
|
return `{fa:${bucket}}`;
|
|
8192
8738
|
}
|
|
8193
8739
|
function flowClaimLogicalPartitionRoutingKey(value) {
|
|
8194
|
-
if (typeof value !== "string" && !
|
|
8740
|
+
if (typeof value !== "string" && !Buffer35.isBuffer(value)) return void 0;
|
|
8195
8741
|
const selector = commandPart(value);
|
|
8196
8742
|
if (selector === "AUTO" || selector === "ANY") return void 0;
|
|
8197
8743
|
if (selector === "GLOBAL") return "{f}";
|
|
@@ -8206,7 +8752,7 @@ function singleShardFlowClaimPartitionKey(values) {
|
|
|
8206
8752
|
return keys.some((key) => key == null) ? void 0 : singleShardKey(keys);
|
|
8207
8753
|
}
|
|
8208
8754
|
function singleShardKey(keys) {
|
|
8209
|
-
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !
|
|
8755
|
+
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !Buffer35.isBuffer(key))) {
|
|
8210
8756
|
return void 0;
|
|
8211
8757
|
}
|
|
8212
8758
|
const usable = keys;
|
|
@@ -8239,7 +8785,7 @@ function routedKeyGroups(keys, routeKey) {
|
|
|
8239
8785
|
const groups = /* @__PURE__ */ new Map();
|
|
8240
8786
|
for (let index = 0; index < keys.length; index += 1) {
|
|
8241
8787
|
const key = keys[index];
|
|
8242
|
-
if (typeof key !== "string" && !
|
|
8788
|
+
if (typeof key !== "string" && !Buffer35.isBuffer(key)) return void 0;
|
|
8243
8789
|
const route = routeKey(key);
|
|
8244
8790
|
const groupKey = `${route.endpointKey}\0${route.laneId}`;
|
|
8245
8791
|
const group = groups.get(groupKey);
|
|
@@ -9011,15 +9557,15 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
9011
9557
|
this.adapterOptions = {
|
|
9012
9558
|
...adapterOptions,
|
|
9013
9559
|
events: [.../* @__PURE__ */ new Set([...adapterOptions.events ?? [], "TOPOLOGY_CHANGED"])],
|
|
9014
|
-
onEvent: (
|
|
9560
|
+
onEvent: (event2) => {
|
|
9015
9561
|
try {
|
|
9016
|
-
const callback = userOnEvent?.(
|
|
9562
|
+
const callback = userOnEvent?.(event2);
|
|
9017
9563
|
if (callback != null) {
|
|
9018
9564
|
void Promise.resolve(callback).catch(() => void 0);
|
|
9019
9565
|
}
|
|
9020
9566
|
} catch {
|
|
9021
9567
|
}
|
|
9022
|
-
if (!this.closed && nativeEventName(
|
|
9568
|
+
if (!this.closed && nativeEventName(event2) === "TOPOLOGY_CHANGED") {
|
|
9023
9569
|
this.requestTopologyRefresh();
|
|
9024
9570
|
}
|
|
9025
9571
|
}
|
|
@@ -9328,7 +9874,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
9328
9874
|
};
|
|
9329
9875
|
|
|
9330
9876
|
// src/response-map-preservation.ts
|
|
9331
|
-
import { Buffer as
|
|
9877
|
+
import { Buffer as Buffer37 } from "buffer";
|
|
9332
9878
|
function toStringKeyMapPreservingValues(value) {
|
|
9333
9879
|
if (value == null) return void 0;
|
|
9334
9880
|
const result = {};
|
|
@@ -9338,7 +9884,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
9338
9884
|
}
|
|
9339
9885
|
return result;
|
|
9340
9886
|
}
|
|
9341
|
-
if (typeof value === "object" && !Array.isArray(value) && !
|
|
9887
|
+
if (typeof value === "object" && !Array.isArray(value) && !Buffer37.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9342
9888
|
for (const [key, item] of Object.entries(value)) {
|
|
9343
9889
|
setOwnValue(result, text(key), normalizeMapStructurePreservingBytes(item));
|
|
9344
9890
|
}
|
|
@@ -9347,7 +9893,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
9347
9893
|
return void 0;
|
|
9348
9894
|
}
|
|
9349
9895
|
function normalizeMapStructurePreservingBytes(value) {
|
|
9350
|
-
if (
|
|
9896
|
+
if (Buffer37.isBuffer(value) || value instanceof Uint8Array) return value;
|
|
9351
9897
|
if (value instanceof Map) {
|
|
9352
9898
|
const result = {};
|
|
9353
9899
|
for (const [key, item] of value.entries()) {
|
|
@@ -9369,7 +9915,7 @@ function normalizeMapStructurePreservingBytes(value) {
|
|
|
9369
9915
|
}
|
|
9370
9916
|
|
|
9371
9917
|
// src/native-kv-responses.ts
|
|
9372
|
-
import { Buffer as
|
|
9918
|
+
import { Buffer as Buffer38 } from "buffer";
|
|
9373
9919
|
function rateLimitResultFromResp(value) {
|
|
9374
9920
|
if (!Array.isArray(value) || value.length !== 4) {
|
|
9375
9921
|
throw new TypeError("RATELIMIT.ADD returned an unexpected response");
|
|
@@ -9426,13 +9972,13 @@ function fetchOrComputeResultFromResp(value, codec) {
|
|
|
9426
9972
|
}
|
|
9427
9973
|
function decodePayload(codec, value) {
|
|
9428
9974
|
if (value == null) return null;
|
|
9429
|
-
if (
|
|
9430
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
9431
|
-
if (typeof value === "string") return codec.decode(
|
|
9975
|
+
if (Buffer38.isBuffer(value)) return codec.decode(value);
|
|
9976
|
+
if (value instanceof Uint8Array) return codec.decode(Buffer38.from(value));
|
|
9977
|
+
if (typeof value === "string") return codec.decode(Buffer38.from(value));
|
|
9432
9978
|
return normalizeRefMeta(value);
|
|
9433
9979
|
}
|
|
9434
9980
|
function requiredResponseString(value, context) {
|
|
9435
|
-
if (typeof value !== "string" && !
|
|
9981
|
+
if (typeof value !== "string" && !Buffer38.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9436
9982
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
9437
9983
|
}
|
|
9438
9984
|
const result = text(value);
|
|
@@ -9449,7 +9995,7 @@ function requiredNonNegativeInteger(value, context) {
|
|
|
9449
9995
|
return result;
|
|
9450
9996
|
}
|
|
9451
9997
|
function responseBytes(value, context) {
|
|
9452
|
-
if (typeof value !== "string" && !
|
|
9998
|
+
if (typeof value !== "string" && !Buffer38.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9453
9999
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
9454
10000
|
}
|
|
9455
10001
|
return bytes(value);
|
|
@@ -9772,17 +10318,6 @@ function finiteNonNegativeInteger(value, fallback) {
|
|
|
9772
10318
|
function finiteNonNegativeNumber(value, fallback) {
|
|
9773
10319
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(0, value);
|
|
9774
10320
|
}
|
|
9775
|
-
function appendReadOptions(args, options) {
|
|
9776
|
-
append(args, "COUNT", options.count);
|
|
9777
|
-
append(args, "PARTITION", options.partitionKey);
|
|
9778
|
-
append(args, "FROM_MS", options.fromMs);
|
|
9779
|
-
append(args, "TO_MS", options.toMs);
|
|
9780
|
-
appendBool(args, "REV", options.rev);
|
|
9781
|
-
append(args, "STATE", options.state);
|
|
9782
|
-
appendBool(args, "TERMINAL_ONLY", options.terminalOnly);
|
|
9783
|
-
appendBool(args, "INCLUDE_COLD", options.includeCold);
|
|
9784
|
-
appendBool(args, "CONSISTENT_PROJECTION", options.consistentProjection);
|
|
9785
|
-
}
|
|
9786
10321
|
function appendAttributeQueryOptions(args, options) {
|
|
9787
10322
|
append(args, "STATE", options.state);
|
|
9788
10323
|
append(args, "PARTITION", options.partitionKey);
|
|
@@ -9836,22 +10371,6 @@ function appendAttributes(args, attributes) {
|
|
|
9836
10371
|
args.push("ATTRIBUTE", name, value);
|
|
9837
10372
|
}
|
|
9838
10373
|
}
|
|
9839
|
-
function appendSearchStateMeta(args, state, stateMeta) {
|
|
9840
|
-
const entries = Object.entries(stateMeta ?? {});
|
|
9841
|
-
if (entries.length === 0) {
|
|
9842
|
-
return;
|
|
9843
|
-
}
|
|
9844
|
-
if (entries.every(([, value]) => isPlainObject5(value))) {
|
|
9845
|
-
for (const [metaState, values] of entries) {
|
|
9846
|
-
args.push("STATE_META", metaState, values);
|
|
9847
|
-
}
|
|
9848
|
-
return;
|
|
9849
|
-
}
|
|
9850
|
-
if (state == null) {
|
|
9851
|
-
throw new Error("search stateMeta filters require state or nested state metadata");
|
|
9852
|
-
}
|
|
9853
|
-
args.push("STATE_META", state, stateMeta);
|
|
9854
|
-
}
|
|
9855
10374
|
function normalizeAdminResponse(value) {
|
|
9856
10375
|
return normalizeRefMeta(value);
|
|
9857
10376
|
}
|
|
@@ -10159,7 +10678,7 @@ function groupAutoPartitionItems(items) {
|
|
|
10159
10678
|
}
|
|
10160
10679
|
|
|
10161
10680
|
// src/client-values.ts
|
|
10162
|
-
import { Buffer as
|
|
10681
|
+
import { Buffer as Buffer39 } from "buffer";
|
|
10163
10682
|
async function valueMGetEntries(client, refs, options = {}) {
|
|
10164
10683
|
const refCount = refs.length;
|
|
10165
10684
|
if (refCount === 0) {
|
|
@@ -10194,12 +10713,12 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
10194
10713
|
const item = response[index];
|
|
10195
10714
|
if (item == null) {
|
|
10196
10715
|
entries[index] = { found: false };
|
|
10197
|
-
} else if (
|
|
10716
|
+
} else if (Buffer39.isBuffer(item)) {
|
|
10198
10717
|
entries[index] = { found: true, value: client.codec.decode(item) };
|
|
10199
10718
|
} else if (item instanceof Uint8Array) {
|
|
10200
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
10719
|
+
entries[index] = { found: true, value: client.codec.decode(Buffer39.from(item)) };
|
|
10201
10720
|
} else if (typeof item === "string") {
|
|
10202
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
10721
|
+
entries[index] = { found: true, value: client.codec.decode(Buffer39.from(item)) };
|
|
10203
10722
|
} else {
|
|
10204
10723
|
entries[index] = { found: true, value: item };
|
|
10205
10724
|
}
|
|
@@ -10211,7 +10730,7 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
10211
10730
|
import "buffer";
|
|
10212
10731
|
|
|
10213
10732
|
// src/auto-batch-ordering.ts
|
|
10214
|
-
import { Buffer as
|
|
10733
|
+
import { Buffer as Buffer40 } from "buffer";
|
|
10215
10734
|
function autoBatchOrderingPlan(batch) {
|
|
10216
10735
|
const accesses = /* @__PURE__ */ new Map();
|
|
10217
10736
|
const fallbackDependencies = [];
|
|
@@ -10326,13 +10845,13 @@ function flowManyAutoBatchIds(command, name) {
|
|
|
10326
10845
|
return fixedFlowItemIds(
|
|
10327
10846
|
command,
|
|
10328
10847
|
mixed ? 4 : 3,
|
|
10329
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) &&
|
|
10848
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && Buffer40.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
|
|
10330
10849
|
);
|
|
10331
10850
|
}
|
|
10332
10851
|
return fixedFlowItemIds(
|
|
10333
10852
|
command,
|
|
10334
10853
|
mixed ? 4 : 3,
|
|
10335
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10854
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer40.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
|
|
10336
10855
|
);
|
|
10337
10856
|
}
|
|
10338
10857
|
function createManyAutoBatchIds(command) {
|
|
@@ -10345,7 +10864,7 @@ function createManyAutoBatchIds(command) {
|
|
|
10345
10864
|
const ids = fixedFlowItemIds(
|
|
10346
10865
|
command,
|
|
10347
10866
|
width,
|
|
10348
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10867
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer40.isBuffer(command[itemIndex + width - 1]),
|
|
10349
10868
|
markerIndex
|
|
10350
10869
|
);
|
|
10351
10870
|
if (ids != null) return ids;
|
|
@@ -10363,7 +10882,7 @@ function extendedCreateManyAutoBatchIds(command, markerIndex) {
|
|
|
10363
10882
|
let cursor = markerIndex + 2;
|
|
10364
10883
|
for (let itemIndex = 0; itemIndex < itemCount; itemIndex += 1) {
|
|
10365
10884
|
const id = command[cursor];
|
|
10366
|
-
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !
|
|
10885
|
+
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !Buffer40.isBuffer(command[cursor + 2])) return void 0;
|
|
10367
10886
|
ids.push(id);
|
|
10368
10887
|
cursor += 3;
|
|
10369
10888
|
const afterValues = skipExtendedNamedItems(command, cursor, true);
|
|
@@ -10382,7 +10901,7 @@ function skipExtendedNamedItems(command, countIndex, encodedValues) {
|
|
|
10382
10901
|
for (let index = 0; index < count; index += 1) {
|
|
10383
10902
|
const name = command[firstItem + index * 2];
|
|
10384
10903
|
const value = command[firstItem + index * 2 + 1];
|
|
10385
|
-
if (!isAutoBatchResourceValue(name) || (encodedValues ? !
|
|
10904
|
+
if (!isAutoBatchResourceValue(name) || (encodedValues ? !Buffer40.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
|
|
10386
10905
|
}
|
|
10387
10906
|
return firstItem + count * 2;
|
|
10388
10907
|
}
|
|
@@ -10397,7 +10916,7 @@ function runStepsManyAutoBatchIds(command) {
|
|
|
10397
10916
|
ids.push(item);
|
|
10398
10917
|
continue;
|
|
10399
10918
|
}
|
|
10400
|
-
if (typeof item !== "object" || item == null || Array.isArray(item) ||
|
|
10919
|
+
if (typeof item !== "object" || item == null || Array.isArray(item) || Buffer40.isBuffer(item)) return void 0;
|
|
10401
10920
|
const id = item.id;
|
|
10402
10921
|
if (!isAutoBatchResourceValue(id)) return void 0;
|
|
10403
10922
|
ids.push(id);
|
|
@@ -10438,7 +10957,7 @@ function flowValuePutOwner(command, start) {
|
|
|
10438
10957
|
}
|
|
10439
10958
|
var flowValuePutOptionTokens = /* @__PURE__ */ new Set(["NAME", "NOW", "OVERRIDE", "OWNER_FLOW_ID", "PARTITION", "TTL", "TTL_MS"]);
|
|
10440
10959
|
function isAutoBatchResourceValue(value) {
|
|
10441
|
-
return typeof value === "string" ||
|
|
10960
|
+
return typeof value === "string" || Buffer40.isBuffer(value);
|
|
10442
10961
|
}
|
|
10443
10962
|
function isFencingToken(value) {
|
|
10444
10963
|
return typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint";
|
|
@@ -10447,7 +10966,7 @@ function nonNegativeItemCount(value) {
|
|
|
10447
10966
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
10448
10967
|
}
|
|
10449
10968
|
function autoBatchResourceKey(namespace, value) {
|
|
10450
|
-
return `${namespace}:${
|
|
10969
|
+
return `${namespace}:${Buffer40.from(value).toString("base64")}`;
|
|
10451
10970
|
}
|
|
10452
10971
|
function autoBatchCommandName(command) {
|
|
10453
10972
|
return commandView(command).name ?? null;
|
|
@@ -10823,7 +11342,7 @@ async function hydrateClaimedRecords(claimed, concurrency, hydrate) {
|
|
|
10823
11342
|
const results = new Array(claimed.length);
|
|
10824
11343
|
let cursor = 0;
|
|
10825
11344
|
let failure;
|
|
10826
|
-
const
|
|
11345
|
+
const run2 = async () => {
|
|
10827
11346
|
while (failure == null) {
|
|
10828
11347
|
const index = cursor;
|
|
10829
11348
|
cursor += 1;
|
|
@@ -10836,7 +11355,7 @@ async function hydrateClaimedRecords(claimed, concurrency, hydrate) {
|
|
|
10836
11355
|
}
|
|
10837
11356
|
}
|
|
10838
11357
|
};
|
|
10839
|
-
await Promise.all(Array.from({ length: Math.min(concurrency, claimed.length) },
|
|
11358
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, claimed.length) }, run2));
|
|
10840
11359
|
if (failure != null) {
|
|
10841
11360
|
const hydratedItems = [];
|
|
10842
11361
|
for (let index = 0; index < results.length; index += 1) {
|
|
@@ -10858,69 +11377,1037 @@ function claimFailure(error) {
|
|
|
10858
11377
|
// src/client-flow-support.ts
|
|
10859
11378
|
import "buffer";
|
|
10860
11379
|
|
|
10861
|
-
// src/
|
|
10862
|
-
import "buffer";
|
|
11380
|
+
// src/flow-query-builder.ts
|
|
11381
|
+
import { Buffer as Buffer43 } from "buffer";
|
|
10863
11382
|
|
|
10864
|
-
// src/
|
|
10865
|
-
import { Buffer as
|
|
10866
|
-
|
|
10867
|
-
|
|
10868
|
-
|
|
11383
|
+
// src/flow-query-metadata.ts
|
|
11384
|
+
import { Buffer as Buffer42 } from "buffer";
|
|
11385
|
+
var MAX_FLOW_QUERY_METADATA_KEY_BYTES = 64;
|
|
11386
|
+
function normalizeStateMeta(value, state) {
|
|
11387
|
+
if (value == null) return {};
|
|
11388
|
+
const entries = objectEntries(value, "stateMeta");
|
|
11389
|
+
if (entries.length === 0) return {};
|
|
11390
|
+
const nested = entries.map(([, item]) => isPlainRecord(item));
|
|
11391
|
+
if (nested.every(Boolean)) {
|
|
11392
|
+
return value;
|
|
10869
11393
|
}
|
|
10870
|
-
|
|
10871
|
-
}
|
|
10872
|
-
function clientNameResponse(response) {
|
|
10873
|
-
return response == null ? null : textResponse(response, "CLIENT GETNAME");
|
|
10874
|
-
}
|
|
10875
|
-
function fetchOrComputeCompletionToken(options) {
|
|
10876
|
-
if (options == null || !Object.hasOwn(options, "computeToken") || options.computeToken === void 0) {
|
|
11394
|
+
if (nested.some(Boolean)) {
|
|
10877
11395
|
throw new TypeError(
|
|
10878
|
-
"
|
|
11396
|
+
"stateMeta must be entirely flat or entirely nested by state"
|
|
10879
11397
|
);
|
|
10880
11398
|
}
|
|
10881
|
-
if (
|
|
10882
|
-
throw new TypeError(
|
|
11399
|
+
if (state == null || state === "" || state === "any") {
|
|
11400
|
+
throw new TypeError(
|
|
11401
|
+
"FLOW.QUERY stateMeta filters require state; a concrete state is required"
|
|
11402
|
+
);
|
|
10883
11403
|
}
|
|
10884
|
-
return
|
|
11404
|
+
return { [state]: value };
|
|
10885
11405
|
}
|
|
10886
|
-
function
|
|
10887
|
-
const
|
|
10888
|
-
|
|
10889
|
-
|
|
10890
|
-
|
|
11406
|
+
function metadataEntries(value, context) {
|
|
11407
|
+
const entries = objectEntries(value ?? {}, context).map(([rawName, item]) => {
|
|
11408
|
+
const name = rawName.trim();
|
|
11409
|
+
const size = Buffer42.byteLength(name, "utf8");
|
|
11410
|
+
if (size === 0 || size > MAX_FLOW_QUERY_METADATA_KEY_BYTES || name.startsWith("__")) {
|
|
11411
|
+
throw new TypeError(`${context} key is invalid or reserved`);
|
|
11412
|
+
}
|
|
11413
|
+
return [name, item];
|
|
11414
|
+
});
|
|
11415
|
+
entries.sort(([left], [right]) => compareUnicodeScalars(left, right));
|
|
11416
|
+
for (let index = 1; index < entries.length; index += 1) {
|
|
11417
|
+
if (entries[index - 1]?.[0] === entries[index]?.[0]) {
|
|
11418
|
+
throw new TypeError(`${context} key is duplicated after normalization`);
|
|
11419
|
+
}
|
|
10891
11420
|
}
|
|
10892
|
-
return
|
|
11421
|
+
return entries;
|
|
10893
11422
|
}
|
|
10894
|
-
function
|
|
10895
|
-
|
|
10896
|
-
|
|
10897
|
-
);
|
|
11423
|
+
function objectEntries(value, context) {
|
|
11424
|
+
if (!isPlainRecord(value))
|
|
11425
|
+
throw new TypeError(`${context} must be a plain object`);
|
|
11426
|
+
const keys = Reflect.ownKeys(value);
|
|
11427
|
+
if (keys.some((key) => typeof key !== "string")) {
|
|
11428
|
+
throw new TypeError(`${context} keys must be strings`);
|
|
11429
|
+
}
|
|
11430
|
+
return keys.map((key) => [key, value[key]]);
|
|
10898
11431
|
}
|
|
10899
|
-
function
|
|
10900
|
-
|
|
11432
|
+
function isPlainRecord(value) {
|
|
11433
|
+
if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer42.isBuffer(value)) {
|
|
11434
|
+
return false;
|
|
11435
|
+
}
|
|
11436
|
+
const prototype = Object.getPrototypeOf(value);
|
|
11437
|
+
return prototype === null || prototype === Object.prototype;
|
|
10901
11438
|
}
|
|
10902
|
-
|
|
10903
|
-
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
11439
|
+
function metadataSelector(root, ...names) {
|
|
11440
|
+
return root + names.map((name) => `['${name.replaceAll("'", "''")}']`).join("");
|
|
11441
|
+
}
|
|
11442
|
+
function compareUnicodeScalars(left, right) {
|
|
11443
|
+
let leftOffset = 0;
|
|
11444
|
+
let rightOffset = 0;
|
|
11445
|
+
while (leftOffset < left.length && rightOffset < right.length) {
|
|
11446
|
+
const leftCodePoint = left.codePointAt(leftOffset);
|
|
11447
|
+
const rightCodePoint = right.codePointAt(rightOffset);
|
|
11448
|
+
if (leftCodePoint == null || rightCodePoint == null) break;
|
|
11449
|
+
if (leftCodePoint !== rightCodePoint)
|
|
11450
|
+
return leftCodePoint < rightCodePoint ? -1 : 1;
|
|
11451
|
+
leftOffset += leftCodePoint > 65535 ? 2 : 1;
|
|
11452
|
+
rightOffset += rightCodePoint > 65535 ? 2 : 1;
|
|
10911
11453
|
}
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
11454
|
+
return left.length === right.length ? 0 : leftOffset === left.length ? -1 : 1;
|
|
11455
|
+
}
|
|
11456
|
+
|
|
11457
|
+
// src/flow-query-builder.ts
|
|
11458
|
+
var MAX_FLOW_QUERY_RESULTS = 100;
|
|
11459
|
+
var MAX_FLOW_QUERY_PARTITION_BYTES = 65535;
|
|
11460
|
+
var MAX_FLOW_QUERY_TIME = Number.MAX_SAFE_INTEGER;
|
|
11461
|
+
var MAX_FLOW_QUERY_STATE_BYTES = 64;
|
|
11462
|
+
var FlowCollectionQuery = class {
|
|
11463
|
+
constructor(partitionKey, limit, reverse) {
|
|
11464
|
+
this.limit = limit;
|
|
11465
|
+
this.reverse = reverse;
|
|
11466
|
+
this.params.partition_key = partitionKey;
|
|
10915
11467
|
}
|
|
10916
|
-
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
11468
|
+
limit;
|
|
11469
|
+
reverse;
|
|
11470
|
+
params = /* @__PURE__ */ Object.create(null);
|
|
11471
|
+
predicates = ["partition_key = @partition_key"];
|
|
11472
|
+
orderField = "updated_at_ms";
|
|
11473
|
+
equality(selector, parameter, value) {
|
|
11474
|
+
this.params[parameter] = queryParameter(value, parameter);
|
|
11475
|
+
this.predicates.push(`${selector} = @${parameter}`);
|
|
11476
|
+
}
|
|
11477
|
+
window(fromMs, toMs) {
|
|
11478
|
+
if (fromMs == null && toMs == null) return;
|
|
11479
|
+
const lower = fromMs == null ? 0 : boundedTime(fromMs, "fromMs");
|
|
11480
|
+
const upper = toMs == null ? MAX_FLOW_QUERY_TIME : boundedTime(toMs, "toMs");
|
|
11481
|
+
if (lower > upper) throw new TypeError("fromMs must not exceed toMs");
|
|
11482
|
+
this.predicates.push("updated_at_ms BETWEEN @from_ms AND @to_ms");
|
|
11483
|
+
this.params.from_ms = lower;
|
|
11484
|
+
this.params.to_ms = upper;
|
|
11485
|
+
}
|
|
11486
|
+
metadata(root, values) {
|
|
11487
|
+
const entries = metadataEntries(values, root);
|
|
11488
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
11489
|
+
const entry = entries[index];
|
|
11490
|
+
if (entry == null) throw new TypeError("metadata entries must be dense");
|
|
11491
|
+
this.equality(
|
|
11492
|
+
metadataSelector(root, entry[0]),
|
|
11493
|
+
`${root}_${index}`,
|
|
11494
|
+
entry[1]
|
|
11495
|
+
);
|
|
10921
11496
|
}
|
|
10922
11497
|
}
|
|
10923
|
-
|
|
11498
|
+
stateMetadata(values) {
|
|
11499
|
+
const entries = [];
|
|
11500
|
+
const states = /* @__PURE__ */ new Set();
|
|
11501
|
+
for (const [rawState, metadata] of objectEntries(values, "stateMeta")) {
|
|
11502
|
+
const state = requiredText(rawState, "stateMeta state").trim();
|
|
11503
|
+
const stateBytes = Buffer43.byteLength(state, "utf8");
|
|
11504
|
+
if (stateBytes === 0 || stateBytes > MAX_FLOW_QUERY_STATE_BYTES) {
|
|
11505
|
+
throw new TypeError(
|
|
11506
|
+
`stateMeta state names must be 1..${MAX_FLOW_QUERY_STATE_BYTES} bytes`
|
|
11507
|
+
);
|
|
11508
|
+
}
|
|
11509
|
+
if (states.has(state)) {
|
|
11510
|
+
throw new TypeError(
|
|
11511
|
+
"stateMeta state is duplicated after normalization"
|
|
11512
|
+
);
|
|
11513
|
+
}
|
|
11514
|
+
states.add(state);
|
|
11515
|
+
if (!isPlainRecord(metadata))
|
|
11516
|
+
throw new TypeError("stateMeta values must be metadata maps");
|
|
11517
|
+
for (const [name, value] of metadataEntries(metadata, "stateMeta")) {
|
|
11518
|
+
entries.push([state, name, value]);
|
|
11519
|
+
}
|
|
11520
|
+
}
|
|
11521
|
+
entries.sort(
|
|
11522
|
+
([leftState, leftName], [rightState, rightName]) => compareUnicodeScalars(leftState, rightState) || compareUnicodeScalars(leftName, rightName)
|
|
11523
|
+
);
|
|
11524
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
11525
|
+
const entry = entries[index];
|
|
11526
|
+
if (entry == null) throw new TypeError("stateMeta entries must be dense");
|
|
11527
|
+
this.equality(
|
|
11528
|
+
metadataSelector("state_meta", entry[0], entry[1]),
|
|
11529
|
+
`state_meta_${index}`,
|
|
11530
|
+
entry[2]
|
|
11531
|
+
);
|
|
11532
|
+
}
|
|
11533
|
+
}
|
|
11534
|
+
build() {
|
|
11535
|
+
if (this.predicates.length > 12) {
|
|
11536
|
+
throw new TypeError("FLOW.QUERY accepts at most 12 predicates");
|
|
11537
|
+
}
|
|
11538
|
+
const direction = this.reverse ? "DESC" : "ASC";
|
|
11539
|
+
const query = `FROM runs WHERE ${this.predicates.join(" AND ")} ORDER BY ${this.orderField} ${direction} LIMIT ${this.limit} RETURN RECORDS`;
|
|
11540
|
+
validateFlowQueryText(query);
|
|
11541
|
+
return { query, params: this.params };
|
|
11542
|
+
}
|
|
11543
|
+
};
|
|
11544
|
+
function buildFlowListQuery(type, options) {
|
|
11545
|
+
const attributeCount = Object.keys(options.attributes ?? {}).length;
|
|
11546
|
+
if (type === "any" && attributeCount === 0) {
|
|
11547
|
+
throw new TypeError(
|
|
11548
|
+
"FLOW.QUERY list requires a concrete flow type or an attribute predicate"
|
|
11549
|
+
);
|
|
11550
|
+
}
|
|
11551
|
+
if (options.terminalOnly !== true && options.state === "any" && attributeCount === 0) {
|
|
11552
|
+
throw new TypeError(
|
|
11553
|
+
"FLOW.QUERY list state any requires an attribute predicate"
|
|
11554
|
+
);
|
|
11555
|
+
}
|
|
11556
|
+
const builder = queryBuilder(options);
|
|
11557
|
+
addType(builder, type);
|
|
11558
|
+
if (options.terminalOnly === true) {
|
|
11559
|
+
addTerminalState(builder, options.state);
|
|
11560
|
+
} else if (options.state == null || options.state === "") {
|
|
11561
|
+
builder.equality("state", "state", "queued");
|
|
11562
|
+
} else if (options.state !== "any") {
|
|
11563
|
+
builder.equality("state", "state", requiredText(options.state, "state"));
|
|
11564
|
+
}
|
|
11565
|
+
builder.metadata("attribute", options.attributes);
|
|
11566
|
+
builder.window(options.fromMs, options.toMs);
|
|
11567
|
+
return builder.build();
|
|
11568
|
+
}
|
|
11569
|
+
function buildFlowSearchQuery(type, options) {
|
|
11570
|
+
const stateMeta = normalizeStateMeta(options.stateMeta, options.state);
|
|
11571
|
+
if (Object.keys(options.attributes ?? {}).length === 0 && Object.keys(stateMeta).length === 0) {
|
|
11572
|
+
throw new TypeError(
|
|
11573
|
+
"FLOW.QUERY search requires an attribute or stateMeta predicate"
|
|
11574
|
+
);
|
|
11575
|
+
}
|
|
11576
|
+
if ((type === "" || type === "any") && Object.keys(stateMeta).length > 0) {
|
|
11577
|
+
throw new TypeError(
|
|
11578
|
+
"FLOW.QUERY stateMeta predicates require a concrete flow type"
|
|
11579
|
+
);
|
|
11580
|
+
}
|
|
11581
|
+
const builder = queryBuilder(options);
|
|
11582
|
+
if (type !== "" && type !== "any")
|
|
11583
|
+
builder.equality("type", "type", requiredText(type, "type"));
|
|
11584
|
+
if (options.terminalOnly === true) {
|
|
11585
|
+
addTerminalState(builder, options.state);
|
|
11586
|
+
} else if (options.state != null && options.state !== "" && options.state !== "any") {
|
|
11587
|
+
builder.equality("state", "state", requiredText(options.state, "state"));
|
|
11588
|
+
}
|
|
11589
|
+
builder.metadata("attribute", options.attributes);
|
|
11590
|
+
builder.stateMetadata(stateMeta);
|
|
11591
|
+
builder.window(options.fromMs, options.toMs);
|
|
11592
|
+
return builder.build();
|
|
11593
|
+
}
|
|
11594
|
+
function buildFlowTerminalQuery(type, options) {
|
|
11595
|
+
if (requiredText(type, "type") === "any") {
|
|
11596
|
+
throw new TypeError("FLOW.QUERY terminals require a concrete flow type");
|
|
11597
|
+
}
|
|
11598
|
+
if (metadataEntries(options.attributes, "attribute").length > 0) {
|
|
11599
|
+
throw new TypeError(
|
|
11600
|
+
"FLOW.QUERY terminals do not support attribute predicates"
|
|
11601
|
+
);
|
|
11602
|
+
}
|
|
11603
|
+
const builder = queryBuilder(options);
|
|
11604
|
+
addType(builder, type);
|
|
11605
|
+
addTerminalState(builder, options.state);
|
|
11606
|
+
builder.window(options.fromMs, options.toMs);
|
|
11607
|
+
return builder.build();
|
|
11608
|
+
}
|
|
11609
|
+
function buildFlowFailureQuery(type, options) {
|
|
11610
|
+
if (options.state != null && options.state !== "" && options.state !== "any" && options.state !== "failed") {
|
|
11611
|
+
throw new TypeError("FLOW failures state must be failed or any");
|
|
11612
|
+
}
|
|
11613
|
+
return buildFlowListQuery(type, {
|
|
11614
|
+
...options,
|
|
11615
|
+
state: "failed",
|
|
11616
|
+
terminalOnly: false
|
|
11617
|
+
});
|
|
11618
|
+
}
|
|
11619
|
+
function buildFlowLineageQuery(selector, id, options) {
|
|
11620
|
+
if (options.terminalOnly === true) {
|
|
11621
|
+
throw new TypeError("terminalOnly cannot be combined with a lineage query");
|
|
11622
|
+
}
|
|
11623
|
+
if (metadataEntries(options.attributes, "attribute").length > 0) {
|
|
11624
|
+
throw new TypeError(
|
|
11625
|
+
"FLOW.QUERY lineage does not support attribute predicates"
|
|
11626
|
+
);
|
|
11627
|
+
}
|
|
11628
|
+
const builder = queryBuilder(options);
|
|
11629
|
+
builder.equality(selector, "lineage_id", requiredText(id, "lineage id"));
|
|
11630
|
+
if (options.state != null && options.state !== "" && options.state !== "any") {
|
|
11631
|
+
builder.equality("state", "state", requiredText(options.state, "state"));
|
|
11632
|
+
}
|
|
11633
|
+
builder.metadata("attribute", options.attributes);
|
|
11634
|
+
builder.window(options.fromMs, options.toMs);
|
|
11635
|
+
return builder.build();
|
|
11636
|
+
}
|
|
11637
|
+
function buildFlowStuckQuery(type, options) {
|
|
11638
|
+
const concreteType = requiredText(type, "type");
|
|
11639
|
+
if (concreteType === "any") {
|
|
11640
|
+
throw new TypeError("FLOW.QUERY stuck requires a concrete flow type");
|
|
11641
|
+
}
|
|
11642
|
+
const now = options.nowMs == null ? Date.now() : boundedTime(options.nowMs, "nowMs");
|
|
11643
|
+
const older = options.olderThanMs == null ? 0 : boundedTime(options.olderThanMs, "olderThanMs");
|
|
11644
|
+
const cutoff = now - older;
|
|
11645
|
+
if (cutoff < 0) throw new TypeError("olderThanMs must not exceed nowMs");
|
|
11646
|
+
const builder = new FlowCollectionQuery(
|
|
11647
|
+
requiredPartition(options.partitionKey),
|
|
11648
|
+
boundedCount(options.count),
|
|
11649
|
+
false
|
|
11650
|
+
);
|
|
11651
|
+
builder.orderField = "lease_deadline_ms";
|
|
11652
|
+
builder.equality("type", "type", concreteType);
|
|
11653
|
+
builder.equality("state", "state", "running");
|
|
11654
|
+
builder.predicates.push(
|
|
11655
|
+
"lease_deadline_ms BETWEEN @lease_from_ms AND @lease_to_ms"
|
|
11656
|
+
);
|
|
11657
|
+
builder.params.lease_from_ms = 0;
|
|
11658
|
+
builder.params.lease_to_ms = cutoff;
|
|
11659
|
+
return builder.build();
|
|
11660
|
+
}
|
|
11661
|
+
function queryBuilder(options) {
|
|
11662
|
+
if (options.includeCold === true)
|
|
11663
|
+
throw new TypeError("FLOW.QUERY does not expose includeCold");
|
|
11664
|
+
if (options.consistentProjection === true) {
|
|
11665
|
+
throw new TypeError("FLOW.QUERY does not expose consistentProjection");
|
|
11666
|
+
}
|
|
11667
|
+
if (options.rev != null && typeof options.rev !== "boolean") {
|
|
11668
|
+
throw new TypeError("rev must be boolean");
|
|
11669
|
+
}
|
|
11670
|
+
return new FlowCollectionQuery(
|
|
11671
|
+
requiredPartition(options.partitionKey),
|
|
11672
|
+
boundedCount(options.count),
|
|
11673
|
+
options.rev !== false
|
|
11674
|
+
);
|
|
11675
|
+
}
|
|
11676
|
+
function requiredPartition(value) {
|
|
11677
|
+
if (typeof value !== "string") {
|
|
11678
|
+
throw new TypeError(
|
|
11679
|
+
"FLOW.QUERY convenience methods require a partition key"
|
|
11680
|
+
);
|
|
11681
|
+
}
|
|
11682
|
+
const size = Buffer43.byteLength(value, "utf8");
|
|
11683
|
+
if (size === 0 || size > MAX_FLOW_QUERY_PARTITION_BYTES) {
|
|
11684
|
+
throw new TypeError(
|
|
11685
|
+
`FLOW.QUERY partition key must be 1..${MAX_FLOW_QUERY_PARTITION_BYTES} bytes`
|
|
11686
|
+
);
|
|
11687
|
+
}
|
|
11688
|
+
return value;
|
|
11689
|
+
}
|
|
11690
|
+
function boundedCount(value) {
|
|
11691
|
+
if (value == null) return MAX_FLOW_QUERY_RESULTS;
|
|
11692
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_FLOW_QUERY_RESULTS) {
|
|
11693
|
+
throw new TypeError(
|
|
11694
|
+
`FLOW.QUERY limit must be between 1 and ${MAX_FLOW_QUERY_RESULTS}`
|
|
11695
|
+
);
|
|
11696
|
+
}
|
|
11697
|
+
return value;
|
|
11698
|
+
}
|
|
11699
|
+
function boundedTime(value, name) {
|
|
11700
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > MAX_FLOW_QUERY_TIME) {
|
|
11701
|
+
throw new TypeError(`${name} must be a non-negative safe integer`);
|
|
11702
|
+
}
|
|
11703
|
+
return value;
|
|
11704
|
+
}
|
|
11705
|
+
function addType(builder, type) {
|
|
11706
|
+
const normalized = requiredText(type, "type");
|
|
11707
|
+
if (normalized !== "any") builder.equality("type", "type", normalized);
|
|
11708
|
+
}
|
|
11709
|
+
function addTerminalState(builder, state) {
|
|
11710
|
+
if (state == null || state === "" || state === "any") {
|
|
11711
|
+
builder.predicates.push("state IN (@terminal_0, @terminal_1, @terminal_2)");
|
|
11712
|
+
builder.params.terminal_0 = "completed";
|
|
11713
|
+
builder.params.terminal_1 = "failed";
|
|
11714
|
+
builder.params.terminal_2 = "cancelled";
|
|
11715
|
+
} else if (state === "completed" || state === "failed" || state === "cancelled") {
|
|
11716
|
+
builder.equality("state", "state", state);
|
|
11717
|
+
} else {
|
|
11718
|
+
throw new TypeError(
|
|
11719
|
+
"terminal state must be completed, failed, cancelled, or any"
|
|
11720
|
+
);
|
|
11721
|
+
}
|
|
11722
|
+
}
|
|
11723
|
+
function requiredText(value, context) {
|
|
11724
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
11725
|
+
throw new TypeError(`${context} must be non-empty text`);
|
|
11726
|
+
}
|
|
11727
|
+
return value;
|
|
11728
|
+
}
|
|
11729
|
+
function queryParameter(value, context) {
|
|
11730
|
+
if (typeof value === "string" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "number" || Buffer43.isBuffer(value)) {
|
|
11731
|
+
return value;
|
|
11732
|
+
}
|
|
11733
|
+
throw new TypeError(`${context} must be a scalar FLOW.QUERY parameter`);
|
|
11734
|
+
}
|
|
11735
|
+
|
|
11736
|
+
// src/flow-query-response.ts
|
|
11737
|
+
import { Buffer as Buffer45 } from "buffer";
|
|
11738
|
+
|
|
11739
|
+
// src/flow-query-response-validation.ts
|
|
11740
|
+
import { Buffer as Buffer44 } from "buffer";
|
|
11741
|
+
function requiredMap2(value, context) {
|
|
11742
|
+
if (value instanceof Map) return value;
|
|
11743
|
+
if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer44.isBuffer(value) || value instanceof Uint8Array) {
|
|
11744
|
+
throw decodeError(`${context} must be a map`, value);
|
|
11745
|
+
}
|
|
11746
|
+
return value;
|
|
11747
|
+
}
|
|
11748
|
+
function freezeMap(value) {
|
|
11749
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
11750
|
+
const entries = value instanceof Map ? value.entries() : Object.entries(value);
|
|
11751
|
+
for (const [rawKey, item] of entries) {
|
|
11752
|
+
const key = strictText2(rawKey);
|
|
11753
|
+
if (key == null || Object.hasOwn(output, key)) {
|
|
11754
|
+
throw decodeError(
|
|
11755
|
+
"server response map contains an invalid or duplicate key",
|
|
11756
|
+
value
|
|
11757
|
+
);
|
|
11758
|
+
}
|
|
11759
|
+
output[key] = item;
|
|
11760
|
+
}
|
|
11761
|
+
return Object.freeze(output);
|
|
11762
|
+
}
|
|
11763
|
+
function freezeMetadataMap(value, context) {
|
|
11764
|
+
return normalizeMetadataMap(
|
|
11765
|
+
value,
|
|
11766
|
+
context,
|
|
11767
|
+
{ remaining: DEFAULT_MAX_VALUE_ITEMS },
|
|
11768
|
+
/* @__PURE__ */ new Set(),
|
|
11769
|
+
0
|
|
11770
|
+
);
|
|
11771
|
+
}
|
|
11772
|
+
function normalizeMetadataMap(value, context, budget, ancestors, depth) {
|
|
11773
|
+
enterMetadataContainer(value, context, budget, ancestors, depth);
|
|
11774
|
+
try {
|
|
11775
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
11776
|
+
const entries = value instanceof Map ? value.entries() : Object.entries(value);
|
|
11777
|
+
for (const [rawKey, item] of entries) {
|
|
11778
|
+
const key = strictText2(rawKey);
|
|
11779
|
+
if (key == null || Object.hasOwn(output, key)) {
|
|
11780
|
+
throw decodeError(`${context} contains an invalid or duplicate key`, value);
|
|
11781
|
+
}
|
|
11782
|
+
output[key] = normalizeMetadataValue(
|
|
11783
|
+
item,
|
|
11784
|
+
`${context}.${key}`,
|
|
11785
|
+
budget,
|
|
11786
|
+
ancestors,
|
|
11787
|
+
depth + 1
|
|
11788
|
+
);
|
|
11789
|
+
}
|
|
11790
|
+
return Object.freeze(output);
|
|
11791
|
+
} finally {
|
|
11792
|
+
ancestors.delete(value);
|
|
11793
|
+
}
|
|
11794
|
+
}
|
|
11795
|
+
function normalizeMetadataValue(value, context, budget, ancestors, depth) {
|
|
11796
|
+
if (typeof value === "string") {
|
|
11797
|
+
if (!value.isWellFormed()) throw decodeError(`${context} contains invalid text`, value);
|
|
11798
|
+
return value;
|
|
11799
|
+
}
|
|
11800
|
+
if (Buffer44.isBuffer(value) || value instanceof Uint8Array) {
|
|
11801
|
+
const decoded = strictText2(value);
|
|
11802
|
+
if (decoded == null) throw decodeError(`${context} contains invalid UTF-8`, value);
|
|
11803
|
+
return decoded;
|
|
11804
|
+
}
|
|
11805
|
+
if (value == null || typeof value === "boolean" || typeof value === "number" || typeof value === "bigint") {
|
|
11806
|
+
return value;
|
|
11807
|
+
}
|
|
11808
|
+
if (Array.isArray(value)) {
|
|
11809
|
+
enterMetadataContainer(value, context, budget, ancestors, depth);
|
|
11810
|
+
try {
|
|
11811
|
+
const output = new Array(value.length);
|
|
11812
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
11813
|
+
if (!Object.hasOwn(value, index)) {
|
|
11814
|
+
throw decodeError(`${context} must be a dense array`, value);
|
|
11815
|
+
}
|
|
11816
|
+
output[index] = normalizeMetadataValue(
|
|
11817
|
+
value[index],
|
|
11818
|
+
`${context}[${index}]`,
|
|
11819
|
+
budget,
|
|
11820
|
+
ancestors,
|
|
11821
|
+
depth + 1
|
|
11822
|
+
);
|
|
11823
|
+
}
|
|
11824
|
+
return Object.freeze(output);
|
|
11825
|
+
} finally {
|
|
11826
|
+
ancestors.delete(value);
|
|
11827
|
+
}
|
|
11828
|
+
}
|
|
11829
|
+
if (value instanceof Map) {
|
|
11830
|
+
return normalizeMetadataMap(value, context, budget, ancestors, depth);
|
|
11831
|
+
}
|
|
11832
|
+
if (isPlainObject6(value)) {
|
|
11833
|
+
return normalizeMetadataMap(value, context, budget, ancestors, depth);
|
|
11834
|
+
}
|
|
11835
|
+
throw decodeError(`${context} contains an unsupported value`, value);
|
|
11836
|
+
}
|
|
11837
|
+
function enterMetadataContainer(value, context, budget, ancestors, depth) {
|
|
11838
|
+
if (depth >= DEFAULT_MAX_VALUE_DEPTH) {
|
|
11839
|
+
throw decodeError(`${context} exceeds the maximum metadata depth`, value);
|
|
11840
|
+
}
|
|
11841
|
+
if (ancestors.has(value)) throw decodeError(`${context} contains a cycle`, value);
|
|
11842
|
+
const size = Array.isArray(value) ? value.length : value instanceof Map ? value.size : Object.keys(value).length;
|
|
11843
|
+
if (size > budget.remaining) {
|
|
11844
|
+
throw decodeError(`${context} exceeds the maximum metadata items`, value);
|
|
11845
|
+
}
|
|
11846
|
+
budget.remaining -= size;
|
|
11847
|
+
ancestors.add(value);
|
|
11848
|
+
}
|
|
11849
|
+
function isPlainObject6(value) {
|
|
11850
|
+
const prototype = Object.getPrototypeOf(value);
|
|
11851
|
+
return prototype === Object.prototype || prototype === null;
|
|
11852
|
+
}
|
|
11853
|
+
function requireContract(mapping, name, expected, context) {
|
|
11854
|
+
const actual = requiredText2(mapping, name, context);
|
|
11855
|
+
if (actual !== expected) {
|
|
11856
|
+
throw decodeError(
|
|
11857
|
+
`${context} has unsupported contract ${JSON.stringify(actual)}`,
|
|
11858
|
+
mapping
|
|
11859
|
+
);
|
|
11860
|
+
}
|
|
11861
|
+
}
|
|
11862
|
+
function requiredText2(mapping, name, context) {
|
|
11863
|
+
const value = strictText2(field(mapping, name));
|
|
11864
|
+
if (value == null || value.length === 0) {
|
|
11865
|
+
throw decodeError(`${context} ${name} must be non-empty text`, mapping);
|
|
11866
|
+
}
|
|
11867
|
+
return value;
|
|
11868
|
+
}
|
|
11869
|
+
function optionalText2(mapping, name, context) {
|
|
11870
|
+
const raw = field(mapping, name);
|
|
11871
|
+
if (raw == null) return void 0;
|
|
11872
|
+
const value = strictText2(raw);
|
|
11873
|
+
if (value == null)
|
|
11874
|
+
throw decodeError(`${context} ${name} must be text`, mapping);
|
|
11875
|
+
return value;
|
|
11876
|
+
}
|
|
11877
|
+
function requiredBoundedText2(mapping, name, context, maximumBytes) {
|
|
11878
|
+
const value = requiredText2(mapping, name, context);
|
|
11879
|
+
if (Buffer44.byteLength(value, "utf8") > maximumBytes) {
|
|
11880
|
+
throw decodeError(
|
|
11881
|
+
`${context} ${name} exceeds ${maximumBytes} bytes`,
|
|
11882
|
+
mapping
|
|
11883
|
+
);
|
|
11884
|
+
}
|
|
11885
|
+
return value;
|
|
11886
|
+
}
|
|
11887
|
+
function boundedText(value, context, maximumBytes) {
|
|
11888
|
+
const decoded = strictText2(value);
|
|
11889
|
+
if (decoded == null || decoded.length === 0) {
|
|
11890
|
+
throw decodeError(`${context} must be non-empty text`, value);
|
|
11891
|
+
}
|
|
11892
|
+
if (Buffer44.byteLength(decoded, "utf8") > maximumBytes) {
|
|
11893
|
+
throw decodeError(`${context} exceeds ${maximumBytes} bytes`, value);
|
|
11894
|
+
}
|
|
11895
|
+
return decoded;
|
|
11896
|
+
}
|
|
11897
|
+
function requiredBoolean(mapping, name, context) {
|
|
11898
|
+
const value = field(mapping, name);
|
|
11899
|
+
if (typeof value !== "boolean") {
|
|
11900
|
+
throw decodeError(`${context} ${name} must be boolean`, mapping);
|
|
11901
|
+
}
|
|
11902
|
+
return value;
|
|
11903
|
+
}
|
|
11904
|
+
function nonNegativeInteger(value, context) {
|
|
11905
|
+
if (typeof value === "bigint") {
|
|
11906
|
+
if (value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER))
|
|
11907
|
+
return Number(value);
|
|
11908
|
+
} else if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
|
|
11909
|
+
return value;
|
|
11910
|
+
}
|
|
11911
|
+
throw decodeError(`${context} must be a non-negative safe integer`, value);
|
|
11912
|
+
}
|
|
11913
|
+
function positiveInteger(value, context) {
|
|
11914
|
+
const parsed = nonNegativeInteger(value, context);
|
|
11915
|
+
if (parsed === 0) throw decodeError(`${context} must be positive`, value);
|
|
11916
|
+
return parsed;
|
|
11917
|
+
}
|
|
11918
|
+
function boundedInteger(value, maximum, context) {
|
|
11919
|
+
let parsed;
|
|
11920
|
+
if (typeof value === "bigint") {
|
|
11921
|
+
parsed = value;
|
|
11922
|
+
} else if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
11923
|
+
parsed = BigInt(value);
|
|
11924
|
+
} else {
|
|
11925
|
+
throw decodeError(
|
|
11926
|
+
`${context} must be a lossless non-negative integer`,
|
|
11927
|
+
value
|
|
11928
|
+
);
|
|
11929
|
+
}
|
|
11930
|
+
if (parsed < 0n || parsed > maximum) {
|
|
11931
|
+
throw decodeError(
|
|
11932
|
+
`${context} is outside its supported integer range`,
|
|
11933
|
+
value
|
|
11934
|
+
);
|
|
11935
|
+
}
|
|
11936
|
+
return parsed <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(parsed) : parsed;
|
|
11937
|
+
}
|
|
11938
|
+
function positiveBoundedInteger(value, maximum, context) {
|
|
11939
|
+
const parsed = boundedInteger(value, maximum, context);
|
|
11940
|
+
if (parsed === 0) throw decodeError(`${context} must be positive`, value);
|
|
11941
|
+
return parsed;
|
|
11942
|
+
}
|
|
11943
|
+
function hasKey(mapping, name) {
|
|
11944
|
+
if (!(mapping instanceof Map)) return Object.hasOwn(mapping, name);
|
|
11945
|
+
if (mapping.has(name)) return true;
|
|
11946
|
+
const binaryName = Buffer44.from(name);
|
|
11947
|
+
for (const key of mapping.keys()) {
|
|
11948
|
+
if (Buffer44.isBuffer(key) && key.equals(binaryName)) return true;
|
|
11949
|
+
if (key instanceof Uint8Array && Buffer44.from(key).equals(binaryName))
|
|
11950
|
+
return true;
|
|
11951
|
+
}
|
|
11952
|
+
return false;
|
|
11953
|
+
}
|
|
11954
|
+
function decodeError(message, raw) {
|
|
11955
|
+
return new FerricStoreError(`invalid server response: ${message}`, { raw });
|
|
11956
|
+
}
|
|
11957
|
+
function strictText2(value) {
|
|
11958
|
+
if (typeof value === "string")
|
|
11959
|
+
return value.isWellFormed() ? value : void 0;
|
|
11960
|
+
if (Buffer44.isBuffer(value) || value instanceof Uint8Array) {
|
|
11961
|
+
try {
|
|
11962
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
11963
|
+
} catch {
|
|
11964
|
+
return void 0;
|
|
11965
|
+
}
|
|
11966
|
+
}
|
|
11967
|
+
return void 0;
|
|
11968
|
+
}
|
|
11969
|
+
|
|
11970
|
+
// src/flow-query-types.ts
|
|
11971
|
+
var FlowQueryError = class extends FerricStoreError {
|
|
11972
|
+
code;
|
|
11973
|
+
detail;
|
|
11974
|
+
hint;
|
|
11975
|
+
position;
|
|
11976
|
+
context;
|
|
11977
|
+
constructor(options) {
|
|
11978
|
+
super(options.message, {
|
|
11979
|
+
cause: options.cause,
|
|
11980
|
+
raw: options.raw,
|
|
11981
|
+
retryable: options.retryable,
|
|
11982
|
+
safeToRetry: options.safeToRetry,
|
|
11983
|
+
retryAfterMs: options.retryAfterMs
|
|
11984
|
+
});
|
|
11985
|
+
this.code = options.code;
|
|
11986
|
+
this.detail = options.detail;
|
|
11987
|
+
this.hint = options.hint;
|
|
11988
|
+
this.position = options.position;
|
|
11989
|
+
this.context = options.context;
|
|
11990
|
+
}
|
|
11991
|
+
};
|
|
11992
|
+
|
|
11993
|
+
// src/flow-query-response.ts
|
|
11994
|
+
var FLOW_QUERY_RESULT_CONTRACT = "ferric.flow.query.result/v1";
|
|
11995
|
+
var FLOW_EXPLAIN_CONTRACT = "ferric.flow.explain/v1";
|
|
11996
|
+
var FLOW_QUERY_INDEXES_CONTRACT = "ferric.flow.query.indexes/v1";
|
|
11997
|
+
var USAGE_FIELDS2 = [
|
|
11998
|
+
["range_seeks", "rangeSeeks"],
|
|
11999
|
+
["range_pages", "rangePages"],
|
|
12000
|
+
["scanned_entries", "scannedEntries"],
|
|
12001
|
+
["scanned_bytes", "scannedBytes"],
|
|
12002
|
+
["hydrated_records", "hydratedRecords"],
|
|
12003
|
+
["residual_checks", "residualChecks"],
|
|
12004
|
+
["duplicate_entries", "duplicateEntries"],
|
|
12005
|
+
["result_records", "resultRecords"],
|
|
12006
|
+
["response_bytes", "responseBytes"],
|
|
12007
|
+
["memory_high_water_bytes", "memoryHighWaterBytes"],
|
|
12008
|
+
["wall_time_us", "wallTimeUs"]
|
|
12009
|
+
];
|
|
12010
|
+
var MAX_SIGNED_64 = (1n << 63n) - 1n;
|
|
12011
|
+
var MAX_UNSIGNED_64 = (1n << 64n) - 1n;
|
|
12012
|
+
function decodeFlowQueryResult(value) {
|
|
12013
|
+
const result = decodeFlowQueryResponse(value, (mapping) => freezeMap(mapping));
|
|
12014
|
+
if (result.kind === "records") {
|
|
12015
|
+
return Object.freeze({
|
|
12016
|
+
kind: "records",
|
|
12017
|
+
version: FLOW_QUERY_RESULT_CONTRACT,
|
|
12018
|
+
records: Object.freeze(result.records),
|
|
12019
|
+
page: result.page,
|
|
12020
|
+
quality: result.quality,
|
|
12021
|
+
usage: result.usage,
|
|
12022
|
+
raw: result.raw
|
|
12023
|
+
});
|
|
12024
|
+
}
|
|
12025
|
+
return Object.freeze({
|
|
12026
|
+
kind: "count",
|
|
12027
|
+
version: FLOW_QUERY_RESULT_CONTRACT,
|
|
12028
|
+
count: result.count,
|
|
12029
|
+
quality: result.quality,
|
|
12030
|
+
usage: result.usage,
|
|
12031
|
+
raw: result.raw
|
|
12032
|
+
});
|
|
12033
|
+
}
|
|
12034
|
+
function decodeFlowQueryRecords(value, decodeRecord) {
|
|
12035
|
+
const result = decodeFlowQueryResponse(
|
|
12036
|
+
value,
|
|
12037
|
+
(mapping, index) => decodeRecord(mapping instanceof Map ? freezeMap(mapping) : mapping, index)
|
|
12038
|
+
);
|
|
12039
|
+
if (result.kind === "count") {
|
|
12040
|
+
throw new FerricStoreError("Flow record convenience query returned a count result", {
|
|
12041
|
+
raw: result.raw
|
|
12042
|
+
});
|
|
12043
|
+
}
|
|
12044
|
+
return result.records;
|
|
12045
|
+
}
|
|
12046
|
+
function decodeFlowQueryResponse(value, decodeRecord) {
|
|
12047
|
+
const mapping = requiredMap2(value, "FLOW.QUERY result");
|
|
12048
|
+
requireContract(mapping, "version", FLOW_QUERY_RESULT_CONTRACT, "FLOW.QUERY result");
|
|
12049
|
+
const quality = decodeQuality(field(mapping, "quality"));
|
|
12050
|
+
const usage = decodeUsage(field(mapping, "usage"));
|
|
12051
|
+
const hasRecords = hasKey(mapping, "records");
|
|
12052
|
+
const hasCount = hasKey(mapping, "result");
|
|
12053
|
+
if (hasRecords === hasCount) {
|
|
12054
|
+
throw decodeError("FLOW.QUERY result must contain exactly one records or count shape", value);
|
|
12055
|
+
}
|
|
12056
|
+
const raw = freezeMap(mapping);
|
|
12057
|
+
if (hasRecords) {
|
|
12058
|
+
const rawRecords = field(mapping, "records");
|
|
12059
|
+
if (!Array.isArray(rawRecords) || rawRecords.length > 100) {
|
|
12060
|
+
throw decodeError("FLOW.QUERY records must be an array of at most 100 maps", value);
|
|
12061
|
+
}
|
|
12062
|
+
const records = new Array(rawRecords.length);
|
|
12063
|
+
for (let index = 0; index < rawRecords.length; index += 1) {
|
|
12064
|
+
if (!Object.hasOwn(rawRecords, index)) {
|
|
12065
|
+
throw decodeError("FLOW.QUERY records must be a dense array", value);
|
|
12066
|
+
}
|
|
12067
|
+
records[index] = decodeRecord(
|
|
12068
|
+
requiredMap2(rawRecords[index], `FLOW.QUERY record ${index}`),
|
|
12069
|
+
index
|
|
12070
|
+
);
|
|
12071
|
+
}
|
|
12072
|
+
if (usage.resultRecords !== records.length) {
|
|
12073
|
+
throw decodeError("FLOW.QUERY usage result_records does not match records", value);
|
|
12074
|
+
}
|
|
12075
|
+
return {
|
|
12076
|
+
kind: "records",
|
|
12077
|
+
records,
|
|
12078
|
+
page: decodePage(field(mapping, "page")),
|
|
12079
|
+
quality,
|
|
12080
|
+
usage,
|
|
12081
|
+
raw
|
|
12082
|
+
};
|
|
12083
|
+
}
|
|
12084
|
+
if (hasKey(mapping, "page")) {
|
|
12085
|
+
throw decodeError("FLOW.QUERY count result contains an unexpected page", value);
|
|
12086
|
+
}
|
|
12087
|
+
const countResult = requiredMap2(field(mapping, "result"), "FLOW.QUERY count result");
|
|
12088
|
+
if (requiredText2(countResult, "kind", "FLOW.QUERY count result") !== "count") {
|
|
12089
|
+
throw decodeError("FLOW.QUERY count result kind must be count", value);
|
|
12090
|
+
}
|
|
12091
|
+
const count = boundedInteger(
|
|
12092
|
+
field(countResult, "value"),
|
|
12093
|
+
MAX_SIGNED_64,
|
|
12094
|
+
"FLOW.QUERY count value"
|
|
12095
|
+
);
|
|
12096
|
+
if (usage.resultRecords !== 1) {
|
|
12097
|
+
throw decodeError("FLOW.QUERY count usage result_records must be 1", value);
|
|
12098
|
+
}
|
|
12099
|
+
return {
|
|
12100
|
+
kind: "count",
|
|
12101
|
+
count,
|
|
12102
|
+
quality,
|
|
12103
|
+
usage,
|
|
12104
|
+
raw
|
|
12105
|
+
};
|
|
12106
|
+
}
|
|
12107
|
+
function decodeFlowExplainResult(value) {
|
|
12108
|
+
const mapping = requiredMap2(value, "FLOW.QUERY explain");
|
|
12109
|
+
requireContract(mapping, "version", FLOW_EXPLAIN_CONTRACT, "FLOW.QUERY explain");
|
|
12110
|
+
const queryFingerprint = requiredText2(mapping, "query_fingerprint", "FLOW.QUERY explain");
|
|
12111
|
+
if (!/^[0-9a-f]{64}$/iu.test(queryFingerprint)) {
|
|
12112
|
+
throw decodeError("FLOW.QUERY explain query_fingerprint is invalid", value);
|
|
12113
|
+
}
|
|
12114
|
+
const status = requiredText2(mapping, "status", "FLOW.QUERY explain");
|
|
12115
|
+
if (status !== "planned" && status !== "rejected" && status !== "executed") {
|
|
12116
|
+
throw decodeError(`FLOW.QUERY explain status ${JSON.stringify(status)} is unsupported`, value);
|
|
12117
|
+
}
|
|
12118
|
+
const plan = freezeMetadataMap(
|
|
12119
|
+
requiredMap2(field(mapping, "plan"), "FLOW.QUERY explain plan"),
|
|
12120
|
+
"FLOW.QUERY explain plan"
|
|
12121
|
+
);
|
|
12122
|
+
const estimate = freezeMetadataMap(
|
|
12123
|
+
requiredMap2(field(mapping, "estimate"), "FLOW.QUERY explain estimate"),
|
|
12124
|
+
"FLOW.QUERY explain estimate"
|
|
12125
|
+
);
|
|
12126
|
+
const bounds = freezeMetadataMap(
|
|
12127
|
+
requiredMap2(field(mapping, "bounds"), "FLOW.QUERY explain bounds"),
|
|
12128
|
+
"FLOW.QUERY explain bounds"
|
|
12129
|
+
);
|
|
12130
|
+
const actualValue = field(mapping, "actual");
|
|
12131
|
+
let actual;
|
|
12132
|
+
if (status === "executed") {
|
|
12133
|
+
if (actualValue == null) {
|
|
12134
|
+
throw decodeError("FLOW.QUERY executed explain is missing actual usage", value);
|
|
12135
|
+
}
|
|
12136
|
+
actual = decodeUsage(actualValue);
|
|
12137
|
+
} else if (actualValue != null) {
|
|
12138
|
+
throw decodeError("FLOW.QUERY non-executed explain contains actual usage", value);
|
|
12139
|
+
}
|
|
12140
|
+
const diagnosticValue = field(mapping, "diagnostic");
|
|
12141
|
+
let diagnostic;
|
|
12142
|
+
if (status === "rejected") {
|
|
12143
|
+
diagnostic = tryDecodeFlowQueryError(diagnosticValue);
|
|
12144
|
+
if (diagnostic == null) {
|
|
12145
|
+
throw decodeError("FLOW.QUERY rejected explain has an invalid diagnostic", value);
|
|
12146
|
+
}
|
|
12147
|
+
} else if (diagnosticValue != null) {
|
|
12148
|
+
throw decodeError("FLOW.QUERY non-rejected explain contains a diagnostic", value);
|
|
12149
|
+
}
|
|
12150
|
+
return Object.freeze({
|
|
12151
|
+
version: FLOW_EXPLAIN_CONTRACT,
|
|
12152
|
+
queryFingerprint,
|
|
12153
|
+
status,
|
|
12154
|
+
plan,
|
|
12155
|
+
estimate,
|
|
12156
|
+
bounds,
|
|
12157
|
+
actual,
|
|
12158
|
+
diagnostic,
|
|
12159
|
+
raw: freezeMap(mapping)
|
|
12160
|
+
});
|
|
12161
|
+
}
|
|
12162
|
+
function tryDecodeFlowQueryError(value, cause) {
|
|
12163
|
+
try {
|
|
12164
|
+
const mapping = requiredMap2(value, "FLOW.QUERY diagnostic");
|
|
12165
|
+
const contextValue = field(mapping, "context");
|
|
12166
|
+
const context = contextValue == null ? void 0 : freezeMetadataMap(
|
|
12167
|
+
requiredMap2(contextValue, "FLOW.QUERY diagnostic context"),
|
|
12168
|
+
"FLOW.QUERY diagnostic context"
|
|
12169
|
+
);
|
|
12170
|
+
const position = decodePosition(field(mapping, "position"));
|
|
12171
|
+
return new FlowQueryError({
|
|
12172
|
+
code: requiredText2(mapping, "code", "FLOW.QUERY diagnostic"),
|
|
12173
|
+
message: requiredText2(mapping, "message", "FLOW.QUERY diagnostic"),
|
|
12174
|
+
detail: optionalText2(mapping, "detail", "FLOW.QUERY diagnostic"),
|
|
12175
|
+
hint: optionalText2(mapping, "hint", "FLOW.QUERY diagnostic"),
|
|
12176
|
+
retryable: requiredBoolean(mapping, "retryable", "FLOW.QUERY diagnostic"),
|
|
12177
|
+
safeToRetry: requiredBoolean(mapping, "safe_to_retry", "FLOW.QUERY diagnostic"),
|
|
12178
|
+
retryAfterMs: nonNegativeInteger(
|
|
12179
|
+
field(mapping, "retry_after_ms"),
|
|
12180
|
+
"FLOW.QUERY diagnostic retry_after_ms"
|
|
12181
|
+
),
|
|
12182
|
+
position,
|
|
12183
|
+
context,
|
|
12184
|
+
raw: value,
|
|
12185
|
+
cause
|
|
12186
|
+
});
|
|
12187
|
+
} catch (error) {
|
|
12188
|
+
if (error instanceof FerricStoreError) return void 0;
|
|
12189
|
+
throw error;
|
|
12190
|
+
}
|
|
12191
|
+
}
|
|
12192
|
+
function decodeFlowQueryIndexStatus(value) {
|
|
12193
|
+
const mapping = requiredMap2(value, "FLOW.QUERY.INDEXES");
|
|
12194
|
+
requireContract(
|
|
12195
|
+
mapping,
|
|
12196
|
+
"contract_version",
|
|
12197
|
+
FLOW_QUERY_INDEXES_CONTRACT,
|
|
12198
|
+
"FLOW.QUERY.INDEXES"
|
|
12199
|
+
);
|
|
12200
|
+
const registry = requiredMap2(field(mapping, "registry"), "FLOW.QUERY.INDEXES registry");
|
|
12201
|
+
const services = freezeMetadataMap(
|
|
12202
|
+
requiredMap2(field(mapping, "services"), "FLOW.QUERY.INDEXES services"),
|
|
12203
|
+
"FLOW.QUERY.INDEXES services"
|
|
12204
|
+
);
|
|
12205
|
+
const rawIndexes = field(mapping, "indexes");
|
|
12206
|
+
if (!Array.isArray(rawIndexes) || rawIndexes.length > 32) {
|
|
12207
|
+
throw decodeError("FLOW.QUERY.INDEXES indexes must contain at most 32 entries", value);
|
|
12208
|
+
}
|
|
12209
|
+
const indexes = new Array(rawIndexes.length);
|
|
12210
|
+
for (let index = 0; index < rawIndexes.length; index += 1) {
|
|
12211
|
+
if (!Object.hasOwn(rawIndexes, index)) {
|
|
12212
|
+
throw decodeError("FLOW.QUERY.INDEXES indexes must be a dense array", value);
|
|
12213
|
+
}
|
|
12214
|
+
indexes[index] = decodeIndex(rawIndexes[index], index);
|
|
12215
|
+
}
|
|
12216
|
+
return Object.freeze({
|
|
12217
|
+
contractVersion: FLOW_QUERY_INDEXES_CONTRACT,
|
|
12218
|
+
observedAtMs: nonNegativeInteger(
|
|
12219
|
+
field(mapping, "observed_at_ms"),
|
|
12220
|
+
"FLOW.QUERY.INDEXES observed_at_ms"
|
|
12221
|
+
),
|
|
12222
|
+
statisticsMaxAgeMs: nonNegativeInteger(
|
|
12223
|
+
field(mapping, "statistics_max_age_ms"),
|
|
12224
|
+
"FLOW.QUERY.INDEXES statistics_max_age_ms"
|
|
12225
|
+
),
|
|
12226
|
+
registry: Object.freeze({
|
|
12227
|
+
epoch: boundedInteger(
|
|
12228
|
+
field(registry, "epoch"),
|
|
12229
|
+
MAX_UNSIGNED_64,
|
|
12230
|
+
"FLOW.QUERY.INDEXES epoch"
|
|
12231
|
+
),
|
|
12232
|
+
catalogVersion: positiveBoundedInteger(
|
|
12233
|
+
field(registry, "catalog_version"),
|
|
12234
|
+
MAX_UNSIGNED_64,
|
|
12235
|
+
"FLOW.QUERY.INDEXES catalog_version"
|
|
12236
|
+
)
|
|
12237
|
+
}),
|
|
12238
|
+
services,
|
|
12239
|
+
indexes: Object.freeze(indexes),
|
|
12240
|
+
raw: freezeMap(mapping)
|
|
12241
|
+
});
|
|
12242
|
+
}
|
|
12243
|
+
function decodeIndex(value, index) {
|
|
12244
|
+
const mapping = requiredMap2(value, `FLOW.QUERY.INDEXES index ${index}`);
|
|
12245
|
+
return Object.freeze({
|
|
12246
|
+
id: requiredText2(mapping, "id", "FLOW.QUERY.INDEXES index"),
|
|
12247
|
+
version: positiveBoundedInteger(
|
|
12248
|
+
field(mapping, "version"),
|
|
12249
|
+
MAX_UNSIGNED_64,
|
|
12250
|
+
"FLOW.QUERY.INDEXES index version"
|
|
12251
|
+
),
|
|
12252
|
+
buildId: requiredText2(mapping, "build_id", "FLOW.QUERY.INDEXES index"),
|
|
12253
|
+
state: requiredText2(mapping, "state", "FLOW.QUERY.INDEXES index"),
|
|
12254
|
+
queryable: requiredBoolean(mapping, "queryable", "FLOW.QUERY.INDEXES index"),
|
|
12255
|
+
coveringFields: decodeCoveringFields(mapping),
|
|
12256
|
+
format: decodeIndexFormat(mapping),
|
|
12257
|
+
raw: freezeMap(mapping)
|
|
12258
|
+
});
|
|
12259
|
+
}
|
|
12260
|
+
function decodeCoveringFields(mapping) {
|
|
12261
|
+
const raw = field(mapping, "covering_fields");
|
|
12262
|
+
if (!Array.isArray(raw) || raw.length > 32) {
|
|
12263
|
+
throw decodeError(
|
|
12264
|
+
"FLOW.QUERY.INDEXES index covering_fields must contain at most 32 entries",
|
|
12265
|
+
raw
|
|
12266
|
+
);
|
|
12267
|
+
}
|
|
12268
|
+
const fields = new Array(raw.length);
|
|
12269
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12270
|
+
for (let index = 0; index < raw.length; index += 1) {
|
|
12271
|
+
if (!Object.hasOwn(raw, index)) {
|
|
12272
|
+
throw decodeError("FLOW.QUERY.INDEXES index covering_fields must be dense", raw);
|
|
12273
|
+
}
|
|
12274
|
+
const value = boundedText(
|
|
12275
|
+
raw[index],
|
|
12276
|
+
`FLOW.QUERY.INDEXES index covering_fields entry ${index}`,
|
|
12277
|
+
512
|
|
12278
|
+
);
|
|
12279
|
+
if (seen.has(value)) {
|
|
12280
|
+
throw decodeError("FLOW.QUERY.INDEXES index covering_fields contains duplicates", raw);
|
|
12281
|
+
}
|
|
12282
|
+
seen.add(value);
|
|
12283
|
+
fields[index] = value;
|
|
12284
|
+
}
|
|
12285
|
+
return Object.freeze(fields);
|
|
12286
|
+
}
|
|
12287
|
+
function decodeIndexFormat(mapping) {
|
|
12288
|
+
const raw = requiredMap2(field(mapping, "format"), "FLOW.QUERY.INDEXES index format");
|
|
12289
|
+
if (!hasKey(raw, "counter")) {
|
|
12290
|
+
throw decodeError("FLOW.QUERY.INDEXES index format counter is missing", raw);
|
|
12291
|
+
}
|
|
12292
|
+
const counterValue = field(raw, "counter");
|
|
12293
|
+
const counter = counterValue === null ? void 0 : boundedText(counterValue, "FLOW.QUERY.INDEXES index format counter", 128);
|
|
12294
|
+
return Object.freeze({
|
|
12295
|
+
queryRow: requiredBoundedText2(raw, "query_row", "FLOW.QUERY.INDEXES index format", 128),
|
|
12296
|
+
key: requiredBoundedText2(raw, "key", "FLOW.QUERY.INDEXES index format", 128),
|
|
12297
|
+
entry: requiredBoundedText2(raw, "entry", "FLOW.QUERY.INDEXES index format", 128),
|
|
12298
|
+
reverse: requiredBoundedText2(raw, "reverse", "FLOW.QUERY.INDEXES index format", 128),
|
|
12299
|
+
counter,
|
|
12300
|
+
raw: freezeMap(raw)
|
|
12301
|
+
});
|
|
12302
|
+
}
|
|
12303
|
+
function decodeQuality(value) {
|
|
12304
|
+
const mapping = requiredMap2(value, "FLOW.QUERY quality");
|
|
12305
|
+
return Object.freeze({
|
|
12306
|
+
exactness: requiredBoundedText2(mapping, "exactness", "FLOW.QUERY quality", 64),
|
|
12307
|
+
freshness: requiredBoundedText2(mapping, "freshness", "FLOW.QUERY quality", 64),
|
|
12308
|
+
coverage: requiredBoundedText2(mapping, "coverage", "FLOW.QUERY quality", 64),
|
|
12309
|
+
pagination: requiredBoundedText2(mapping, "pagination", "FLOW.QUERY quality", 64)
|
|
12310
|
+
});
|
|
12311
|
+
}
|
|
12312
|
+
function decodeUsage(value) {
|
|
12313
|
+
const mapping = requiredMap2(value, "FLOW.QUERY usage");
|
|
12314
|
+
const usage = /* @__PURE__ */ Object.create(null);
|
|
12315
|
+
for (const [wireName, property] of USAGE_FIELDS2) {
|
|
12316
|
+
usage[property] = nonNegativeInteger(
|
|
12317
|
+
field(mapping, wireName),
|
|
12318
|
+
`FLOW.QUERY usage ${wireName}`
|
|
12319
|
+
);
|
|
12320
|
+
}
|
|
12321
|
+
return Object.freeze(usage);
|
|
12322
|
+
}
|
|
12323
|
+
function decodePage(value) {
|
|
12324
|
+
const mapping = requiredMap2(value, "FLOW.QUERY page");
|
|
12325
|
+
const hasMore = requiredBoolean(mapping, "has_more", "FLOW.QUERY page");
|
|
12326
|
+
const cursor = optionalText2(mapping, "cursor", "FLOW.QUERY page");
|
|
12327
|
+
if (cursor != null && (!cursor.startsWith("fqc1_") || Buffer45.byteLength(cursor) > 4096)) {
|
|
12328
|
+
throw decodeError("FLOW.QUERY page cursor is invalid", value);
|
|
12329
|
+
}
|
|
12330
|
+
if (hasMore !== (cursor != null)) {
|
|
12331
|
+
throw decodeError("FLOW.QUERY page has_more and cursor are inconsistent", value);
|
|
12332
|
+
}
|
|
12333
|
+
return Object.freeze({ hasMore, ...cursor == null ? {} : { cursor } });
|
|
12334
|
+
}
|
|
12335
|
+
function decodePosition(value) {
|
|
12336
|
+
if (value == null) return void 0;
|
|
12337
|
+
const mapping = requiredMap2(value, "FLOW.QUERY diagnostic position");
|
|
12338
|
+
return Object.freeze({
|
|
12339
|
+
byte: positiveInteger(field(mapping, "byte"), "FLOW.QUERY diagnostic position byte"),
|
|
12340
|
+
line: positiveInteger(field(mapping, "line"), "FLOW.QUERY diagnostic position line"),
|
|
12341
|
+
column: positiveInteger(
|
|
12342
|
+
field(mapping, "column"),
|
|
12343
|
+
"FLOW.QUERY diagnostic position column"
|
|
12344
|
+
)
|
|
12345
|
+
});
|
|
12346
|
+
}
|
|
12347
|
+
|
|
12348
|
+
// src/client-core.ts
|
|
12349
|
+
import "buffer";
|
|
12350
|
+
|
|
12351
|
+
// src/client-core-helpers.ts
|
|
12352
|
+
import { Buffer as Buffer46 } from "buffer";
|
|
12353
|
+
function bgsaveResponse(response) {
|
|
12354
|
+
if ((typeof response === "string" || Buffer46.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
|
|
12355
|
+
return true;
|
|
12356
|
+
}
|
|
12357
|
+
return okResponse(response);
|
|
12358
|
+
}
|
|
12359
|
+
function clientNameResponse(response) {
|
|
12360
|
+
return response == null ? null : textResponse(response, "CLIENT GETNAME");
|
|
12361
|
+
}
|
|
12362
|
+
function fetchOrComputeCompletionToken(options) {
|
|
12363
|
+
if (options == null || !Object.hasOwn(options, "computeToken") || options.computeToken === void 0) {
|
|
12364
|
+
throw new TypeError(
|
|
12365
|
+
"fetch-or-compute completion requires computeToken"
|
|
12366
|
+
);
|
|
12367
|
+
}
|
|
12368
|
+
if (!Buffer46.isBuffer(options.computeToken)) {
|
|
12369
|
+
throw new TypeError("fetch-or-compute computeToken must be a Buffer");
|
|
12370
|
+
}
|
|
12371
|
+
return options.computeToken;
|
|
12372
|
+
}
|
|
12373
|
+
function concatCommandArgs(prefix, suffix) {
|
|
12374
|
+
const args = new Array(prefix.length + suffix.length);
|
|
12375
|
+
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
12376
|
+
for (let index = 0; index < suffix.length; index += 1) {
|
|
12377
|
+
args[prefix.length + index] = suffix[index];
|
|
12378
|
+
}
|
|
12379
|
+
return args;
|
|
12380
|
+
}
|
|
12381
|
+
function unsupportedClientTracking() {
|
|
12382
|
+
throw new InvalidCommandError(
|
|
12383
|
+
"CLIENT TRACKING is not supported by the FerricStore native protocol; use native event subscriptions"
|
|
12384
|
+
);
|
|
12385
|
+
}
|
|
12386
|
+
function unsupportedClientCaching() {
|
|
12387
|
+
throw new InvalidCommandError("CLIENT CACHING is not supported by the FerricStore native protocol");
|
|
12388
|
+
}
|
|
12389
|
+
|
|
12390
|
+
// src/client-base.ts
|
|
12391
|
+
import "buffer";
|
|
12392
|
+
|
|
12393
|
+
// src/client-executor.ts
|
|
12394
|
+
import "buffer";
|
|
12395
|
+
var ErrorMappingExecutor = class {
|
|
12396
|
+
constructor(executor) {
|
|
12397
|
+
this.executor = executor;
|
|
12398
|
+
}
|
|
12399
|
+
executor;
|
|
12400
|
+
async executeCommand(...args) {
|
|
12401
|
+
return await this.executeCommandArgs(args);
|
|
12402
|
+
}
|
|
12403
|
+
async executeCommandArgs(args) {
|
|
12404
|
+
try {
|
|
12405
|
+
return await executeCommandArgs(this.executor, args);
|
|
12406
|
+
} catch (error) {
|
|
12407
|
+
throwMapped(error);
|
|
12408
|
+
}
|
|
12409
|
+
}
|
|
12410
|
+
async executePipeline(commands, options) {
|
|
10924
12411
|
let results;
|
|
10925
12412
|
try {
|
|
10926
12413
|
if (this.executor.executePipeline != null) {
|
|
@@ -11238,14 +12725,14 @@ var FerricStoreAdministrationClient = class extends FerricStoreClientBase {
|
|
|
11238
12725
|
};
|
|
11239
12726
|
|
|
11240
12727
|
// src/store-utilities.ts
|
|
11241
|
-
import { Buffer as
|
|
12728
|
+
import { Buffer as Buffer49 } from "buffer";
|
|
11242
12729
|
function encode(codec, value) {
|
|
11243
12730
|
return codec.encode(value);
|
|
11244
12731
|
}
|
|
11245
12732
|
function decode(codec, value) {
|
|
11246
12733
|
if (value == null) return null;
|
|
11247
|
-
if (
|
|
11248
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
12734
|
+
if (Buffer49.isBuffer(value)) return codec.decode(value);
|
|
12735
|
+
if (value instanceof Uint8Array) return codec.decode(Buffer49.from(value));
|
|
11249
12736
|
return value;
|
|
11250
12737
|
}
|
|
11251
12738
|
function number(value) {
|
|
@@ -11835,15 +13322,15 @@ function compressionOptions(options) {
|
|
|
11835
13322
|
// src/store-decoders.ts
|
|
11836
13323
|
function decodeHashRecord(codec, value) {
|
|
11837
13324
|
const result = {};
|
|
11838
|
-
for (const [
|
|
11839
|
-
setOwnValue(result, textToken(
|
|
13325
|
+
for (const [field3, item] of hashPairs(value)) {
|
|
13326
|
+
setOwnValue(result, textToken(field3), decode(codec, item));
|
|
11840
13327
|
}
|
|
11841
13328
|
return result;
|
|
11842
13329
|
}
|
|
11843
13330
|
function decodeHashFlatPairs(codec, value) {
|
|
11844
13331
|
const result = [];
|
|
11845
|
-
for (const [
|
|
11846
|
-
result.push(textToken(
|
|
13332
|
+
for (const [field3, item] of hashPairs(value)) {
|
|
13333
|
+
result.push(textToken(field3), decode(codec, item));
|
|
11847
13334
|
}
|
|
11848
13335
|
return result;
|
|
11849
13336
|
}
|
|
@@ -11963,7 +13450,7 @@ function requiredPair(value, message) {
|
|
|
11963
13450
|
}
|
|
11964
13451
|
function decodeStreamFieldValues(codec, value) {
|
|
11965
13452
|
const result = [];
|
|
11966
|
-
for (const [
|
|
13453
|
+
for (const [field3, item] of hashPairs(value)) result.push(textToken(field3), decode(codec, item));
|
|
11967
13454
|
return result;
|
|
11968
13455
|
}
|
|
11969
13456
|
var geoSearchMetadataTokens = /* @__PURE__ */ new Set(["WITHCOORD", "WITHDIST", "WITHHASH"]);
|
|
@@ -12777,8 +14264,8 @@ var HashStore = class {
|
|
|
12777
14264
|
async hset(key, entries) {
|
|
12778
14265
|
return number(await commandArgs(this.client, keyValueArgs(["HSET", key], this.client.codec, entries)));
|
|
12779
14266
|
}
|
|
12780
|
-
async hget(key,
|
|
12781
|
-
return decode(this.client.codec, await this.client.command("HGET", key,
|
|
14267
|
+
async hget(key, field3) {
|
|
14268
|
+
return decode(this.client.codec, await this.client.command("HGET", key, field3));
|
|
12782
14269
|
}
|
|
12783
14270
|
async hdel(key, ...fieldsOrArray) {
|
|
12784
14271
|
const fields = requireNonEmpty(arrayOrRest(fieldsOrArray), "HDEL", "field");
|
|
@@ -12797,8 +14284,8 @@ var HashStore = class {
|
|
|
12797
14284
|
async hgetall(key) {
|
|
12798
14285
|
return decodeHashRecord(this.client.codec, await this.client.command("HGETALL", key));
|
|
12799
14286
|
}
|
|
12800
|
-
async hexists(key,
|
|
12801
|
-
return binaryBooleanResponse(await this.client.command("HEXISTS", key,
|
|
14287
|
+
async hexists(key, field3) {
|
|
14288
|
+
return binaryBooleanResponse(await this.client.command("HEXISTS", key, field3));
|
|
12802
14289
|
}
|
|
12803
14290
|
async hkeys(key) {
|
|
12804
14291
|
return mapArray(await this.client.command("HKEYS", key), "HKEYS", textToken);
|
|
@@ -12813,17 +14300,17 @@ var HashStore = class {
|
|
|
12813
14300
|
async hlen(key) {
|
|
12814
14301
|
return number(await this.client.command("HLEN", key));
|
|
12815
14302
|
}
|
|
12816
|
-
async hincrby(key,
|
|
12817
|
-
return integerReply(await this.client.command("HINCRBY", key,
|
|
14303
|
+
async hincrby(key, field3, increment) {
|
|
14304
|
+
return integerReply(await this.client.command("HINCRBY", key, field3, increment));
|
|
12818
14305
|
}
|
|
12819
|
-
async hincrbyfloat(key,
|
|
12820
|
-
return string(await this.client.command("HINCRBYFLOAT", key,
|
|
14306
|
+
async hincrbyfloat(key, field3, increment) {
|
|
14307
|
+
return string(await this.client.command("HINCRBYFLOAT", key, field3, increment));
|
|
12821
14308
|
}
|
|
12822
|
-
async hsetnx(key,
|
|
12823
|
-
return binaryBooleanResponse(await this.client.command("HSETNX", key,
|
|
14309
|
+
async hsetnx(key, field3, value) {
|
|
14310
|
+
return binaryBooleanResponse(await this.client.command("HSETNX", key, field3, encode(this.client.codec, value)));
|
|
12824
14311
|
}
|
|
12825
|
-
async hstrlen(key,
|
|
12826
|
-
return number(await this.client.command("HSTRLEN", key,
|
|
14312
|
+
async hstrlen(key, field3) {
|
|
14313
|
+
return number(await this.client.command("HSTRLEN", key, field3));
|
|
12827
14314
|
}
|
|
12828
14315
|
async hrandfield(key, count, withValues = false) {
|
|
12829
14316
|
if (withValues && count == null) {
|
|
@@ -13459,6 +14946,100 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
|
|
|
13459
14946
|
}
|
|
13460
14947
|
};
|
|
13461
14948
|
|
|
14949
|
+
// src/client-flow-query.ts
|
|
14950
|
+
var FerricStoreFlowQueryClient = class extends FerricStoreManagementClient {
|
|
14951
|
+
async query(query, params = {}) {
|
|
14952
|
+
if (hasFlowExplainPrefix(query)) {
|
|
14953
|
+
throw new TypeError("query does not accept EXPLAIN; use explain or explainAnalyze");
|
|
14954
|
+
}
|
|
14955
|
+
return decodeFlowQueryResult(await this.executeFlowQuery(query, params));
|
|
14956
|
+
}
|
|
14957
|
+
async explain(query, params = {}) {
|
|
14958
|
+
return await this.executeExplain("EXPLAIN ", query, params);
|
|
14959
|
+
}
|
|
14960
|
+
async explainAnalyze(query, params = {}) {
|
|
14961
|
+
return await this.executeExplain("EXPLAIN ANALYZE ", query, params);
|
|
14962
|
+
}
|
|
14963
|
+
async queryIndexes(indexId) {
|
|
14964
|
+
const args = ["FLOW.QUERY.INDEXES"];
|
|
14965
|
+
if (indexId != null) {
|
|
14966
|
+
validateFlowQueryIndexId(indexId);
|
|
14967
|
+
args.push(indexId);
|
|
14968
|
+
}
|
|
14969
|
+
try {
|
|
14970
|
+
return decodeFlowQueryIndexStatus(await this.commandArgs(args));
|
|
14971
|
+
} catch (error) {
|
|
14972
|
+
this.throwFlowQueryError(error);
|
|
14973
|
+
}
|
|
14974
|
+
}
|
|
14975
|
+
async list(type, options) {
|
|
14976
|
+
return await this.executeFlowRecordQuery(buildFlowListQuery(type, options));
|
|
14977
|
+
}
|
|
14978
|
+
async search(type, options) {
|
|
14979
|
+
return await this.executeFlowRecordQuery(buildFlowSearchQuery(type, options));
|
|
14980
|
+
}
|
|
14981
|
+
async terminals(type, options) {
|
|
14982
|
+
return await this.executeFlowRecordQuery(buildFlowTerminalQuery(type, options));
|
|
14983
|
+
}
|
|
14984
|
+
async failures(type, options) {
|
|
14985
|
+
return await this.executeFlowRecordQuery(buildFlowFailureQuery(type, options));
|
|
14986
|
+
}
|
|
14987
|
+
async byParent(parentFlowId, options) {
|
|
14988
|
+
return await this.executeFlowRecordQuery(
|
|
14989
|
+
buildFlowLineageQuery("parent_flow_id", parentFlowId, options)
|
|
14990
|
+
);
|
|
14991
|
+
}
|
|
14992
|
+
async byRoot(rootFlowId, options) {
|
|
14993
|
+
return await this.executeFlowRecordQuery(
|
|
14994
|
+
buildFlowLineageQuery("root_flow_id", rootFlowId, options)
|
|
14995
|
+
);
|
|
14996
|
+
}
|
|
14997
|
+
async byCorrelation(correlationId, options) {
|
|
14998
|
+
return await this.executeFlowRecordQuery(
|
|
14999
|
+
buildFlowLineageQuery("correlation_id", correlationId, options)
|
|
15000
|
+
);
|
|
15001
|
+
}
|
|
15002
|
+
async stuck(type, options) {
|
|
15003
|
+
return await this.executeFlowRecordQuery(buildFlowStuckQuery(type, options));
|
|
15004
|
+
}
|
|
15005
|
+
records(values) {
|
|
15006
|
+
const records = new Array(values.length);
|
|
15007
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
15008
|
+
if (!Object.hasOwn(values, index)) {
|
|
15009
|
+
throw new TypeError(`Flow record response item ${index} is missing`);
|
|
15010
|
+
}
|
|
15011
|
+
records[index] = flowRecordFromResp(values[index], this.codec);
|
|
15012
|
+
}
|
|
15013
|
+
return records;
|
|
15014
|
+
}
|
|
15015
|
+
async executeFlowQuery(query, params) {
|
|
15016
|
+
const args = flowQueryArgs(query, params);
|
|
15017
|
+
try {
|
|
15018
|
+
return await this.commandArgs(args);
|
|
15019
|
+
} catch (error) {
|
|
15020
|
+
this.throwFlowQueryError(error);
|
|
15021
|
+
}
|
|
15022
|
+
}
|
|
15023
|
+
async executeFlowRecordQuery(request) {
|
|
15024
|
+
const response = await this.executeFlowQuery(request.query, request.params);
|
|
15025
|
+
return decodeFlowQueryRecords(response, (value) => flowRecordFromResp(value, this.codec));
|
|
15026
|
+
}
|
|
15027
|
+
async executeExplain(prefix, query, params) {
|
|
15028
|
+
validateFlowQueryText(query);
|
|
15029
|
+
if (hasFlowExplainPrefix(query)) {
|
|
15030
|
+
throw new TypeError("query already contains an EXPLAIN prefix");
|
|
15031
|
+
}
|
|
15032
|
+
return decodeFlowExplainResult(await this.executeFlowQuery(prefix + query.trim(), params));
|
|
15033
|
+
}
|
|
15034
|
+
throwFlowQueryError(error) {
|
|
15035
|
+
if (error instanceof FerricStoreError) {
|
|
15036
|
+
const diagnostic = tryDecodeFlowQueryError(error.raw, error);
|
|
15037
|
+
if (diagnostic != null) throw diagnostic;
|
|
15038
|
+
}
|
|
15039
|
+
throw error;
|
|
15040
|
+
}
|
|
15041
|
+
};
|
|
15042
|
+
|
|
13462
15043
|
// src/producer-backpressure.ts
|
|
13463
15044
|
async function executeProducerWriteWithBackpressure(execute, policy, signal) {
|
|
13464
15045
|
for (let attempt = 0; ; attempt += 1) {
|
|
@@ -13481,7 +15062,7 @@ function throwIfClosed(signal) {
|
|
|
13481
15062
|
}
|
|
13482
15063
|
|
|
13483
15064
|
// src/flow-policy.ts
|
|
13484
|
-
import { Buffer as
|
|
15065
|
+
import { Buffer as Buffer51 } from "buffer";
|
|
13485
15066
|
var MAX_FLOW_POLICY_GENERATION = Number.MAX_SAFE_INTEGER;
|
|
13486
15067
|
function assertFlowPolicyGeneration(value) {
|
|
13487
15068
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
@@ -13491,15 +15072,15 @@ function assertFlowPolicyGeneration(value) {
|
|
|
13491
15072
|
function flowPolicySnapshotFromResp(value) {
|
|
13492
15073
|
const policy = requiredRecord(value, "FLOW policy snapshot");
|
|
13493
15074
|
const maxActiveMs = optionalPositiveInteger(field(policy, "max_active_ms"), "max_active_ms");
|
|
13494
|
-
const state =
|
|
15075
|
+
const state = optionalText3(field(policy, "state"), "state");
|
|
13495
15076
|
const mode = optionalMode(field(policy, "mode"), "mode");
|
|
13496
15077
|
const version = optionalVersion(field(policy, "version"));
|
|
13497
|
-
const indexedStateMeta =
|
|
15078
|
+
const indexedStateMeta = optionalText3(field(policy, "indexed_state_meta"), "indexed_state_meta");
|
|
13498
15079
|
const governance = optionalRecord(field(policy, "governance"), "governance");
|
|
13499
15080
|
const states = optionalStates(field(policy, "states"));
|
|
13500
15081
|
return {
|
|
13501
|
-
type:
|
|
13502
|
-
generation:
|
|
15082
|
+
type: requiredText3(field(policy, "type"), "type"),
|
|
15083
|
+
generation: nonNegativeInteger2(field(policy, "generation"), "generation"),
|
|
13503
15084
|
...state == null ? {} : { state },
|
|
13504
15085
|
...version == null ? {} : { version },
|
|
13505
15086
|
...mode == null ? {} : { mode },
|
|
@@ -13517,21 +15098,21 @@ function retrySnapshot(value, context) {
|
|
|
13517
15098
|
const retry2 = requiredRecord(value, `FLOW policy ${context}`);
|
|
13518
15099
|
const backoff = requiredRecord(field(retry2, "backoff"), `FLOW policy ${context}.backoff`);
|
|
13519
15100
|
return {
|
|
13520
|
-
maxRetries:
|
|
15101
|
+
maxRetries: nonNegativeInteger2(field(retry2, "max_retries"), `${context}.max_retries`),
|
|
13521
15102
|
backoff: {
|
|
13522
15103
|
kind: backoffKind(field(backoff, "kind"), `${context}.backoff.kind`),
|
|
13523
|
-
baseMs:
|
|
13524
|
-
maxMs:
|
|
13525
|
-
jitterPct:
|
|
15104
|
+
baseMs: nonNegativeInteger2(field(backoff, "base_ms"), `${context}.backoff.base_ms`),
|
|
15105
|
+
maxMs: nonNegativeInteger2(field(backoff, "max_ms"), `${context}.backoff.max_ms`),
|
|
15106
|
+
jitterPct: nonNegativeInteger2(field(backoff, "jitter_pct"), `${context}.backoff.jitter_pct`)
|
|
13526
15107
|
},
|
|
13527
|
-
exhaustedTo:
|
|
15108
|
+
exhaustedTo: requiredText3(field(retry2, "exhausted_to"), `${context}.exhausted_to`)
|
|
13528
15109
|
};
|
|
13529
15110
|
}
|
|
13530
15111
|
function retentionSnapshot(value, context) {
|
|
13531
15112
|
const retention = requiredRecord(value, `FLOW policy ${context}`);
|
|
13532
15113
|
return {
|
|
13533
|
-
ttlMs:
|
|
13534
|
-
historyMaxEvents:
|
|
15114
|
+
ttlMs: nonNegativeInteger2(field(retention, "ttl_ms"), `${context}.ttl_ms`),
|
|
15115
|
+
historyMaxEvents: nonNegativeInteger2(
|
|
13535
15116
|
field(retention, "history_max_events"),
|
|
13536
15117
|
`${context}.history_max_events`
|
|
13537
15118
|
)
|
|
@@ -13567,11 +15148,11 @@ function requiredRecord(value, context) {
|
|
|
13567
15148
|
if (value instanceof Map) {
|
|
13568
15149
|
const result = {};
|
|
13569
15150
|
for (const [key, item] of value.entries()) {
|
|
13570
|
-
setOwnValue(result,
|
|
15151
|
+
setOwnValue(result, requiredText3(key, `${context} key`), item);
|
|
13571
15152
|
}
|
|
13572
15153
|
return result;
|
|
13573
15154
|
}
|
|
13574
|
-
if (typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
15155
|
+
if (typeof value === "object" && value != null && !Array.isArray(value) && !Buffer51.isBuffer(value) && !(value instanceof Uint8Array)) return value;
|
|
13575
15156
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
13576
15157
|
}
|
|
13577
15158
|
function optionalRecord(value, context) {
|
|
@@ -13586,21 +15167,21 @@ function stringArray(value, context) {
|
|
|
13586
15167
|
if (!Object.hasOwn(value, index)) {
|
|
13587
15168
|
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13588
15169
|
}
|
|
13589
|
-
result[index] =
|
|
15170
|
+
result[index] = requiredText3(value[index], `${context}[${index}]`);
|
|
13590
15171
|
}
|
|
13591
15172
|
return result;
|
|
13592
15173
|
}
|
|
13593
|
-
function
|
|
15174
|
+
function requiredText3(value, context) {
|
|
13594
15175
|
if (typeof value === "string") return value;
|
|
13595
|
-
if (
|
|
13596
|
-
return
|
|
15176
|
+
if (Buffer51.isBuffer(value) || value instanceof Uint8Array) {
|
|
15177
|
+
return Buffer51.from(value).toString("utf8");
|
|
13597
15178
|
}
|
|
13598
15179
|
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13599
15180
|
}
|
|
13600
|
-
function
|
|
13601
|
-
return value == null ? void 0 :
|
|
15181
|
+
function optionalText3(value, context) {
|
|
15182
|
+
return value == null ? void 0 : requiredText3(value, context);
|
|
13602
15183
|
}
|
|
13603
|
-
function
|
|
15184
|
+
function nonNegativeInteger2(value, context) {
|
|
13604
15185
|
let parsed;
|
|
13605
15186
|
try {
|
|
13606
15187
|
parsed = integer(value);
|
|
@@ -13612,26 +15193,26 @@ function nonNegativeInteger(value, context) {
|
|
|
13612
15193
|
}
|
|
13613
15194
|
function optionalPositiveInteger(value, context) {
|
|
13614
15195
|
if (value == null) return void 0;
|
|
13615
|
-
const parsed =
|
|
15196
|
+
const parsed = nonNegativeInteger2(value, context);
|
|
13616
15197
|
if (parsed === 0) throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13617
15198
|
return parsed;
|
|
13618
15199
|
}
|
|
13619
15200
|
function optionalVersion(value) {
|
|
13620
15201
|
if (value == null) return void 0;
|
|
13621
15202
|
if (typeof value === "number" || typeof value === "bigint") {
|
|
13622
|
-
return
|
|
15203
|
+
return nonNegativeInteger2(value, "version");
|
|
13623
15204
|
}
|
|
13624
|
-
return
|
|
15205
|
+
return requiredText3(value, "version");
|
|
13625
15206
|
}
|
|
13626
15207
|
function backoffKind(value, context) {
|
|
13627
|
-
const kind =
|
|
15208
|
+
const kind = requiredText3(value, context).toLowerCase();
|
|
13628
15209
|
if (kind === "none" || kind === "fixed" || kind === "linear" || kind === "exponential") {
|
|
13629
15210
|
return kind;
|
|
13630
15211
|
}
|
|
13631
15212
|
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13632
15213
|
}
|
|
13633
15214
|
function requiredMode(value, context) {
|
|
13634
|
-
const mode =
|
|
15215
|
+
const mode = requiredText3(value, context).toLowerCase();
|
|
13635
15216
|
if (mode === "fifo" || mode === "parallel") return mode;
|
|
13636
15217
|
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13637
15218
|
}
|
|
@@ -13640,7 +15221,7 @@ function optionalMode(value, context) {
|
|
|
13640
15221
|
}
|
|
13641
15222
|
|
|
13642
15223
|
// src/client-flow-support.ts
|
|
13643
|
-
var FerricStoreFlowSupportClient = class extends
|
|
15224
|
+
var FerricStoreFlowSupportClient = class extends FerricStoreFlowQueryClient {
|
|
13644
15225
|
async rewind(id, options = {}) {
|
|
13645
15226
|
const partitionKey = options.partitionKey;
|
|
13646
15227
|
const returnRecord = options.returnRecord === true;
|
|
@@ -13666,43 +15247,9 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13666
15247
|
}
|
|
13667
15248
|
return flowRecordFromResp(response, this.codec);
|
|
13668
15249
|
}
|
|
13669
|
-
async list(type, options = {}) {
|
|
13670
|
-
return await this.indexQuery("FLOW.LIST", type, options);
|
|
13671
|
-
}
|
|
13672
|
-
async search(type, options = {}) {
|
|
13673
|
-
const args = ["FLOW.SEARCH", type];
|
|
13674
|
-
appendReadOptions(args, options);
|
|
13675
|
-
appendAttributes(args, options.attributes);
|
|
13676
|
-
appendSearchStateMeta(args, options.state, options.stateMeta);
|
|
13677
|
-
const response = await this.commandArgs(args);
|
|
13678
|
-
return this.records(requiredArrayResponse(response, "FLOW.SEARCH"));
|
|
13679
|
-
}
|
|
13680
|
-
async terminals(type, options = {}) {
|
|
13681
|
-
return await this.indexQuery("FLOW.TERMINALS", type, options);
|
|
13682
|
-
}
|
|
13683
|
-
async failures(type, options = {}) {
|
|
13684
|
-
return await this.indexQuery("FLOW.FAILURES", type, options);
|
|
13685
|
-
}
|
|
13686
|
-
async byParent(parentFlowId, options = {}) {
|
|
13687
|
-
return await this.indexQuery("FLOW.BY_PARENT", parentFlowId, options);
|
|
13688
|
-
}
|
|
13689
|
-
async byRoot(rootFlowId, options = {}) {
|
|
13690
|
-
return await this.indexQuery("FLOW.BY_ROOT", rootFlowId, options);
|
|
13691
|
-
}
|
|
13692
|
-
async byCorrelation(correlationId, options = {}) {
|
|
13693
|
-
return await this.indexQuery("FLOW.BY_CORRELATION", correlationId, options);
|
|
13694
|
-
}
|
|
13695
15250
|
async info(type) {
|
|
13696
15251
|
return parseKvResponse(await this.command("FLOW.INFO", type));
|
|
13697
15252
|
}
|
|
13698
|
-
async stuck(type, options = {}) {
|
|
13699
|
-
const args = ["FLOW.STUCK", type];
|
|
13700
|
-
append(args, "PARTITION", options.partitionKey);
|
|
13701
|
-
append(args, "COUNT", options.count);
|
|
13702
|
-
append(args, "OLDER_THAN", options.olderThanMs);
|
|
13703
|
-
append(args, "NOW", options.nowMs);
|
|
13704
|
-
return this.records(arrayResponse(await this.commandArgs(args)));
|
|
13705
|
-
}
|
|
13706
15253
|
async history(id, options = {}) {
|
|
13707
15254
|
const args = ["FLOW.HISTORY", id];
|
|
13708
15255
|
append(args, "PARTITION", options.partitionKey);
|
|
@@ -13832,16 +15379,6 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13832
15379
|
}
|
|
13833
15380
|
return record;
|
|
13834
15381
|
}
|
|
13835
|
-
records(values) {
|
|
13836
|
-
const records = new Array(values.length);
|
|
13837
|
-
for (let index = 0; index < values.length; index += 1) {
|
|
13838
|
-
if (!Object.hasOwn(values, index)) {
|
|
13839
|
-
throw new TypeError(`Flow record response item ${index} is missing`);
|
|
13840
|
-
}
|
|
13841
|
-
records[index] = flowRecordFromResp(values[index], this.codec);
|
|
13842
|
-
}
|
|
13843
|
-
return records;
|
|
13844
|
-
}
|
|
13845
15382
|
recordsOrResponse(value) {
|
|
13846
15383
|
if (Array.isArray(value) && value.every(isRecordLike)) {
|
|
13847
15384
|
return this.records(value);
|
|
@@ -13871,12 +15408,6 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13871
15408
|
}
|
|
13872
15409
|
return results;
|
|
13873
15410
|
}
|
|
13874
|
-
async indexQuery(command, key, options) {
|
|
13875
|
-
const args = [command, key];
|
|
13876
|
-
appendReadOptions(args, options);
|
|
13877
|
-
const response = await this.commandArgs(args);
|
|
13878
|
-
return this.records(requiredArrayResponse(response, command));
|
|
13879
|
-
}
|
|
13880
15411
|
appendPartitionOptions(args, options) {
|
|
13881
15412
|
if (options.partitionKey != null && options.partitionKeys != null) {
|
|
13882
15413
|
throw new Error("partitionKey and partitionKeys are mutually exclusive");
|
|
@@ -13899,7 +15430,7 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13899
15430
|
};
|
|
13900
15431
|
|
|
13901
15432
|
// src/flow-many-snapshot.ts
|
|
13902
|
-
import { Buffer as
|
|
15433
|
+
import { Buffer as Buffer53 } from "buffer";
|
|
13903
15434
|
var encodedOptionFields = ["error", "payload", "reason", "result"];
|
|
13904
15435
|
function snapshotCreateItem(item, codec) {
|
|
13905
15436
|
const snapshot = {
|
|
@@ -13917,9 +15448,9 @@ function snapshotCreateItem(item, codec) {
|
|
|
13917
15448
|
function snapshotFlowManyOptions(options, codec) {
|
|
13918
15449
|
const snapshot = { ...options };
|
|
13919
15450
|
const mutable = snapshot;
|
|
13920
|
-
for (const
|
|
13921
|
-
const value = options[
|
|
13922
|
-
if (value != null) mutable[
|
|
15451
|
+
for (const field3 of encodedOptionFields) {
|
|
15452
|
+
const value = options[field3];
|
|
15453
|
+
if (value != null) mutable[field3] = snapshotFlowValue(codec, value);
|
|
13923
15454
|
}
|
|
13924
15455
|
if (options.attributes != null) mutable.attributes = snapshotCommandRecord(options.attributes);
|
|
13925
15456
|
if (options.attributesMerge != null) {
|
|
@@ -13939,7 +15470,7 @@ function snapshotFlowManyOptions(options, codec) {
|
|
|
13939
15470
|
}
|
|
13940
15471
|
function snapshotClaimedItem(item) {
|
|
13941
15472
|
const wire = item[CLAIMED_ITEM_WIRE];
|
|
13942
|
-
const leaseToken =
|
|
15473
|
+
const leaseToken = Buffer53.from(wire?.leaseToken ?? item.leaseToken);
|
|
13943
15474
|
const snapshot = {
|
|
13944
15475
|
...item,
|
|
13945
15476
|
fencingToken: wire?.fencingToken ?? item.fencingToken,
|
|
@@ -13956,15 +15487,15 @@ function snapshotClaimedItem(item) {
|
|
|
13956
15487
|
function snapshotFencedItem(item) {
|
|
13957
15488
|
return Object.freeze({
|
|
13958
15489
|
...item,
|
|
13959
|
-
...item.leaseToken == null ? {} : { leaseToken:
|
|
15490
|
+
...item.leaseToken == null ? {} : { leaseToken: Buffer53.from(item.leaseToken) }
|
|
13960
15491
|
});
|
|
13961
15492
|
}
|
|
13962
15493
|
function snapshotClaimedItemWire(wire, leaseToken) {
|
|
13963
15494
|
return Object.freeze({
|
|
13964
15495
|
fencingToken: wire.fencingToken,
|
|
13965
|
-
id:
|
|
15496
|
+
id: Buffer53.from(wire.id),
|
|
13966
15497
|
leaseToken,
|
|
13967
|
-
partitionKey: wire.partitionKey == null ? wire.partitionKey :
|
|
15498
|
+
partitionKey: wire.partitionKey == null ? wire.partitionKey : Buffer53.from(wire.partitionKey)
|
|
13968
15499
|
});
|
|
13969
15500
|
}
|
|
13970
15501
|
function snapshotArray(values) {
|
|
@@ -13975,7 +15506,7 @@ function snapshotArray(values) {
|
|
|
13975
15506
|
return Object.freeze(snapshot);
|
|
13976
15507
|
}
|
|
13977
15508
|
function snapshotStateMeta(stateMeta) {
|
|
13978
|
-
return snapshotRecord(stateMeta, (value) =>
|
|
15509
|
+
return snapshotRecord(stateMeta, (value) => Buffer53.isBuffer(value) ? Buffer53.from(value) : value);
|
|
13979
15510
|
}
|
|
13980
15511
|
function snapshotCommandRecord(values) {
|
|
13981
15512
|
const seen = /* @__PURE__ */ new WeakMap();
|
|
@@ -13993,7 +15524,7 @@ function snapshotRecord(values, capture) {
|
|
|
13993
15524
|
}
|
|
13994
15525
|
function snapshotCommandArgument(value, seen) {
|
|
13995
15526
|
if (typeof value !== "object" || value == null) return value;
|
|
13996
|
-
if (
|
|
15527
|
+
if (Buffer53.isBuffer(value) || value instanceof Uint8Array) return Buffer53.from(value);
|
|
13997
15528
|
const objectValue = value;
|
|
13998
15529
|
const existing = seen.get(objectValue);
|
|
13999
15530
|
if (existing != null) return existing;
|
|
@@ -14980,6 +16511,142 @@ function nativeOptionsForBootstrap(options, signal) {
|
|
|
14980
16511
|
};
|
|
14981
16512
|
}
|
|
14982
16513
|
|
|
16514
|
+
// src/flow-query-projection.ts
|
|
16515
|
+
import { Buffer as Buffer54 } from "buffer";
|
|
16516
|
+
var MAX_PROJECTION_FIELDS = 32;
|
|
16517
|
+
var MAX_DYNAMIC_NAME_BYTES = 64;
|
|
16518
|
+
var FIELD_BRAND = /* @__PURE__ */ Symbol("FerricStoreFlowProjectionField");
|
|
16519
|
+
function field2(source, selector) {
|
|
16520
|
+
return Object.freeze({ source, selector, [FIELD_BRAND]: true });
|
|
16521
|
+
}
|
|
16522
|
+
var run = Object.freeze({
|
|
16523
|
+
id: field2("runs", "run_id"),
|
|
16524
|
+
type: field2("runs", "type"),
|
|
16525
|
+
state: field2("runs", "state"),
|
|
16526
|
+
version: field2("runs", "version"),
|
|
16527
|
+
priority: field2("runs", "priority"),
|
|
16528
|
+
partitionKey: field2("runs", "partition_key"),
|
|
16529
|
+
createdAtMs: field2("runs", "created_at_ms"),
|
|
16530
|
+
updatedAtMs: field2("runs", "updated_at_ms"),
|
|
16531
|
+
nextRunAtMs: field2("runs", "next_run_at_ms"),
|
|
16532
|
+
leaseDeadlineMs: field2("runs", "lease_deadline_ms"),
|
|
16533
|
+
attempts: field2("runs", "attempts"),
|
|
16534
|
+
runState: field2("runs", "run_state"),
|
|
16535
|
+
maxActiveMs: field2("runs", "max_active_ms"),
|
|
16536
|
+
parentFlowId: field2("runs", "parent_flow_id"),
|
|
16537
|
+
rootFlowId: field2("runs", "root_flow_id"),
|
|
16538
|
+
correlationId: field2("runs", "correlation_id"),
|
|
16539
|
+
attributes: field2("runs", "attributes"),
|
|
16540
|
+
stateMetadata: field2("runs", "state_meta"),
|
|
16541
|
+
attribute(name) {
|
|
16542
|
+
return field2("runs", `attribute[${quoteName(name, false)}]`);
|
|
16543
|
+
},
|
|
16544
|
+
stateMeta(state, name) {
|
|
16545
|
+
return field2(
|
|
16546
|
+
"runs",
|
|
16547
|
+
`state_meta[${quoteName(state, true)}][${quoteName(name, false)}]`
|
|
16548
|
+
);
|
|
16549
|
+
}
|
|
16550
|
+
});
|
|
16551
|
+
var event = Object.freeze({
|
|
16552
|
+
id: field2("events", "event_id"),
|
|
16553
|
+
fields: field2("events", "fields"),
|
|
16554
|
+
field(name) {
|
|
16555
|
+
return field2("events", `fields[${quoteName(name, false)}]`);
|
|
16556
|
+
}
|
|
16557
|
+
});
|
|
16558
|
+
var FlowProjection = Object.freeze({ run, event });
|
|
16559
|
+
function projectFlowQuery(query, shape, ...fields) {
|
|
16560
|
+
validateFlowQueryText(query);
|
|
16561
|
+
if (shape !== "record" && shape !== "records") {
|
|
16562
|
+
throw new TypeError("Flow query projection shape must be record or records");
|
|
16563
|
+
}
|
|
16564
|
+
if (fields.length === 0 || fields.length > MAX_PROJECTION_FIELDS) {
|
|
16565
|
+
throw new TypeError(
|
|
16566
|
+
`Flow query projection must contain 1..${MAX_PROJECTION_FIELDS} fields`
|
|
16567
|
+
);
|
|
16568
|
+
}
|
|
16569
|
+
if (!fields.every((item) => item?.[FIELD_BRAND])) {
|
|
16570
|
+
throw new TypeError("Flow query projection accepts only FlowProjection fields");
|
|
16571
|
+
}
|
|
16572
|
+
const source = querySource(query);
|
|
16573
|
+
if (fields.some((item) => item.source !== source)) {
|
|
16574
|
+
throw new TypeError(`Flow query projection fields must belong to ${source}`);
|
|
16575
|
+
}
|
|
16576
|
+
const selectors = fields.map((item) => item.selector);
|
|
16577
|
+
if (new Set(selectors).size !== selectors.length) {
|
|
16578
|
+
throw new TypeError("Flow query projection contains a duplicate field");
|
|
16579
|
+
}
|
|
16580
|
+
if (containsReturnKeyword(query)) {
|
|
16581
|
+
throw new TypeError("Flow query already contains a RETURN clause");
|
|
16582
|
+
}
|
|
16583
|
+
const trimmed = query.trim();
|
|
16584
|
+
const base = trimmed.endsWith(";") ? trimmed.slice(0, -1).trimEnd() : trimmed;
|
|
16585
|
+
const result = `${base} RETURN ${shape.toUpperCase()} (${selectors.join(", ")})`;
|
|
16586
|
+
if (Buffer54.byteLength(result, "utf8") > FLOW_QUERY_MAX_BYTES) {
|
|
16587
|
+
throw new TypeError(`FLOW.QUERY query exceeds ${FLOW_QUERY_MAX_BYTES} bytes`);
|
|
16588
|
+
}
|
|
16589
|
+
return result;
|
|
16590
|
+
}
|
|
16591
|
+
function querySource(query) {
|
|
16592
|
+
const match = /^\s*FROM\s+(runs|events)\b/iu.exec(query);
|
|
16593
|
+
if (match?.[1] == null) {
|
|
16594
|
+
throw new TypeError("Projected Flow query must start with FROM runs or FROM events");
|
|
16595
|
+
}
|
|
16596
|
+
return match[1].toLowerCase();
|
|
16597
|
+
}
|
|
16598
|
+
function containsReturnKeyword(query) {
|
|
16599
|
+
let quoted = false;
|
|
16600
|
+
for (let index = 0; index < query.length; ) {
|
|
16601
|
+
const character = query.charAt(index);
|
|
16602
|
+
if (character === "'") {
|
|
16603
|
+
if (quoted && query[index + 1] === "'") {
|
|
16604
|
+
index += 2;
|
|
16605
|
+
continue;
|
|
16606
|
+
}
|
|
16607
|
+
quoted = !quoted;
|
|
16608
|
+
index += 1;
|
|
16609
|
+
continue;
|
|
16610
|
+
}
|
|
16611
|
+
if (!quoted && /[A-Za-z_]/u.test(character)) {
|
|
16612
|
+
let end = index + 1;
|
|
16613
|
+
while (end < query.length && /[A-Za-z0-9_]/u.test(query.charAt(end))) end += 1;
|
|
16614
|
+
if (query.slice(index, end).toUpperCase() === "RETURN") return true;
|
|
16615
|
+
index = end;
|
|
16616
|
+
continue;
|
|
16617
|
+
}
|
|
16618
|
+
index += 1;
|
|
16619
|
+
}
|
|
16620
|
+
return false;
|
|
16621
|
+
}
|
|
16622
|
+
function quoteName(value, allowPrivate) {
|
|
16623
|
+
if (typeof value !== "string") {
|
|
16624
|
+
throw new TypeError("Flow query projection metadata name must be text");
|
|
16625
|
+
}
|
|
16626
|
+
validateUnicodeScalarText2(value);
|
|
16627
|
+
const size = Buffer54.byteLength(value, "utf8");
|
|
16628
|
+
if (size === 0 || size > MAX_DYNAMIC_NAME_BYTES || !allowPrivate && value.startsWith("__")) {
|
|
16629
|
+
throw new TypeError(
|
|
16630
|
+
`Flow query projection metadata names must be 1..${MAX_DYNAMIC_NAME_BYTES} UTF-8 bytes`
|
|
16631
|
+
);
|
|
16632
|
+
}
|
|
16633
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
16634
|
+
}
|
|
16635
|
+
function validateUnicodeScalarText2(value) {
|
|
16636
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
16637
|
+
const code = value.charCodeAt(index);
|
|
16638
|
+
if (code >= 55296 && code <= 56319) {
|
|
16639
|
+
const low = value.charCodeAt(index + 1);
|
|
16640
|
+
if (!(low >= 56320 && low <= 57343)) {
|
|
16641
|
+
throw new TypeError("Flow query projection metadata name must be valid UTF-8");
|
|
16642
|
+
}
|
|
16643
|
+
index += 1;
|
|
16644
|
+
} else if (code >= 56320 && code <= 57343) {
|
|
16645
|
+
throw new TypeError("Flow query projection metadata name must be valid UTF-8");
|
|
16646
|
+
}
|
|
16647
|
+
}
|
|
16648
|
+
}
|
|
16649
|
+
|
|
14983
16650
|
// src/outcomes.ts
|
|
14984
16651
|
var OUTCOME_BRAND = /* @__PURE__ */ Symbol("ferricstore.outcome");
|
|
14985
16652
|
function transition(toState, options = {}) {
|
|
@@ -15059,7 +16726,7 @@ var LeaseRenewalGuard = class {
|
|
|
15059
16726
|
if (options.leaseRenewal === false) {
|
|
15060
16727
|
return;
|
|
15061
16728
|
}
|
|
15062
|
-
const intervalMs =
|
|
16729
|
+
const intervalMs = positiveInteger2(options.leaseRenewIntervalMs, Math.max(1, Math.trunc(leaseMs / 2)));
|
|
15063
16730
|
this.timer = setLongInterval(() => this.renew(), intervalMs);
|
|
15064
16731
|
this.timer.unref();
|
|
15065
16732
|
}
|
|
@@ -15131,7 +16798,7 @@ function snapshotLeasedJob(job) {
|
|
|
15131
16798
|
return snapshot;
|
|
15132
16799
|
}
|
|
15133
16800
|
function workerConcurrency(options) {
|
|
15134
|
-
return
|
|
16801
|
+
return positiveInteger2(options.concurrency ?? options.workers, 1);
|
|
15135
16802
|
}
|
|
15136
16803
|
function workerRefillStrategy(options) {
|
|
15137
16804
|
return options.refillStrategy === "wave" ? "wave" : "continuous";
|
|
@@ -15174,18 +16841,18 @@ function workerErrorPayload(error, options, codec) {
|
|
|
15174
16841
|
}
|
|
15175
16842
|
function workerBatchSize(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
|
|
15176
16843
|
return Math.min(
|
|
15177
|
-
|
|
15178
|
-
|
|
16844
|
+
positiveInteger2(options.batchSize, 10),
|
|
16845
|
+
positiveInteger2(flowManyBatchLimit, DEFAULT_FLOW_MANY_BATCH_LIMIT2)
|
|
15179
16846
|
);
|
|
15180
16847
|
}
|
|
15181
16848
|
function workerClaimLimit(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
|
|
15182
16849
|
return Math.min(workerBatchSize(options, flowManyBatchLimit), workerConcurrency(options));
|
|
15183
16850
|
}
|
|
15184
16851
|
function workerDrainBatches(options) {
|
|
15185
|
-
return
|
|
16852
|
+
return positiveInteger2(options.claimDrainBatches, 1);
|
|
15186
16853
|
}
|
|
15187
16854
|
function workerLeaseMs(options, fallback = 3e4) {
|
|
15188
|
-
return
|
|
16855
|
+
return positiveInteger2(options.leaseMs, positiveInteger2(fallback, 3e4));
|
|
15189
16856
|
}
|
|
15190
16857
|
function workerIdleSleepMs(options) {
|
|
15191
16858
|
return nonNegativeDuration(options.idleSleepMs, 250);
|
|
@@ -15197,7 +16864,7 @@ function workerClaimBlockMs(options, useBlocking) {
|
|
|
15197
16864
|
if (options.signal == null || !Number.isFinite(options.blockMs) || options.blockMs < 0) {
|
|
15198
16865
|
return options.blockMs;
|
|
15199
16866
|
}
|
|
15200
|
-
const abortPollMs =
|
|
16867
|
+
const abortPollMs = positiveInteger2(options.abortPollMs, 1e3);
|
|
15201
16868
|
return options.blockMs === 0 ? abortPollMs : Math.min(Math.trunc(options.blockMs), abortPollMs);
|
|
15202
16869
|
}
|
|
15203
16870
|
function workerMaxIdleSleepMs(options, idleSleepMs = workerIdleSleepMs(options)) {
|
|
@@ -15208,14 +16875,14 @@ function nextWorkerIdleSleepMs(currentIdleSleepMs, maxIdleSleepMs) {
|
|
|
15208
16875
|
return Math.min(maxIdleSleepMs, Math.max(1, currentIdleSleepMs * 2));
|
|
15209
16876
|
}
|
|
15210
16877
|
async function runContinuousWorkerPool(options) {
|
|
15211
|
-
const concurrency =
|
|
15212
|
-
const maxClaimSize =
|
|
16878
|
+
const concurrency = positiveInteger2(options.concurrency, 1);
|
|
16879
|
+
const maxClaimSize = positiveInteger2(options.maxClaimSize, concurrency);
|
|
15213
16880
|
const initialIdleSleepMs = nonNegativeDuration(options.idleSleepMs, 250);
|
|
15214
16881
|
const maxIdleSleepMs = Math.max(
|
|
15215
16882
|
initialIdleSleepMs,
|
|
15216
16883
|
nonNegativeDuration(options.maxIdleSleepMs, 5e3)
|
|
15217
16884
|
);
|
|
15218
|
-
const refillDelayMs =
|
|
16885
|
+
const refillDelayMs = nonNegativeInteger3(options.refillDelayMs, 0);
|
|
15219
16886
|
const active = /* @__PURE__ */ new Set();
|
|
15220
16887
|
const pending = [];
|
|
15221
16888
|
let pendingIndex = 0;
|
|
@@ -15331,10 +16998,10 @@ function normalizeWorkflowWorkerConfig(options) {
|
|
|
15331
16998
|
...captured
|
|
15332
16999
|
});
|
|
15333
17000
|
}
|
|
15334
|
-
function
|
|
17001
|
+
function positiveInteger2(value, fallback) {
|
|
15335
17002
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(1, Math.trunc(value));
|
|
15336
17003
|
}
|
|
15337
|
-
function
|
|
17004
|
+
function nonNegativeInteger3(value, fallback) {
|
|
15338
17005
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(0, Math.trunc(value));
|
|
15339
17006
|
}
|
|
15340
17007
|
function nonNegativeDuration(value, fallback) {
|
|
@@ -16963,8 +18630,8 @@ var WorkflowWorker = class {
|
|
|
16963
18630
|
};
|
|
16964
18631
|
|
|
16965
18632
|
// src/version.ts
|
|
16966
|
-
var FERRICSTORE_SDK_VERSION = "0.
|
|
16967
|
-
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.
|
|
18633
|
+
var FERRICSTORE_SDK_VERSION = "0.5.0";
|
|
18634
|
+
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.11.0";
|
|
16968
18635
|
var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
|
|
16969
18636
|
export {
|
|
16970
18637
|
BitmapStore,
|
|
@@ -16982,6 +18649,8 @@ export {
|
|
|
16982
18649
|
FlowAlreadyExistsError,
|
|
16983
18650
|
FlowBatchError,
|
|
16984
18651
|
FlowNotFoundError,
|
|
18652
|
+
FlowProjection,
|
|
18653
|
+
FlowQueryError,
|
|
16985
18654
|
FlowWrongStateError,
|
|
16986
18655
|
GeoStore,
|
|
16987
18656
|
HashStore,
|
|
@@ -17024,6 +18693,7 @@ export {
|
|
|
17024
18693
|
isOutcome,
|
|
17025
18694
|
isReconnectableClosedConnectionError,
|
|
17026
18695
|
mapException,
|
|
18696
|
+
projectFlowQuery,
|
|
17027
18697
|
retry,
|
|
17028
18698
|
transition
|
|
17029
18699
|
};
|