From 5ddebbb9c147018ce24286b514478d88febbc78d Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 4 Jul 2025 13:58:03 +0200 Subject: [PATCH 1/4] use esdb when the image contains 'eventstore' --- docs/modules/kurrentdb.md | 15 ++++ .../kurrentdb/src/kurrentdb-container.test.ts | 74 +++++++++++++++++++ .../kurrentdb/src/kurrentdb-container.ts | 17 ++++- 3 files changed, 103 insertions(+), 3 deletions(-) diff --git a/docs/modules/kurrentdb.md b/docs/modules/kurrentdb.md index d016770ef..97a7bd90c 100644 --- a/docs/modules/kurrentdb.md +++ b/docs/modules/kurrentdb.md @@ -17,3 +17,18 @@ npm install @testcontainers/kurrentdb --save-dev [Subscribe to standard projection:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:usingStandardProjections + +## Rebranding and protocol + +When EventStoreDB rebranded to KurrentDB, they've also changed the protocol name in the connection string. +Historically, `esdb://` was the protocol, but now it is `kurrentdb://`. + +This package's `.getConnectionString()` will choose the protocol to use based on the provided image name. + + +[By default, it uses `kurrentdb://`:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:protocolUsedByDefault + + + +[The package switches to `esdb://` if the provided image contains `eventstore`:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:protocolAdaptsToImageName + \ No newline at end of file diff --git a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts index f8cf0d10a..b7b0430b1 100644 --- a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts +++ b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts @@ -45,6 +45,80 @@ describe("KurrentDbContainer", { timeout: 240_000 }, () => { }); // } + // protocolUsedByDefault { + it("should use the protocol kurrentdb:// by default", async () => { + const container = await new KurrentDbContainer(IMAGE).start(); + const connectionString = container.getConnectionString() + await container.stop() + + expect(connectionString.startsWith("kurrentdb://")).to.equal(true, `${connectionString} does not start with kurrentdb://`) + }) + // } + + // protocolAdaptsToImageName + it("should use the protocol esdb:// if the image name contains 'eventstore'", async () => { + const container = await new KurrentDbContainer('eventstore/eventstore:23.10.7-bookworm-slim') + .withEnvironment({ + EVENTSTORE_CLUSTER_SIZE: "1", + EVENTSTORE_RUN_PROJECTIONS: "All", + EVENTSTORE_START_STANDARD_PROJECTIONS: "true", + EVENTSTORE_INSECURE: "true", + }) + .start(); + + const connectionString = container.getConnectionString() + await container.stop() + + expect(connectionString.startsWith("esdb://")).to.equal(true, `${connectionString} does not start with esdb://`) + }) + // } + + it("should use the protocol esdb:// to read and write", async () => { + const container = await new KurrentDbContainer('eventstore/eventstore:23.10.7-bookworm-slim') + .withEnvironment({ + EVENTSTORE_CLUSTER_SIZE: "1", + EVENTSTORE_RUN_PROJECTIONS: "All", + EVENTSTORE_START_STANDARD_PROJECTIONS: "true", + EVENTSTORE_INSECURE: "true", + }) + .start(); + + + const client = KurrentDBClient.connectionString(container.getConnectionString()); + + await client.appendToStream("User-1", [ + { + contentType: "application/json", + data: { email: "john@foo.local" }, + type: "UserCreated", + id: "28ab6bca-d9ae-418b-a1af-eb65dd653c38", + metadata: { + someMetadata: "bar", + }, + }, + ]); + + expect(await consumeSteamingRead(client.readStream("User-1"))).toEqual([ + expect.objectContaining({ + event: expect.objectContaining({ + data: { + email: "john@foo.local", + }, + id: "28ab6bca-d9ae-418b-a1af-eb65dd653c38", + isJson: true, + metadata: { + someMetadata: "bar", + }, + revision: 0, + streamId: "User-1", + type: "UserCreated", + }), + }), + ]); + + await container.stop(); + }) + // usingStandardProjections { it("should use built-in projections", async () => { const container = await new KurrentDbContainer(IMAGE).start(); diff --git a/packages/modules/kurrentdb/src/kurrentdb-container.ts b/packages/modules/kurrentdb/src/kurrentdb-container.ts index 53b73a237..4538fc7bf 100644 --- a/packages/modules/kurrentdb/src/kurrentdb-container.ts +++ b/packages/modules/kurrentdb/src/kurrentdb-container.ts @@ -1,8 +1,19 @@ -import { AbstractStartedContainer, GenericContainer, Wait } from "testcontainers"; +import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers"; export class StartedKurrentDbContainer extends AbstractStartedContainer { + private readonly image: string + + constructor(started: StartedTestContainer, image: string) { + super(started) + this.image = image + } + getConnectionString(): string { - return `esdb://${this.getHost()}:${this.getFirstMappedPort()}?tls=false`; + const protocol = this.image.includes("eventstore") + ? 'esdb' + : 'kurrentdb' + + return `${protocol}://${this.getHost()}:${this.getFirstMappedPort()}?tls=false`; } } @@ -22,6 +33,6 @@ export class KurrentDbContainer extends GenericContainer { } public override async start(): Promise { - return new StartedKurrentDbContainer(await super.start()); + return new StartedKurrentDbContainer(await super.start(), this.imageName.image); } } From be9d611b3ef5ddaa18aa4a2b2358304f9fca9e04 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 4 Jul 2025 14:12:37 +0200 Subject: [PATCH 2/4] fix a doc example --- docs/modules/kurrentdb.md | 2 +- packages/modules/kurrentdb/src/kurrentdb-container.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/modules/kurrentdb.md b/docs/modules/kurrentdb.md index 97a7bd90c..e986d3187 100644 --- a/docs/modules/kurrentdb.md +++ b/docs/modules/kurrentdb.md @@ -30,5 +30,5 @@ This package's `.getConnectionString()` will choose the protocol to use based on -[The package switches to `esdb://` if the provided image contains `eventstore`:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:protocolAdaptsToImageName +[Switches automatically to `esdb://` if the provided image contains `eventstore`:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:protocolAdaptsToImageName \ No newline at end of file diff --git a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts index b7b0430b1..40aa4ee5e 100644 --- a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts +++ b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts @@ -55,7 +55,7 @@ describe("KurrentDbContainer", { timeout: 240_000 }, () => { }) // } - // protocolAdaptsToImageName + // protocolAdaptsToImageName { it("should use the protocol esdb:// if the image name contains 'eventstore'", async () => { const container = await new KurrentDbContainer('eventstore/eventstore:23.10.7-bookworm-slim') .withEnvironment({ From 9d3c48c4b7629760913674ecd134daa2718d6c62 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 4 Jul 2025 15:36:42 +0200 Subject: [PATCH 3/4] remove esdb:// entirly Take a look at the [PR's comment](https://github.com/testcontainers/testcontainers-node/pull/1051#issuecomment-3036209686) to know why. --- docs/modules/kurrentdb.md | 15 ---- .../kurrentdb/src/kurrentdb-container.test.ts | 74 ------------------- .../kurrentdb/src/kurrentdb-container.ts | 15 +--- 3 files changed, 2 insertions(+), 102 deletions(-) diff --git a/docs/modules/kurrentdb.md b/docs/modules/kurrentdb.md index e986d3187..d016770ef 100644 --- a/docs/modules/kurrentdb.md +++ b/docs/modules/kurrentdb.md @@ -17,18 +17,3 @@ npm install @testcontainers/kurrentdb --save-dev [Subscribe to standard projection:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:usingStandardProjections - -## Rebranding and protocol - -When EventStoreDB rebranded to KurrentDB, they've also changed the protocol name in the connection string. -Historically, `esdb://` was the protocol, but now it is `kurrentdb://`. - -This package's `.getConnectionString()` will choose the protocol to use based on the provided image name. - - -[By default, it uses `kurrentdb://`:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:protocolUsedByDefault - - - -[Switches automatically to `esdb://` if the provided image contains `eventstore`:](../../packages/modules/kurrentdb/src/kurrentdb-container.test.ts) inside_block:protocolAdaptsToImageName - \ No newline at end of file diff --git a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts index 40aa4ee5e..f8cf0d10a 100644 --- a/packages/modules/kurrentdb/src/kurrentdb-container.test.ts +++ b/packages/modules/kurrentdb/src/kurrentdb-container.test.ts @@ -45,80 +45,6 @@ describe("KurrentDbContainer", { timeout: 240_000 }, () => { }); // } - // protocolUsedByDefault { - it("should use the protocol kurrentdb:// by default", async () => { - const container = await new KurrentDbContainer(IMAGE).start(); - const connectionString = container.getConnectionString() - await container.stop() - - expect(connectionString.startsWith("kurrentdb://")).to.equal(true, `${connectionString} does not start with kurrentdb://`) - }) - // } - - // protocolAdaptsToImageName { - it("should use the protocol esdb:// if the image name contains 'eventstore'", async () => { - const container = await new KurrentDbContainer('eventstore/eventstore:23.10.7-bookworm-slim') - .withEnvironment({ - EVENTSTORE_CLUSTER_SIZE: "1", - EVENTSTORE_RUN_PROJECTIONS: "All", - EVENTSTORE_START_STANDARD_PROJECTIONS: "true", - EVENTSTORE_INSECURE: "true", - }) - .start(); - - const connectionString = container.getConnectionString() - await container.stop() - - expect(connectionString.startsWith("esdb://")).to.equal(true, `${connectionString} does not start with esdb://`) - }) - // } - - it("should use the protocol esdb:// to read and write", async () => { - const container = await new KurrentDbContainer('eventstore/eventstore:23.10.7-bookworm-slim') - .withEnvironment({ - EVENTSTORE_CLUSTER_SIZE: "1", - EVENTSTORE_RUN_PROJECTIONS: "All", - EVENTSTORE_START_STANDARD_PROJECTIONS: "true", - EVENTSTORE_INSECURE: "true", - }) - .start(); - - - const client = KurrentDBClient.connectionString(container.getConnectionString()); - - await client.appendToStream("User-1", [ - { - contentType: "application/json", - data: { email: "john@foo.local" }, - type: "UserCreated", - id: "28ab6bca-d9ae-418b-a1af-eb65dd653c38", - metadata: { - someMetadata: "bar", - }, - }, - ]); - - expect(await consumeSteamingRead(client.readStream("User-1"))).toEqual([ - expect.objectContaining({ - event: expect.objectContaining({ - data: { - email: "john@foo.local", - }, - id: "28ab6bca-d9ae-418b-a1af-eb65dd653c38", - isJson: true, - metadata: { - someMetadata: "bar", - }, - revision: 0, - streamId: "User-1", - type: "UserCreated", - }), - }), - ]); - - await container.stop(); - }) - // usingStandardProjections { it("should use built-in projections", async () => { const container = await new KurrentDbContainer(IMAGE).start(); diff --git a/packages/modules/kurrentdb/src/kurrentdb-container.ts b/packages/modules/kurrentdb/src/kurrentdb-container.ts index 4538fc7bf..63e46c931 100644 --- a/packages/modules/kurrentdb/src/kurrentdb-container.ts +++ b/packages/modules/kurrentdb/src/kurrentdb-container.ts @@ -1,19 +1,8 @@ import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers"; export class StartedKurrentDbContainer extends AbstractStartedContainer { - private readonly image: string - - constructor(started: StartedTestContainer, image: string) { - super(started) - this.image = image - } - getConnectionString(): string { - const protocol = this.image.includes("eventstore") - ? 'esdb' - : 'kurrentdb' - - return `${protocol}://${this.getHost()}:${this.getFirstMappedPort()}?tls=false`; + return `kurrentdb://${this.getHost()}:${this.getFirstMappedPort()}?tls=false`; } } @@ -33,6 +22,6 @@ export class KurrentDbContainer extends GenericContainer { } public override async start(): Promise { - return new StartedKurrentDbContainer(await super.start(), this.imageName.image); + return new StartedKurrentDbContainer(await super.start()); } } From 74f174c13f26f83dee5bc5772e9af2bf7a9202b3 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 4 Jul 2025 15:38:47 +0200 Subject: [PATCH 4/4] remove unused import --- packages/modules/kurrentdb/src/kurrentdb-container.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/modules/kurrentdb/src/kurrentdb-container.ts b/packages/modules/kurrentdb/src/kurrentdb-container.ts index 63e46c931..0daefa760 100644 --- a/packages/modules/kurrentdb/src/kurrentdb-container.ts +++ b/packages/modules/kurrentdb/src/kurrentdb-container.ts @@ -1,4 +1,4 @@ -import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers"; +import { AbstractStartedContainer, GenericContainer, Wait } from "testcontainers"; export class StartedKurrentDbContainer extends AbstractStartedContainer { getConnectionString(): string {