@ferricstore/ferricstore 0.11.4 → 0.11.6
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 +5 -4
- package/dist/index.cjs +172 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +172 -17
- package/dist/index.js.map +1 -1
- package/docs/api/index.html +5 -4
- package/docs/api/variables/FERRICSTORE_SDK_VERSION.html +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,9 +18,10 @@ Requires Node.js 22.22 or newer. The SDK ships ESM and CommonJS builds and is te
|
|
|
18
18
|
|
|
19
19
|
## Compatibility
|
|
20
20
|
|
|
21
|
-
TypeScript SDK `0.11.
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
TypeScript SDK `0.11.6` requires FerricStore server `0.11.4` or newer. With
|
|
22
|
+
FerricStore 0.11.6 it negotiates compact Stream mode 34 for homogeneous auto-ID
|
|
23
|
+
`XADD` pipelines and compact Pub/Sub mode 35 for homogeneous `PUBLISH`
|
|
24
|
+
pipelines. Native wire protocol v1 and the generic fallback are unchanged.
|
|
24
25
|
Capabilities and response-size limits are negotiated
|
|
25
26
|
per connection from the HELLO-shaped startup response rather than inferred from
|
|
26
27
|
a server version table.
|
|
@@ -43,7 +44,7 @@ const { FerricStoreClient, JsonCodec } = require("@ferricstore/ferricstore");
|
|
|
43
44
|
docker run -p 6388:6388 \
|
|
44
45
|
-e FERRICSTORE_PROTECTED_MODE=false \
|
|
45
46
|
-v ferricstore_data:/data \
|
|
46
|
-
|
|
47
|
+
quay.io/ferricstore/ferricstore:0.11.6
|
|
47
48
|
```
|
|
48
49
|
|
|
49
50
|
## Query durable runs
|
package/dist/index.cjs
CHANGED
|
@@ -4632,7 +4632,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
|
|
|
4632
4632
|
}
|
|
4633
4633
|
return { flags: FLAG_CUSTOM_PAYLOAD, opcode, payload: out };
|
|
4634
4634
|
}
|
|
4635
|
-
function compactPipelinePayload(commands, maxBodyBytes) {
|
|
4635
|
+
function compactPipelinePayload(commands, maxBodyBytes, allowStreamXAdd = true, allowPubSubPublish = true) {
|
|
4636
4636
|
if (commands.length === 0) {
|
|
4637
4637
|
assertCompactPayloadFits(6, maxBodyBytes);
|
|
4638
4638
|
const out = import_node_buffer14.Buffer.allocUnsafe(6);
|
|
@@ -4644,8 +4644,115 @@ function compactPipelinePayload(commands, maxBodyBytes) {
|
|
|
4644
4644
|
}
|
|
4645
4645
|
if (commandNameIs(commands[0]?.[0], "SET")) return compactSetPipelinePayload(commands, maxBodyBytes);
|
|
4646
4646
|
if (commandNameIs(commands[0]?.[0], "GET")) return compactGetPipelinePayload(commands, maxBodyBytes);
|
|
4647
|
+
if (commandNameIs(commands[0]?.[0], "XADD")) {
|
|
4648
|
+
return allowStreamXAdd ? compactStreamXAddPipelinePayload(commands, maxBodyBytes) : void 0;
|
|
4649
|
+
}
|
|
4650
|
+
if (commandNameIs(commands[0]?.[0], "PUBLISH")) {
|
|
4651
|
+
return allowPubSubPublish ? compactPubSubPublishPipelinePayload(commands, maxBodyBytes) : void 0;
|
|
4652
|
+
}
|
|
4647
4653
|
return void 0;
|
|
4648
4654
|
}
|
|
4655
|
+
function compactPubSubPublishPipelinePayload(commands, maxBodyBytes) {
|
|
4656
|
+
const minimum = 6 + commands.length * 8;
|
|
4657
|
+
if (!compactPayloadFits(minimum, maxBodyBytes)) {
|
|
4658
|
+
if (!compactPipelineEligible(commands, "PUBLISH", 3)) return void 0;
|
|
4659
|
+
assertCompactPayloadFits(minimum, maxBodyBytes);
|
|
4660
|
+
}
|
|
4661
|
+
const argumentByteLengths = new Uint32Array(commands.length * 2);
|
|
4662
|
+
const argumentValues = new Array(commands.length * 2);
|
|
4663
|
+
let total = 6;
|
|
4664
|
+
for (let index = 0; index < commands.length; index += 1) {
|
|
4665
|
+
const command = commands[index];
|
|
4666
|
+
if (!Object.hasOwn(commands, index) || !Array.isArray(command)) {
|
|
4667
|
+
throw new TypeError("pipeline commands must be a dense array of command arrays");
|
|
4668
|
+
}
|
|
4669
|
+
if (command.length !== 3 || !Object.hasOwn(command, 0) || !Object.hasOwn(command, 1) || !Object.hasOwn(command, 2)) {
|
|
4670
|
+
if (command.length === 3) throw new TypeError("pipeline command arguments must be dense");
|
|
4671
|
+
return void 0;
|
|
4672
|
+
}
|
|
4673
|
+
if (!commandNameIs(command[0], "PUBLISH")) return void 0;
|
|
4674
|
+
const channel = command[1];
|
|
4675
|
+
const message = command[2];
|
|
4676
|
+
if (!isCompactBinaryScalar(channel) || !isCompactBinaryScalar(message)) return void 0;
|
|
4677
|
+
const channelByteLength = compactBinaryByteLength(channel);
|
|
4678
|
+
const messageByteLength = compactBinaryByteLength(message);
|
|
4679
|
+
argumentValues[index * 2] = channel;
|
|
4680
|
+
argumentValues[index * 2 + 1] = message;
|
|
4681
|
+
argumentByteLengths[index * 2] = channelByteLength;
|
|
4682
|
+
argumentByteLengths[index * 2 + 1] = messageByteLength;
|
|
4683
|
+
total += 8 + channelByteLength + messageByteLength;
|
|
4684
|
+
}
|
|
4685
|
+
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4686
|
+
const out = import_node_buffer14.Buffer.allocUnsafe(total);
|
|
4687
|
+
let offset = writeCompactPipelineHeader(out, 128 | 35, commands.length);
|
|
4688
|
+
for (let index = 0; index < commands.length; index += 1) {
|
|
4689
|
+
offset = writeBinaryValue(
|
|
4690
|
+
out,
|
|
4691
|
+
offset,
|
|
4692
|
+
argumentValues[index * 2],
|
|
4693
|
+
argumentByteLengths[index * 2] ?? 0
|
|
4694
|
+
);
|
|
4695
|
+
offset = writeBinaryValue(
|
|
4696
|
+
out,
|
|
4697
|
+
offset,
|
|
4698
|
+
argumentValues[index * 2 + 1],
|
|
4699
|
+
argumentByteLengths[index * 2 + 1] ?? 0
|
|
4700
|
+
);
|
|
4701
|
+
}
|
|
4702
|
+
return out;
|
|
4703
|
+
}
|
|
4704
|
+
function compactStreamXAddPipelinePayload(commands, maxBodyBytes) {
|
|
4705
|
+
let argumentCount = 0;
|
|
4706
|
+
let minimum = 6;
|
|
4707
|
+
for (const command of commands) {
|
|
4708
|
+
if (!Array.isArray(command)) {
|
|
4709
|
+
throw new TypeError("pipeline commands must be a dense array of command arrays");
|
|
4710
|
+
}
|
|
4711
|
+
if (command.length < 5 || (command.length - 3) % 2 !== 0) return void 0;
|
|
4712
|
+
for (let argumentIndex = 0; argumentIndex < command.length; argumentIndex += 1) {
|
|
4713
|
+
if (!Object.hasOwn(command, argumentIndex)) {
|
|
4714
|
+
throw new TypeError("pipeline command arguments must be dense");
|
|
4715
|
+
}
|
|
4716
|
+
}
|
|
4717
|
+
if (!commandTokenIs(command[0], "XADD") || !commandTokenIs(command[2], "*")) return void 0;
|
|
4718
|
+
if ((command.length - 3) / 2 > 65535) return void 0;
|
|
4719
|
+
for (let argumentIndex = 1; argumentIndex < command.length; argumentIndex += 1) {
|
|
4720
|
+
if (argumentIndex !== 2 && !isCompactBinaryScalar(command[argumentIndex])) return void 0;
|
|
4721
|
+
}
|
|
4722
|
+
argumentCount += command.length - 2;
|
|
4723
|
+
minimum += 2 + (command.length - 2) * 4;
|
|
4724
|
+
}
|
|
4725
|
+
assertCompactPayloadFits(minimum, maxBodyBytes);
|
|
4726
|
+
const byteLengths = new Uint32Array(argumentCount);
|
|
4727
|
+
let lengthIndex = 0;
|
|
4728
|
+
let total = 6;
|
|
4729
|
+
for (const command of commands) {
|
|
4730
|
+
total += 2;
|
|
4731
|
+
for (let argumentIndex = 1; argumentIndex < command.length; argumentIndex += 1) {
|
|
4732
|
+
if (argumentIndex === 2) continue;
|
|
4733
|
+
const value = command[argumentIndex];
|
|
4734
|
+
const byteLength = compactBinaryByteLength(value);
|
|
4735
|
+
byteLengths[lengthIndex] = byteLength;
|
|
4736
|
+
lengthIndex += 1;
|
|
4737
|
+
total += 4 + byteLength;
|
|
4738
|
+
}
|
|
4739
|
+
}
|
|
4740
|
+
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4741
|
+
const out = import_node_buffer14.Buffer.allocUnsafe(total);
|
|
4742
|
+
let offset = writeCompactPipelineHeader(out, 128 | 34, commands.length);
|
|
4743
|
+
lengthIndex = 0;
|
|
4744
|
+
for (const command of commands) {
|
|
4745
|
+
offset = writeBinaryValue(out, offset, command[1], byteLengths[lengthIndex] ?? 0);
|
|
4746
|
+
lengthIndex += 1;
|
|
4747
|
+
out.writeUInt16BE((command.length - 3) / 2, offset);
|
|
4748
|
+
offset += 2;
|
|
4749
|
+
for (let argumentIndex = 3; argumentIndex < command.length; argumentIndex += 1) {
|
|
4750
|
+
offset = writeBinaryValue(out, offset, command[argumentIndex], byteLengths[lengthIndex] ?? 0);
|
|
4751
|
+
lengthIndex += 1;
|
|
4752
|
+
}
|
|
4753
|
+
}
|
|
4754
|
+
return out;
|
|
4755
|
+
}
|
|
4649
4756
|
function compactSetPipelinePayload(commands, maxBodyBytes) {
|
|
4650
4757
|
let total = 6;
|
|
4651
4758
|
const minimum = total + commands.length * 8;
|
|
@@ -5227,10 +5334,19 @@ function decodeValueAt(data, offset, limits, budget, depth) {
|
|
|
5227
5334
|
const count = data.readUInt32BE(offset);
|
|
5228
5335
|
requireValueContainer(count, depth, limits, budget);
|
|
5229
5336
|
offset += 4;
|
|
5230
|
-
const values =
|
|
5337
|
+
const values = new Array(count);
|
|
5338
|
+
if (count === 3) {
|
|
5339
|
+
const first = decodeValueAt(data, offset, limits, budget, depth + 1);
|
|
5340
|
+
const second = decodeValueAt(data, first.offset, limits, budget, depth + 1);
|
|
5341
|
+
const third = decodeValueAt(data, second.offset, limits, budget, depth + 1);
|
|
5342
|
+
values[0] = first.value;
|
|
5343
|
+
values[1] = second.value;
|
|
5344
|
+
values[2] = third.value;
|
|
5345
|
+
return { value: values, offset: third.offset };
|
|
5346
|
+
}
|
|
5231
5347
|
for (let index = 0; index < count; index += 1) {
|
|
5232
5348
|
const read = decodeValueAt(data, offset, limits, budget, depth + 1);
|
|
5233
|
-
values
|
|
5349
|
+
values[index] = read.value;
|
|
5234
5350
|
offset = read.offset;
|
|
5235
5351
|
}
|
|
5236
5352
|
return { value: values, offset };
|
|
@@ -5547,6 +5663,8 @@ function nativeNegotiation(value) {
|
|
|
5547
5663
|
compactResponseOpcodes: parseCompactResponseOpcodes(
|
|
5548
5664
|
field(responseCodecs, "compact_response_opcodes")
|
|
5549
5665
|
),
|
|
5666
|
+
compactPubSubPublish: strictUnsigned16(field(field(field(capabilities, "pipeline"), "modes"), "pubsub_publish")) === 35,
|
|
5667
|
+
compactStreamXAdd: strictUnsigned16(field(field(field(capabilities, "pipeline"), "modes"), "stream_xadd_auto")) === 34,
|
|
5550
5668
|
flowQuery: parseFlowQueryNegotiation(capabilities, schemas),
|
|
5551
5669
|
...maxResponseBytes == null ? {} : { maxResponseBytes }
|
|
5552
5670
|
};
|
|
@@ -6839,8 +6957,13 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
6839
6957
|
}
|
|
6840
6958
|
return commandExec(args);
|
|
6841
6959
|
}
|
|
6842
|
-
function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
|
|
6843
|
-
const compact = compactPipelinePayload(
|
|
6960
|
+
function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER, allowStreamXAdd = true, allowPubSubPublish = true) {
|
|
6961
|
+
const compact = compactPipelinePayload(
|
|
6962
|
+
commands,
|
|
6963
|
+
maxBodyBytes,
|
|
6964
|
+
allowStreamXAdd,
|
|
6965
|
+
allowPubSubPublish
|
|
6966
|
+
);
|
|
6844
6967
|
if (compact != null) {
|
|
6845
6968
|
return {
|
|
6846
6969
|
compactResponseItems: commands.length,
|
|
@@ -7341,13 +7464,18 @@ function surfaceIndividualCommandErrors(results, rejected, hasRejected, options)
|
|
|
7341
7464
|
}
|
|
7342
7465
|
|
|
7343
7466
|
// src/native-pipeline-execution.ts
|
|
7344
|
-
async function executeNativeFusedPipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes) {
|
|
7467
|
+
async function executeNativeFusedPipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes, compactStreamXAdd = true, compactPubSubPublish = true) {
|
|
7345
7468
|
commands = snapshotPipelineCommands(commands);
|
|
7346
7469
|
options = snapshotPipelineOptions(options) ?? options;
|
|
7347
7470
|
if (commands.length === 0) return [];
|
|
7348
7471
|
if (maxPipelineCommands === 0 || commands.length > maxPipelineCommands) return void 0;
|
|
7349
7472
|
try {
|
|
7350
|
-
const pipeline = tryPipelineCommand(
|
|
7473
|
+
const pipeline = tryPipelineCommand(
|
|
7474
|
+
commands,
|
|
7475
|
+
maxRequestFrameBytes,
|
|
7476
|
+
compactStreamXAdd,
|
|
7477
|
+
compactPubSubPublish
|
|
7478
|
+
);
|
|
7351
7479
|
if (pipeline == null) return void 0;
|
|
7352
7480
|
const response = await host.executeProtocolCommand(pipeline, laneId);
|
|
7353
7481
|
return unwrapPipelineResponse(response, options, commands.length);
|
|
@@ -7356,7 +7484,7 @@ async function executeNativeFusedPipeline(host, commands, laneId, options, maxPi
|
|
|
7356
7484
|
throw error;
|
|
7357
7485
|
}
|
|
7358
7486
|
}
|
|
7359
|
-
async function executeNativePipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes) {
|
|
7487
|
+
async function executeNativePipeline(host, commands, laneId, options, maxPipelineCommands, maxRequestFrameBytes, compactStreamXAdd = true, compactPubSubPublish = true) {
|
|
7360
7488
|
commands = snapshotPipelineCommands(commands);
|
|
7361
7489
|
options = snapshotPipelineOptions(options) ?? options;
|
|
7362
7490
|
if (commands.length === 0) return [];
|
|
@@ -7364,7 +7492,15 @@ async function executeNativePipeline(host, commands, laneId, options, maxPipelin
|
|
|
7364
7492
|
return await executeIndividually(host, commands, laneId, pipelineFallbackOptions(commands, options));
|
|
7365
7493
|
}
|
|
7366
7494
|
if (commands.length <= maxPipelineCommands) {
|
|
7367
|
-
return await executeChunk(
|
|
7495
|
+
return await executeChunk(
|
|
7496
|
+
host,
|
|
7497
|
+
commands,
|
|
7498
|
+
laneId,
|
|
7499
|
+
options,
|
|
7500
|
+
maxRequestFrameBytes,
|
|
7501
|
+
compactStreamXAdd,
|
|
7502
|
+
compactPubSubPublish
|
|
7503
|
+
);
|
|
7368
7504
|
}
|
|
7369
7505
|
const collectingOptions = pipelineErrorCollectingOptions(options);
|
|
7370
7506
|
const results = new Array(commands.length);
|
|
@@ -7376,7 +7512,9 @@ async function executeNativePipeline(host, commands, laneId, options, maxPipelin
|
|
|
7376
7512
|
chunk,
|
|
7377
7513
|
laneId,
|
|
7378
7514
|
pipelineSliceOptions(collectingOptions, start, start + chunk.length),
|
|
7379
|
-
maxRequestFrameBytes
|
|
7515
|
+
maxRequestFrameBytes,
|
|
7516
|
+
compactStreamXAdd,
|
|
7517
|
+
compactPubSubPublish
|
|
7380
7518
|
);
|
|
7381
7519
|
for (let index = 0; index < chunkResults.length; index += 1) results[start + index] = chunkResults[index];
|
|
7382
7520
|
rejected = collectPipelineRejections(chunkResults, start, rejected);
|
|
@@ -7384,9 +7522,14 @@ async function executeNativePipeline(host, commands, laneId, options, maxPipelin
|
|
|
7384
7522
|
if (rejected != null) attachPipelineItemRejectionFlags(results, rejected);
|
|
7385
7523
|
return surfaceFirstPipelineItemError(results, options);
|
|
7386
7524
|
}
|
|
7387
|
-
async function executeChunk(host, commands, laneId, options, maxRequestFrameBytes) {
|
|
7525
|
+
async function executeChunk(host, commands, laneId, options, maxRequestFrameBytes, compactStreamXAdd, compactPubSubPublish) {
|
|
7388
7526
|
try {
|
|
7389
|
-
const pipeline = tryPipelineCommand(
|
|
7527
|
+
const pipeline = tryPipelineCommand(
|
|
7528
|
+
commands,
|
|
7529
|
+
maxRequestFrameBytes,
|
|
7530
|
+
compactStreamXAdd,
|
|
7531
|
+
compactPubSubPublish
|
|
7532
|
+
);
|
|
7390
7533
|
if (pipeline != null) {
|
|
7391
7534
|
const response = await host.executeProtocolCommand(pipeline, laneId);
|
|
7392
7535
|
return unwrapPipelineResponse(response, options, commands.length);
|
|
@@ -7404,14 +7547,18 @@ async function executeChunk(host, commands, laneId, options, maxRequestFrameByte
|
|
|
7404
7547
|
commands.slice(0, middle),
|
|
7405
7548
|
laneId,
|
|
7406
7549
|
pipelineSliceOptions(collectingOptions, 0, middle),
|
|
7407
|
-
maxRequestFrameBytes
|
|
7550
|
+
maxRequestFrameBytes,
|
|
7551
|
+
compactStreamXAdd,
|
|
7552
|
+
compactPubSubPublish
|
|
7408
7553
|
);
|
|
7409
7554
|
const second = await executeChunk(
|
|
7410
7555
|
host,
|
|
7411
7556
|
commands.slice(middle),
|
|
7412
7557
|
laneId,
|
|
7413
7558
|
pipelineSliceOptions(collectingOptions, middle, commands.length),
|
|
7414
|
-
maxRequestFrameBytes
|
|
7559
|
+
maxRequestFrameBytes,
|
|
7560
|
+
compactStreamXAdd,
|
|
7561
|
+
compactPubSubPublish
|
|
7415
7562
|
);
|
|
7416
7563
|
return surfaceFirstPipelineItemError(mergePipelineResults(first, second), options);
|
|
7417
7564
|
}
|
|
@@ -8045,6 +8192,8 @@ var NativeConnectionCapabilities = class {
|
|
|
8045
8192
|
}
|
|
8046
8193
|
configuredRequestFrameBytes;
|
|
8047
8194
|
compactResponseOpcodes = EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
8195
|
+
compactPubSubPublish = false;
|
|
8196
|
+
compactStreamXAdd = false;
|
|
8048
8197
|
flowQuery;
|
|
8049
8198
|
requestFrameBytes;
|
|
8050
8199
|
negotiatedRequestFrameBytes;
|
|
@@ -8052,6 +8201,8 @@ var NativeConnectionCapabilities = class {
|
|
|
8052
8201
|
const limits = startupLimits(value);
|
|
8053
8202
|
const negotiation = nativeNegotiation(value);
|
|
8054
8203
|
this.compactResponseOpcodes = negotiation.compactResponseOpcodes;
|
|
8204
|
+
this.compactPubSubPublish = negotiation.compactPubSubPublish;
|
|
8205
|
+
this.compactStreamXAdd = negotiation.compactStreamXAdd;
|
|
8055
8206
|
this.flowQuery = negotiation.flowQuery;
|
|
8056
8207
|
if (limits.frameBytes != null) {
|
|
8057
8208
|
this.negotiatedRequestFrameBytes = Math.min(
|
|
@@ -8277,7 +8428,9 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
8277
8428
|
laneId,
|
|
8278
8429
|
options,
|
|
8279
8430
|
this.maxPipelineCommands,
|
|
8280
|
-
this.capabilities.requestFrameBytes
|
|
8431
|
+
this.capabilities.requestFrameBytes,
|
|
8432
|
+
this.capabilities.compactStreamXAdd,
|
|
8433
|
+
this.capabilities.compactPubSubPublish
|
|
8281
8434
|
);
|
|
8282
8435
|
}
|
|
8283
8436
|
/** @internal Execute an ordered pipeline on a topology-selected lane. */
|
|
@@ -8288,7 +8441,9 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
8288
8441
|
laneId,
|
|
8289
8442
|
options,
|
|
8290
8443
|
this.maxPipelineCommands,
|
|
8291
|
-
this.capabilities.requestFrameBytes
|
|
8444
|
+
this.capabilities.requestFrameBytes,
|
|
8445
|
+
this.capabilities.compactStreamXAdd,
|
|
8446
|
+
this.capabilities.compactPubSubPublish
|
|
8292
8447
|
);
|
|
8293
8448
|
}
|
|
8294
8449
|
async close() {
|
|
@@ -20371,7 +20526,7 @@ var WorkflowWorker = class {
|
|
|
20371
20526
|
};
|
|
20372
20527
|
|
|
20373
20528
|
// src/version.ts
|
|
20374
|
-
var FERRICSTORE_SDK_VERSION = "0.11.
|
|
20529
|
+
var FERRICSTORE_SDK_VERSION = "0.11.6";
|
|
20375
20530
|
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.11.4";
|
|
20376
20531
|
var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
|
|
20377
20532
|
// Annotate the CommonJS export names for ESM import in node:
|