@durable-streams/client-conformance-tests 0.1.9 → 0.2.1

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.
@@ -1,4 +1,4 @@
1
- import { calculateStats, formatStats, parseResult, serializeCommand } from "./protocol-1p0soayz.js";
1
+ import { calculateStats, formatStats, parseResult, serializeCommand } from "./protocol-BnqUAMKe.js";
2
2
  import { spawn } from "node:child_process";
3
3
  import { createInterface } from "node:readline";
4
4
  import { randomUUID } from "node:crypto";
@@ -161,7 +161,9 @@ async function executeOperation(op, ctx) {
161
161
  contentType: op.contentType,
162
162
  ttlSeconds: op.ttlSeconds,
163
163
  expiresAt: op.expiresAt,
164
- headers: op.headers
164
+ headers: op.headers,
165
+ closed: op.closed,
166
+ data: op.data
165
167
  }, commandTimeout);
166
168
  if (verbose) console.log(` create ${path$1}: ${result.success ? `ok` : `failed`}`);
167
169
  return { result };
@@ -248,6 +250,33 @@ async function executeOperation(op, ctx) {
248
250
  if (verbose) console.log(` idempotent-append-batch ${path$1}: ${result.success ? `ok` : `failed`}`);
249
251
  return { result };
250
252
  }
253
+ case `idempotent-close`: {
254
+ const path$1 = resolveVariables(op.path, variables);
255
+ const data = op.data ? resolveVariables(op.data, variables) : void 0;
256
+ const result = await client.send({
257
+ type: `idempotent-close`,
258
+ path: path$1,
259
+ producerId: op.producerId,
260
+ epoch: op.epoch ?? 0,
261
+ data,
262
+ autoClaim: op.autoClaim ?? false,
263
+ headers: op.headers
264
+ }, commandTimeout);
265
+ if (verbose) console.log(` idempotent-close ${path$1}: ${result.success ? `ok` : `failed`}`);
266
+ return { result };
267
+ }
268
+ case `idempotent-detach`: {
269
+ const path$1 = resolveVariables(op.path, variables);
270
+ const result = await client.send({
271
+ type: `idempotent-detach`,
272
+ path: path$1,
273
+ producerId: op.producerId,
274
+ epoch: op.epoch ?? 0,
275
+ headers: op.headers
276
+ }, commandTimeout);
277
+ if (verbose) console.log(` idempotent-detach ${path$1}: ${result.success ? `ok` : `failed`}`);
278
+ return { result };
279
+ }
251
280
  case `read`: {
252
281
  const path$1 = resolveVariables(op.path, variables);
253
282
  const offset = op.offset ? resolveVariables(op.offset, variables) : void 0;
@@ -307,6 +336,43 @@ async function executeOperation(op, ctx) {
307
336
  if (verbose) console.log(` delete ${path$1}: ${result.success ? `ok` : `failed`}`);
308
337
  return { result };
309
338
  }
339
+ case `close`: {
340
+ const path$1 = resolveVariables(op.path, variables);
341
+ const result = await client.send({
342
+ type: `close`,
343
+ path: path$1,
344
+ data: op.data,
345
+ contentType: op.contentType
346
+ }, commandTimeout);
347
+ if (verbose) console.log(` close ${path$1}: ${result.success ? `ok` : `failed`}`);
348
+ return { result };
349
+ }
350
+ case `server-close`: {
351
+ const path$1 = resolveVariables(op.path, variables);
352
+ try {
353
+ const headers = {
354
+ "Stream-Closed": `true`,
355
+ ...op.headers
356
+ };
357
+ if (op.data && op.contentType) headers[`content-type`] = op.contentType;
358
+ const response = await fetch(`${ctx.serverUrl}${path$1}`, {
359
+ method: `POST`,
360
+ body: op.data,
361
+ headers
362
+ });
363
+ const status = response.status;
364
+ const finalOffset = response.headers.get(`Stream-Next-Offset`) ?? void 0;
365
+ if (verbose) console.log(` server-close ${path$1}: status=${status}`);
366
+ const result = {
367
+ type: `close`,
368
+ success: true,
369
+ finalOffset: finalOffset ?? ``
370
+ };
371
+ return { result };
372
+ } catch (err) {
373
+ return { error: `Server close failed: ${err instanceof Error ? err.message : String(err)}` };
374
+ }
375
+ }
310
376
  case `wait`: {
311
377
  await new Promise((resolve) => setTimeout(resolve, op.ms));
312
378
  return {};
@@ -488,6 +554,9 @@ function isAppendResult(result) {
488
554
  function isHeadResult(result) {
489
555
  return result.type === `head` && result.success;
490
556
  }
557
+ function isCloseResult(result) {
558
+ return result.type === `close` && result.success;
559
+ }
491
560
  function isErrorResult(result) {
492
561
  return result.type === `error` && !result.success;
493
562
  }
@@ -529,6 +598,15 @@ function validateExpectation(result, expect) {
529
598
  if (expect.upToDate !== void 0 && isReadResult(result)) {
530
599
  if (result.upToDate !== expect.upToDate) return `Expected upToDate=${expect.upToDate}, got ${result.upToDate}`;
531
600
  }
601
+ if (expect.streamClosed !== void 0 && isReadResult(result)) {
602
+ if (result.streamClosed !== expect.streamClosed) return `Expected streamClosed=${expect.streamClosed}, got ${result.streamClosed}`;
603
+ }
604
+ if (expect.streamClosed !== void 0 && isHeadResult(result)) {
605
+ if (result.streamClosed !== expect.streamClosed) return `Expected streamClosed=${expect.streamClosed}, got ${result.streamClosed}`;
606
+ }
607
+ if (expect.finalOffset !== void 0 && isCloseResult(result)) {
608
+ if (result.finalOffset !== expect.finalOffset) return `Expected finalOffset=${expect.finalOffset}, got ${result.finalOffset}`;
609
+ }
532
610
  if (expect.chunkCount !== void 0 && isReadResult(result)) {
533
611
  if (result.chunks.length !== expect.chunkCount) return `Expected ${expect.chunkCount} chunks, got ${result.chunks.length}`;
534
612
  }
package/dist/cli.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- require('./protocol-IioVPNaP.cjs');
4
- const require_benchmark_runner = require('./benchmark-runner-DliEfq9k.cjs');
3
+ require('./protocol-sDk3deGa.cjs');
4
+ const require_benchmark_runner = require('./benchmark-runner-BQiarXdy.cjs');
5
5
 
6
6
  //#region src/cli.ts
7
7
  const HELP = `
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import "./protocol-1p0soayz.js";
3
- import { aggregateBenchmarkResults, runBenchmarks, runConformanceTests } from "./benchmark-runner-81waaCzs.js";
2
+ import "./protocol-BnqUAMKe.js";
3
+ import { aggregateBenchmarkResults, runBenchmarks, runConformanceTests } from "./benchmark-runner-IGT51RTF.js";
4
4
 
5
5
  //#region src/cli.ts
6
6
  const HELP = `
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
- const require_protocol = require('./protocol-IioVPNaP.cjs');
2
- const require_benchmark_runner = require('./benchmark-runner-DliEfq9k.cjs');
1
+ const require_protocol = require('./protocol-sDk3deGa.cjs');
2
+ const require_benchmark_runner = require('./benchmark-runner-BQiarXdy.cjs');
3
3
 
4
4
  exports.ErrorCodes = require_protocol.ErrorCodes
5
5
  exports.allScenarios = require_benchmark_runner.allScenarios
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkStats, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCommand, TestResult, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, calculateStats, decodeBase64, encodeBase64, formatStats, parseCommand, parseResult, serializeCommand, serializeResult } from "./protocol-BxZTqJmO.cjs";
1
+ import { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkStats, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, CloseCommand, CloseResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, IdempotentCloseCommand, IdempotentCloseResult, IdempotentDetachCommand, IdempotentDetachResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, ServerCloseCommand, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCommand, TestResult, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, calculateStats, decodeBase64, encodeBase64, formatStats, parseCommand, parseResult, serializeCommand, serializeResult } from "./protocol-COHkkGmU.cjs";
2
2
 
3
3
  //#region src/test-cases.d.ts
4
4
  interface TestSuite {
@@ -61,6 +61,10 @@ interface CreateOperation {
61
61
  expiresAt?: string;
62
62
  /** Custom headers */
63
63
  headers?: Record<string, string>;
64
+ /** Create stream in closed state */
65
+ closed?: boolean;
66
+ /** Initial body data to include on creation */
67
+ data?: string;
64
68
  /** Expected result */
65
69
  expect?: CreateExpectation;
66
70
  }
@@ -168,6 +172,49 @@ interface IdempotentAppendBatchExpectation extends BaseExpectation {
168
172
  allSucceed?: boolean;
169
173
  }
170
174
  /**
175
+ * Close a stream via IdempotentProducer (uses producer headers for idempotency).
176
+ */
177
+ interface IdempotentCloseOperation {
178
+ action: `idempotent-close`;
179
+ path: string;
180
+ /** Producer ID */
181
+ producerId: string;
182
+ /** Producer epoch */
183
+ epoch?: number;
184
+ /** Optional final message to append atomically with close */
185
+ data?: string;
186
+ /** Auto-claim epoch on 403 */
187
+ autoClaim?: boolean;
188
+ headers?: Record<string, string>;
189
+ expect?: IdempotentCloseExpectation;
190
+ }
191
+ /**
192
+ * Expectation for idempotent-close operation.
193
+ */
194
+ interface IdempotentCloseExpectation extends BaseExpectation {
195
+ /** Store the final offset */
196
+ storeOffsetAs?: string;
197
+ /** Expected finalOffset */
198
+ finalOffset?: string;
199
+ }
200
+ /**
201
+ * Detach an IdempotentProducer (stop without closing stream).
202
+ */
203
+ interface IdempotentDetachOperation {
204
+ action: `idempotent-detach`;
205
+ path: string;
206
+ /** Producer ID */
207
+ producerId: string;
208
+ /** Producer epoch */
209
+ epoch?: number;
210
+ headers?: Record<string, string>;
211
+ expect?: IdempotentDetachExpectation;
212
+ }
213
+ /**
214
+ * Expectation for idempotent-detach operation.
215
+ */
216
+ interface IdempotentDetachExpectation extends BaseExpectation {}
217
+ /**
171
218
  * Read from a stream.
172
219
  */
173
220
  interface ReadOperation {
@@ -209,6 +256,33 @@ interface DeleteOperation {
209
256
  expect?: DeleteExpectation;
210
257
  }
211
258
  /**
259
+ * Close a stream (no more appends allowed).
260
+ */
261
+ interface CloseOperation {
262
+ action: `close`;
263
+ path: string;
264
+ /** Optional final message to append */
265
+ data?: string;
266
+ /** Content type for the final message */
267
+ contentType?: string;
268
+ headers?: Record<string, string>;
269
+ expect?: CloseExpectation;
270
+ }
271
+ /**
272
+ * Close a stream via direct HTTP (bypasses client adapter).
273
+ * Used for testing server-side stream closure behavior.
274
+ */
275
+ interface ServerCloseOperation {
276
+ action: `server-close`;
277
+ path: string;
278
+ /** Optional body data */
279
+ data?: string;
280
+ /** Content type for the body */
281
+ contentType?: string;
282
+ headers?: Record<string, string>;
283
+ expect?: ServerCloseExpectation;
284
+ }
285
+ /**
212
286
  * Wait for a duration (for timing-sensitive tests).
213
287
  */
214
288
  interface WaitOperation {
@@ -412,7 +486,7 @@ interface ValidateExpectation {
412
486
  /**
413
487
  * All possible test operations.
414
488
  */
415
- type TestOperation = CreateOperation | ConnectOperation | AppendOperation | AppendBatchOperation | IdempotentAppendOperation | IdempotentAppendBatchOperation | ReadOperation | HeadOperation | DeleteOperation | WaitOperation | SetOperation | AssertOperation | ServerAppendOperation | AwaitOperation | InjectErrorOperation | ClearErrorsOperation | SetDynamicHeaderOperation | SetDynamicParamOperation | ClearDynamicOperation | ValidateOperation;
489
+ type TestOperation = CreateOperation | ConnectOperation | AppendOperation | AppendBatchOperation | IdempotentAppendOperation | IdempotentAppendBatchOperation | IdempotentCloseOperation | IdempotentDetachOperation | ReadOperation | HeadOperation | DeleteOperation | CloseOperation | ServerCloseOperation | WaitOperation | SetOperation | AssertOperation | ServerAppendOperation | AwaitOperation | InjectErrorOperation | ClearErrorsOperation | SetDynamicHeaderOperation | SetDynamicParamOperation | ClearDynamicOperation | ValidateOperation;
416
490
  /**
417
491
  * Base expectation fields.
418
492
  */
@@ -478,6 +552,8 @@ interface ReadExpectation extends BaseExpectation {
478
552
  maxChunks?: number;
479
553
  /** Should be up-to-date after read */
480
554
  upToDate?: boolean;
555
+ /** Whether the stream has been permanently closed */
556
+ streamClosed?: boolean;
481
557
  /** Store final offset */
482
558
  storeOffsetAs?: string;
483
559
  /** Store all data concatenated */
@@ -493,10 +569,22 @@ interface HeadExpectation extends BaseExpectation {
493
569
  contentType?: string;
494
570
  /** Should have an offset */
495
571
  hasOffset?: boolean;
572
+ /** Whether the stream has been permanently closed */
573
+ streamClosed?: boolean;
496
574
  }
497
575
  interface DeleteExpectation extends BaseExpectation {
498
576
  status?: 200 | 204 | 404 | number;
499
577
  }
578
+ interface CloseExpectation extends BaseExpectation {
579
+ /** Expected final offset after closing */
580
+ finalOffset?: string;
581
+ }
582
+ interface ServerCloseExpectation {
583
+ /** Expected HTTP status code */
584
+ status?: number;
585
+ /** Expected final offset after closing */
586
+ finalOffset?: string;
587
+ }
500
588
  /**
501
589
  * Load all test suites from a directory.
502
590
  */
@@ -667,4 +755,4 @@ interface BenchmarkSummary {
667
755
  declare function runBenchmarks(options: BenchmarkRunnerOptions): Promise<BenchmarkSummary>;
668
756
 
669
757
  //#endregion
670
- export { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkCriteria, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkRunnerOptions, BenchmarkScenario, BenchmarkScenarioConfig, BenchmarkStats, BenchmarkSummary, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, ClientFeature, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, RunSummary, RunnerOptions, ScenarioContext, ScenarioResult, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCase, TestCommand, TestOperation, TestResult, TestRunResult, TestSuite, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, allScenarios, calculateStats, countTests, decodeBase64, encodeBase64, filterByCategory, formatStats, getScenarioById, getScenariosByCategory, loadEmbeddedTestSuites, loadTestSuites, parseCommand, parseResult, runBenchmarks, runConformanceTests, scenariosByCategory, serializeCommand, serializeResult };
758
+ export { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkCriteria, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkRunnerOptions, BenchmarkScenario, BenchmarkScenarioConfig, BenchmarkStats, BenchmarkSummary, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, ClientFeature, CloseCommand, CloseResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, IdempotentCloseCommand, IdempotentCloseResult, IdempotentDetachCommand, IdempotentDetachResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, RunSummary, RunnerOptions, ScenarioContext, ScenarioResult, ServerCloseCommand, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCase, TestCommand, TestOperation, TestResult, TestRunResult, TestSuite, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, allScenarios, calculateStats, countTests, decodeBase64, encodeBase64, filterByCategory, formatStats, getScenarioById, getScenariosByCategory, loadEmbeddedTestSuites, loadTestSuites, parseCommand, parseResult, runBenchmarks, runConformanceTests, scenariosByCategory, serializeCommand, serializeResult };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkStats, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes$1 as ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCommand, TestResult, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, calculateStats$1 as calculateStats, decodeBase64$1 as decodeBase64, encodeBase64$1 as encodeBase64, formatStats$1 as formatStats, parseCommand$1 as parseCommand, parseResult$1 as parseResult, serializeCommand$1 as serializeCommand, serializeResult$1 as serializeResult } from "./protocol-JuFzdV5x.js";
1
+ import { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkStats, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, CloseCommand, CloseResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes$1 as ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, IdempotentCloseCommand, IdempotentCloseResult, IdempotentDetachCommand, IdempotentDetachResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, ServerCloseCommand, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCommand, TestResult, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, calculateStats$1 as calculateStats, decodeBase64$1 as decodeBase64, encodeBase64$1 as encodeBase64, formatStats$1 as formatStats, parseCommand$1 as parseCommand, parseResult$1 as parseResult, serializeCommand$1 as serializeCommand, serializeResult$1 as serializeResult } from "./protocol-9WN0gRRQ.js";
2
2
 
3
3
  //#region src/test-cases.d.ts
4
4
  interface TestSuite {
@@ -61,6 +61,10 @@ interface CreateOperation {
61
61
  expiresAt?: string;
62
62
  /** Custom headers */
63
63
  headers?: Record<string, string>;
64
+ /** Create stream in closed state */
65
+ closed?: boolean;
66
+ /** Initial body data to include on creation */
67
+ data?: string;
64
68
  /** Expected result */
65
69
  expect?: CreateExpectation;
66
70
  }
@@ -168,6 +172,49 @@ interface IdempotentAppendBatchExpectation extends BaseExpectation {
168
172
  allSucceed?: boolean;
169
173
  }
170
174
  /**
175
+ * Close a stream via IdempotentProducer (uses producer headers for idempotency).
176
+ */
177
+ interface IdempotentCloseOperation {
178
+ action: `idempotent-close`;
179
+ path: string;
180
+ /** Producer ID */
181
+ producerId: string;
182
+ /** Producer epoch */
183
+ epoch?: number;
184
+ /** Optional final message to append atomically with close */
185
+ data?: string;
186
+ /** Auto-claim epoch on 403 */
187
+ autoClaim?: boolean;
188
+ headers?: Record<string, string>;
189
+ expect?: IdempotentCloseExpectation;
190
+ }
191
+ /**
192
+ * Expectation for idempotent-close operation.
193
+ */
194
+ interface IdempotentCloseExpectation extends BaseExpectation {
195
+ /** Store the final offset */
196
+ storeOffsetAs?: string;
197
+ /** Expected finalOffset */
198
+ finalOffset?: string;
199
+ }
200
+ /**
201
+ * Detach an IdempotentProducer (stop without closing stream).
202
+ */
203
+ interface IdempotentDetachOperation {
204
+ action: `idempotent-detach`;
205
+ path: string;
206
+ /** Producer ID */
207
+ producerId: string;
208
+ /** Producer epoch */
209
+ epoch?: number;
210
+ headers?: Record<string, string>;
211
+ expect?: IdempotentDetachExpectation;
212
+ }
213
+ /**
214
+ * Expectation for idempotent-detach operation.
215
+ */
216
+ interface IdempotentDetachExpectation extends BaseExpectation {}
217
+ /**
171
218
  * Read from a stream.
172
219
  */
173
220
  interface ReadOperation {
@@ -209,6 +256,33 @@ interface DeleteOperation {
209
256
  expect?: DeleteExpectation;
210
257
  }
211
258
  /**
259
+ * Close a stream (no more appends allowed).
260
+ */
261
+ interface CloseOperation {
262
+ action: `close`;
263
+ path: string;
264
+ /** Optional final message to append */
265
+ data?: string;
266
+ /** Content type for the final message */
267
+ contentType?: string;
268
+ headers?: Record<string, string>;
269
+ expect?: CloseExpectation;
270
+ }
271
+ /**
272
+ * Close a stream via direct HTTP (bypasses client adapter).
273
+ * Used for testing server-side stream closure behavior.
274
+ */
275
+ interface ServerCloseOperation {
276
+ action: `server-close`;
277
+ path: string;
278
+ /** Optional body data */
279
+ data?: string;
280
+ /** Content type for the body */
281
+ contentType?: string;
282
+ headers?: Record<string, string>;
283
+ expect?: ServerCloseExpectation;
284
+ }
285
+ /**
212
286
  * Wait for a duration (for timing-sensitive tests).
213
287
  */
214
288
  interface WaitOperation {
@@ -412,7 +486,7 @@ interface ValidateExpectation {
412
486
  /**
413
487
  * All possible test operations.
414
488
  */
415
- type TestOperation = CreateOperation | ConnectOperation | AppendOperation | AppendBatchOperation | IdempotentAppendOperation | IdempotentAppendBatchOperation | ReadOperation | HeadOperation | DeleteOperation | WaitOperation | SetOperation | AssertOperation | ServerAppendOperation | AwaitOperation | InjectErrorOperation | ClearErrorsOperation | SetDynamicHeaderOperation | SetDynamicParamOperation | ClearDynamicOperation | ValidateOperation;
489
+ type TestOperation = CreateOperation | ConnectOperation | AppendOperation | AppendBatchOperation | IdempotentAppendOperation | IdempotentAppendBatchOperation | IdempotentCloseOperation | IdempotentDetachOperation | ReadOperation | HeadOperation | DeleteOperation | CloseOperation | ServerCloseOperation | WaitOperation | SetOperation | AssertOperation | ServerAppendOperation | AwaitOperation | InjectErrorOperation | ClearErrorsOperation | SetDynamicHeaderOperation | SetDynamicParamOperation | ClearDynamicOperation | ValidateOperation;
416
490
  /**
417
491
  * Base expectation fields.
418
492
  */
@@ -478,6 +552,8 @@ interface ReadExpectation extends BaseExpectation {
478
552
  maxChunks?: number;
479
553
  /** Should be up-to-date after read */
480
554
  upToDate?: boolean;
555
+ /** Whether the stream has been permanently closed */
556
+ streamClosed?: boolean;
481
557
  /** Store final offset */
482
558
  storeOffsetAs?: string;
483
559
  /** Store all data concatenated */
@@ -493,10 +569,22 @@ interface HeadExpectation extends BaseExpectation {
493
569
  contentType?: string;
494
570
  /** Should have an offset */
495
571
  hasOffset?: boolean;
572
+ /** Whether the stream has been permanently closed */
573
+ streamClosed?: boolean;
496
574
  }
497
575
  interface DeleteExpectation extends BaseExpectation {
498
576
  status?: 200 | 204 | 404 | number;
499
577
  }
578
+ interface CloseExpectation extends BaseExpectation {
579
+ /** Expected final offset after closing */
580
+ finalOffset?: string;
581
+ }
582
+ interface ServerCloseExpectation {
583
+ /** Expected HTTP status code */
584
+ status?: number;
585
+ /** Expected final offset after closing */
586
+ finalOffset?: string;
587
+ }
500
588
  /**
501
589
  * Load all test suites from a directory.
502
590
  */
@@ -667,4 +755,4 @@ interface BenchmarkSummary {
667
755
  declare function runBenchmarks(options: BenchmarkRunnerOptions): Promise<BenchmarkSummary>;
668
756
 
669
757
  //#endregion
670
- export { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkCriteria, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkRunnerOptions, BenchmarkScenario, BenchmarkScenarioConfig, BenchmarkStats, BenchmarkSummary, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, ClientFeature, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, RunSummary, RunnerOptions, ScenarioContext, ScenarioResult, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCase, TestCommand, TestOperation, TestResult, TestRunResult, TestSuite, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, allScenarios, calculateStats, countTests, decodeBase64, encodeBase64, filterByCategory, formatStats, getScenarioById, getScenariosByCategory, loadEmbeddedTestSuites, loadTestSuites, parseCommand, parseResult, runBenchmarks, runConformanceTests, scenariosByCategory, serializeCommand, serializeResult };
758
+ export { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkCriteria, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkRunnerOptions, BenchmarkScenario, BenchmarkScenarioConfig, BenchmarkStats, BenchmarkSummary, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, ClientFeature, CloseCommand, CloseResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, IdempotentCloseCommand, IdempotentCloseResult, IdempotentDetachCommand, IdempotentDetachResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, RunSummary, RunnerOptions, ScenarioContext, ScenarioResult, ServerCloseCommand, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCase, TestCommand, TestOperation, TestResult, TestRunResult, TestSuite, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, allScenarios, calculateStats, countTests, decodeBase64, encodeBase64, filterByCategory, formatStats, getScenarioById, getScenariosByCategory, loadEmbeddedTestSuites, loadTestSuites, parseCommand, parseResult, runBenchmarks, runConformanceTests, scenariosByCategory, serializeCommand, serializeResult };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ErrorCodes, calculateStats, decodeBase64, encodeBase64, formatStats, parseCommand, parseResult, serializeCommand, serializeResult } from "./protocol-1p0soayz.js";
2
- import { allScenarios, countTests, filterByCategory, getScenarioById, getScenariosByCategory, loadEmbeddedTestSuites, loadTestSuites, runBenchmarks, runConformanceTests, scenariosByCategory } from "./benchmark-runner-81waaCzs.js";
1
+ import { ErrorCodes, calculateStats, decodeBase64, encodeBase64, formatStats, parseCommand, parseResult, serializeCommand, serializeResult } from "./protocol-BnqUAMKe.js";
2
+ import { allScenarios, countTests, filterByCategory, getScenarioById, getScenariosByCategory, loadEmbeddedTestSuites, loadTestSuites, runBenchmarks, runConformanceTests, scenariosByCategory } from "./benchmark-runner-IGT51RTF.js";
3
3
 
4
4
  export { ErrorCodes, allScenarios, calculateStats, countTests, decodeBase64, encodeBase64, filterByCategory, formatStats, getScenarioById, getScenariosByCategory, loadEmbeddedTestSuites, loadTestSuites, parseCommand, parseResult, runBenchmarks, runConformanceTests, scenariosByCategory, serializeCommand, serializeResult };
@@ -36,6 +36,10 @@ interface CreateCommand {
36
36
  expiresAt?: string;
37
37
  /** Custom headers to include */
38
38
  headers?: Record<string, string>;
39
+ /** Create the stream in closed state */
40
+ closed?: boolean;
41
+ /** Initial body data to include on creation */
42
+ data?: string;
39
43
  }
40
44
  /**
41
45
  * Connect to an existing stream without creating it.
@@ -103,6 +107,36 @@ interface IdempotentAppendBatchCommand {
103
107
  headers?: Record<string, string>;
104
108
  }
105
109
  /**
110
+ * Close a stream via IdempotentProducer (uses producer headers for idempotency).
111
+ */
112
+ interface IdempotentCloseCommand {
113
+ type: `idempotent-close`;
114
+ path: string;
115
+ /** Producer ID */
116
+ producerId: string;
117
+ /** Producer epoch */
118
+ epoch: number;
119
+ /** Optional final message to append atomically with close */
120
+ data?: string;
121
+ /** Auto-claim epoch on 403 */
122
+ autoClaim: boolean;
123
+ /** Custom headers to include */
124
+ headers?: Record<string, string>;
125
+ }
126
+ /**
127
+ * Detach an IdempotentProducer (stop without closing stream).
128
+ */
129
+ interface IdempotentDetachCommand {
130
+ type: `idempotent-detach`;
131
+ path: string;
132
+ /** Producer ID */
133
+ producerId: string;
134
+ /** Producer epoch */
135
+ epoch: number;
136
+ /** Custom headers to include */
137
+ headers?: Record<string, string>;
138
+ }
139
+ /**
106
140
  * Read from a stream (GET request).
107
141
  */
108
142
  interface ReadCommand {
@@ -138,6 +172,33 @@ interface DeleteCommand {
138
172
  headers?: Record<string, string>;
139
173
  }
140
174
  /**
175
+ * Close a stream (no more appends allowed).
176
+ */
177
+ interface CloseCommand {
178
+ type: `close`;
179
+ /** Stream path */
180
+ path: string;
181
+ /** Optional final message to append */
182
+ data?: string;
183
+ /** Content type for the final message */
184
+ contentType?: string;
185
+ }
186
+ /**
187
+ * Close a stream via direct HTTP (bypasses client adapter).
188
+ * Used for testing server-side stream closure behavior.
189
+ */
190
+ interface ServerCloseCommand {
191
+ type: `server-close`;
192
+ /** Stream path */
193
+ path: string;
194
+ /** Whether stream should be closed (always true for this command) */
195
+ streamClosed: true;
196
+ /** Optional body data */
197
+ data?: string;
198
+ /** Content type for the body */
199
+ contentType?: string;
200
+ }
201
+ /**
141
202
  * Shutdown the client adapter gracefully.
142
203
  */
143
204
  interface ShutdownCommand {
@@ -280,7 +341,7 @@ interface BenchmarkThroughputReadOp {
280
341
  /**
281
342
  * All possible commands from test runner to client.
282
343
  */
283
- type TestCommand = InitCommand | CreateCommand | ConnectCommand | AppendCommand | IdempotentAppendCommand | IdempotentAppendBatchCommand | ReadCommand | HeadCommand | DeleteCommand | ShutdownCommand | SetDynamicHeaderCommand | SetDynamicParamCommand | ClearDynamicCommand | BenchmarkCommand | ValidateCommand;
344
+ type TestCommand = InitCommand | CreateCommand | ConnectCommand | AppendCommand | IdempotentAppendCommand | IdempotentAppendBatchCommand | IdempotentCloseCommand | IdempotentDetachCommand | ReadCommand | HeadCommand | DeleteCommand | CloseCommand | ServerCloseCommand | ShutdownCommand | SetDynamicHeaderCommand | SetDynamicParamCommand | ClearDynamicCommand | BenchmarkCommand | ValidateCommand;
284
345
  /**
285
346
  * Successful initialization result.
286
347
  */
@@ -387,6 +448,24 @@ interface IdempotentAppendBatchResult {
387
448
  producerSeq?: number;
388
449
  }
389
450
  /**
451
+ * Successful idempotent-close result.
452
+ */
453
+ interface IdempotentCloseResult {
454
+ type: `idempotent-close`;
455
+ success: true;
456
+ status: number;
457
+ /** Final stream offset after close */
458
+ finalOffset?: string;
459
+ }
460
+ /**
461
+ * Successful idempotent-detach result.
462
+ */
463
+ interface IdempotentDetachResult {
464
+ type: `idempotent-detach`;
465
+ success: true;
466
+ status: number;
467
+ }
468
+ /**
390
469
  * A chunk of data read from the stream.
391
470
  */
392
471
  interface ReadChunk {
@@ -410,6 +489,8 @@ interface ReadResult {
410
489
  offset?: string;
411
490
  /** Whether stream is up-to-date (caught up to head) */
412
491
  upToDate?: boolean;
492
+ /** Whether the stream has been permanently closed (no more appends) */
493
+ streamClosed?: boolean;
413
494
  /** Cursor value if provided */
414
495
  cursor?: string;
415
496
  /** Response headers */
@@ -434,6 +515,8 @@ interface HeadResult {
434
515
  ttlSeconds?: number;
435
516
  /** Absolute expiry (ISO 8601) */
436
517
  expiresAt?: string;
518
+ /** Whether the stream has been permanently closed (no more appends) */
519
+ streamClosed?: boolean;
437
520
  headers?: Record<string, string>;
438
521
  }
439
522
  /**
@@ -446,6 +529,15 @@ interface DeleteResult {
446
529
  headers?: Record<string, string>;
447
530
  }
448
531
  /**
532
+ * Successful close result.
533
+ */
534
+ interface CloseResult {
535
+ type: `close`;
536
+ success: true;
537
+ /** Final offset after closing (may include final message) */
538
+ finalOffset: string;
539
+ }
540
+ /**
449
541
  * Successful shutdown result.
450
542
  */
451
543
  interface ShutdownResult {
@@ -521,7 +613,7 @@ interface ErrorResult {
521
613
  /**
522
614
  * All possible results from client to test runner.
523
615
  */
524
- type TestResult = InitResult | CreateResult | ConnectResult | AppendResult | IdempotentAppendResult | IdempotentAppendBatchResult | ReadResult | HeadResult | DeleteResult | ShutdownResult | SetDynamicHeaderResult | SetDynamicParamResult | ClearDynamicResult | ValidateResult | BenchmarkResult | ErrorResult;
616
+ type TestResult = InitResult | CreateResult | ConnectResult | AppendResult | IdempotentAppendResult | IdempotentAppendBatchResult | IdempotentCloseResult | IdempotentDetachResult | ReadResult | HeadResult | DeleteResult | CloseResult | ShutdownResult | SetDynamicHeaderResult | SetDynamicParamResult | ClearDynamicResult | ValidateResult | BenchmarkResult | ErrorResult;
525
617
  /**
526
618
  * Parse a JSON line into a TestCommand.
527
619
  */
@@ -560,6 +652,8 @@ declare const ErrorCodes: {
560
652
  readonly NOT_FOUND: "NOT_FOUND";
561
653
  /** Sequence number conflict (409) */
562
654
  readonly SEQUENCE_CONFLICT: "SEQUENCE_CONFLICT";
655
+ /** Stream is closed (409 with Stream-Closed header) */
656
+ readonly STREAM_CLOSED: "STREAM_CLOSED";
563
657
  /** Invalid offset format */
564
658
  readonly INVALID_OFFSET: "INVALID_OFFSET";
565
659
  /** Server returned unexpected status */
@@ -607,4 +701,4 @@ declare function calculateStats(durationsNs: Array<bigint>): BenchmarkStats;
607
701
  * Format a BenchmarkStats object for display.
608
702
  */
609
703
  declare function formatStats(stats: BenchmarkStats, unit?: string): Record<string, string>; //#endregion
610
- export { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkStats, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCommand, TestResult, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, calculateStats, decodeBase64, encodeBase64, formatStats, parseCommand, parseResult, serializeCommand, serializeResult };
704
+ export { AppendCommand, AppendResult, BenchmarkAppendOp, BenchmarkCommand, BenchmarkCreateOp, BenchmarkOperation, BenchmarkReadOp, BenchmarkResult, BenchmarkRoundtripOp, BenchmarkStats, BenchmarkThroughputAppendOp, BenchmarkThroughputReadOp, ClearDynamicCommand, ClearDynamicResult, CloseCommand, CloseResult, ConnectCommand, ConnectResult, CreateCommand, CreateResult, DeleteCommand, DeleteResult, ErrorCode, ErrorCodes as ErrorCodes$1, ErrorResult, HeadCommand, HeadResult, IdempotentAppendBatchCommand, IdempotentAppendBatchResult, IdempotentAppendCommand, IdempotentAppendResult, IdempotentCloseCommand, IdempotentCloseResult, IdempotentDetachCommand, IdempotentDetachResult, InitCommand, InitResult, ReadChunk, ReadCommand, ReadResult, ServerCloseCommand, SetDynamicHeaderCommand, SetDynamicHeaderResult, SetDynamicParamCommand, SetDynamicParamResult, ShutdownCommand, ShutdownResult, TestCommand, TestResult, ValidateCommand, ValidateIdempotentProducer, ValidateResult, ValidateRetryOptions, ValidateTarget, calculateStats as calculateStats$1, decodeBase64 as decodeBase64$1, encodeBase64 as encodeBase64$1, formatStats as formatStats$1, parseCommand as parseCommand$1, parseResult as parseResult$1, serializeCommand as serializeCommand$1, serializeResult as serializeResult$1 };
@@ -44,6 +44,7 @@ const ErrorCodes = {
44
44
  CONFLICT: `CONFLICT`,
45
45
  NOT_FOUND: `NOT_FOUND`,
46
46
  SEQUENCE_CONFLICT: `SEQUENCE_CONFLICT`,
47
+ STREAM_CLOSED: `STREAM_CLOSED`,
47
48
  INVALID_OFFSET: `INVALID_OFFSET`,
48
49
  UNEXPECTED_STATUS: `UNEXPECTED_STATUS`,
49
50
  PARSE_ERROR: `PARSE_ERROR`,