From 59a62f401009d9d3b6c579929145fd619e71aa15 Mon Sep 17 00:00:00 2001 From: Stefano Azzalini <73150750+stfnzl@users.noreply.github.com> Date: Mon, 15 Apr 2024 16:04:04 +0200 Subject: [PATCH] Add Redpanda module (#743) --- docs/modules/redpanda.md | 32 ++++ mkdocs.yml | 1 + package-lock.json | 151 +++++++++++++++++- packages/modules/redpanda/jest.config.ts | 11 ++ packages/modules/redpanda/package.json | 39 +++++ packages/modules/redpanda/src/bootstrap.yaml | 7 + packages/modules/redpanda/src/index.ts | 1 + .../redpanda/src/redpanda-container.test.ts | 93 +++++++++++ .../redpanda/src/redpanda-container.ts | 108 +++++++++++++ .../modules/redpanda/src/redpanda.yaml.hbs | 61 +++++++ packages/modules/redpanda/tsconfig.build.json | 13 ++ packages/modules/redpanda/tsconfig.json | 21 +++ 12 files changed, 536 insertions(+), 2 deletions(-) create mode 100644 docs/modules/redpanda.md create mode 100644 packages/modules/redpanda/jest.config.ts create mode 100644 packages/modules/redpanda/package.json create mode 100644 packages/modules/redpanda/src/bootstrap.yaml create mode 100644 packages/modules/redpanda/src/index.ts create mode 100644 packages/modules/redpanda/src/redpanda-container.test.ts create mode 100644 packages/modules/redpanda/src/redpanda-container.ts create mode 100644 packages/modules/redpanda/src/redpanda.yaml.hbs create mode 100644 packages/modules/redpanda/tsconfig.build.json create mode 100644 packages/modules/redpanda/tsconfig.json diff --git a/docs/modules/redpanda.md b/docs/modules/redpanda.md new file mode 100644 index 000000000..ae452a264 --- /dev/null +++ b/docs/modules/redpanda.md @@ -0,0 +1,32 @@ +# Redpanda + +Testcontainers can be used to automatically instantiate and manage [Redpanda](https://redpanda.com/) containers. +More precisely Testcontainers uses the official Docker images for [Redpanda](https://hub.docker.com/r/redpandadata/redpanda) + +!!! note + This module uses features provided in `docker.redpanda.com/redpandadata/redpanda`. + +## Install + + +```bash +npm install @testcontainers/redpanda --save-dev +``` + +## Example + + +[Connect:](../../packages/modules/redpanda/src/redpanda-container.test.ts) inside_block:connectToKafka + + + +[Schema registry:](../../packages/modules/redpanda/src/redpanda-container.test.ts) inside_block:connectToSchemaRegistry + + + +[Admin APIs:](../../packages/modules/redpanda/src/redpanda-container.test.ts) inside_block:connectToAdmin + + + +[Rest Proxy:](../../packages/modules/redpanda/src/redpanda-container.test.ts) inside_block:connectToRestProxy + diff --git a/mkdocs.yml b/mkdocs.yml index 7a6e8c4e4..d664eb740 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -58,6 +58,7 @@ nav: - PostgreSQL: modules/postgresql.md - Qdrant: modules/qdrant.md - Redis: modules/redis.md + - Redpanda: modules/redpanda.md - Selenium: modules/selenium.md - Weaviate: modules/weaviate.md - Configuration: configuration.md diff --git a/package-lock.json b/package-lock.json index 12ca52b3e..ad80aa0cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4873,6 +4873,10 @@ "resolved": "packages/modules/redis", "link": true }, + "node_modules/@testcontainers/redpanda": { + "resolved": "packages/modules/redpanda", + "link": true + }, "node_modules/@testcontainers/selenium": { "resolved": "packages/modules/selenium", "link": true @@ -7571,6 +7575,15 @@ "node": ">=4" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -8589,6 +8602,29 @@ "bser": "2.1.1" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -8794,6 +8830,18 @@ "node": ">= 14.17" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/fp-and-or": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/fp-and-or/-/fp-and-or-0.1.4.tgz", @@ -10200,6 +10248,26 @@ "node": ">=14.0.0" } }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -13019,7 +13087,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13580,6 +13647,11 @@ "node": ">= 0.6" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, "node_modules/neo4j-driver": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/neo4j-driver/-/neo4j-driver-5.17.0.tgz", @@ -13665,6 +13737,25 @@ "integrity": "sha512-ucQW+SbYCUPfprvmzBsnjT034IGRB2XK8rRc78BgjNKhTdFKgAwAmgW704bKIBmcYW48it0Gkjpkd39Azrwquw==", "dev": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -16465,7 +16556,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -17659,6 +17749,18 @@ "node": ">=4.2.0" } }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -17930,6 +18032,15 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -18084,6 +18195,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -18582,6 +18698,37 @@ "redis": "^4.6.13" } }, + "packages/modules/redpanda": { + "name": "@testcontainers/redpanda", + "version": "10.8.0", + "license": "MIT", + "dependencies": { + "handlebars": "^4.7.8", + "testcontainers": "^10.8.0" + }, + "devDependencies": { + "kafkajs": "^2.2.4", + "node-fetch": "^3.3.2" + } + }, + "packages/modules/redpanda/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "packages/modules/selenium": { "name": "@testcontainers/selenium", "version": "10.8.2", diff --git a/packages/modules/redpanda/jest.config.ts b/packages/modules/redpanda/jest.config.ts new file mode 100644 index 000000000..1f677baaf --- /dev/null +++ b/packages/modules/redpanda/jest.config.ts @@ -0,0 +1,11 @@ +import type { Config } from "jest"; +import * as path from "path"; + +const config: Config = { + preset: "ts-jest", + moduleNameMapper: { + "^testcontainers$": path.resolve(__dirname, "../../testcontainers/src"), + }, +}; + +export default config; diff --git a/packages/modules/redpanda/package.json b/packages/modules/redpanda/package.json new file mode 100644 index 000000000..2aa1ff907 --- /dev/null +++ b/packages/modules/redpanda/package.json @@ -0,0 +1,39 @@ +{ + "name": "@testcontainers/redpanda", + "version": "10.8.0", + "license": "MIT", + "keywords": [ + "redpanda", + "testing", + "docker", + "testcontainers" + ], + "description": "Redpanda module for Testcontainers", + "homepage": "https://github.com/testcontainers/testcontainers-node#readme", + "repository": { + "type": "git", + "url": "https://github.com/testcontainers/testcontainers-node" + }, + "bugs": { + "url": "https://github.com/testcontainers/testcontainers-node/issues" + }, + "main": "build/index.js", + "files": [ + "build" + ], + "publishConfig": { + "access": "public" + }, + "scripts": { + "prepack": "shx cp ../../../README.md . && shx cp ../../../LICENSE .", + "build": "tsc --project tsconfig.build.json" + }, + "dependencies": { + "handlebars": "^4.7.8", + "testcontainers": "^10.8.0" + }, + "devDependencies": { + "kafkajs": "^2.2.4", + "node-fetch": "^3.3.2" + } +} diff --git a/packages/modules/redpanda/src/bootstrap.yaml b/packages/modules/redpanda/src/bootstrap.yaml new file mode 100644 index 000000000..f723e61b1 --- /dev/null +++ b/packages/modules/redpanda/src/bootstrap.yaml @@ -0,0 +1,7 @@ +# Injected by testcontainers +# This file contains cluster properties which will only be considered when +# starting the cluster for the first time. Afterwards, you can configure cluster +# properties via the Redpanda Admi n API. + +kafka_enable_authorization: false +auto_create_topics_enabled: true diff --git a/packages/modules/redpanda/src/index.ts b/packages/modules/redpanda/src/index.ts new file mode 100644 index 000000000..606f65951 --- /dev/null +++ b/packages/modules/redpanda/src/index.ts @@ -0,0 +1 @@ +export { RedpandaContainer, StartedRedpandaContainer } from "./redpanda-container"; diff --git a/packages/modules/redpanda/src/redpanda-container.test.ts b/packages/modules/redpanda/src/redpanda-container.test.ts new file mode 100644 index 000000000..c11106053 --- /dev/null +++ b/packages/modules/redpanda/src/redpanda-container.test.ts @@ -0,0 +1,93 @@ +import { Kafka, KafkaConfig, logLevel } from "kafkajs"; +import { RedpandaContainer, StartedRedpandaContainer } from "./redpanda-container"; + +describe("RedpandaContainer", () => { + jest.setTimeout(240_000); + + // connectToKafka { + it("should connect", async () => { + const redpandaContainer = await new RedpandaContainer().start(); + await testPubSub(redpandaContainer); + await redpandaContainer.stop(); + }); + // } + + // connectToSchemaRegistry { + it("should connect to schema registry", async () => { + const redpandaContainer = await new RedpandaContainer().start(); + const schemaRegistryUrl = redpandaContainer.getSchemaRegistryAddress(); + + const response = await fetch(`${schemaRegistryUrl}/subjects`, { + method: "GET", + headers: { + "Content-Type": "application/vnd.schemaregistry.v1+json", + }, + }); + + expect(response.status).toBe(200); + + await redpandaContainer.stop(); + }); + // } + + // connectToAdmin { + it("should connect to admin", async () => { + const redpandaContainer = await new RedpandaContainer().start(); + const adminUrl = `${redpandaContainer.getAdminAddress()}/v1`; + + const response = await fetch(adminUrl); + + expect(response.status).toBe(200); + + await redpandaContainer.stop(); + }); + // } + + // connectToRestProxy { + it("should connect to rest proxy", async () => { + const redpandaContainer = await new RedpandaContainer().start(); + const restProxyUrl = `${redpandaContainer.getRestProxyAddress()}/topics`; + + const response = await fetch(restProxyUrl); + + expect(response.status).toBe(200); + + await redpandaContainer.stop(); + }); + // } + + const testPubSub = async ( + redpandaContainer: StartedRedpandaContainer, + additionalConfig: Partial = {} + ) => { + const kafka = new Kafka({ + logLevel: logLevel.NOTHING, + brokers: [redpandaContainer.getBootstrapServers()], + ...additionalConfig, + }); + + const producer = kafka.producer(); + await producer.connect(); + + const consumer = kafka.consumer({ groupId: "test-group" }); + await consumer.connect(); + + await producer.send({ + topic: "test-topic", + messages: [{ value: "test message" }], + }); + + await consumer.subscribe({ topic: "test-topic", fromBeginning: true }); + + const consumedMessage = await new Promise((resolve) => { + consumer.run({ + eachMessage: async ({ message }) => resolve(message.value?.toString()), + }); + }); + + expect(consumedMessage).toBe("test message"); + + await consumer.disconnect(); + await producer.disconnect(); + }; +}); diff --git a/packages/modules/redpanda/src/redpanda-container.ts b/packages/modules/redpanda/src/redpanda-container.ts new file mode 100644 index 000000000..222a1882c --- /dev/null +++ b/packages/modules/redpanda/src/redpanda-container.ts @@ -0,0 +1,108 @@ +import fs from "fs"; +import path from "path"; +import { compile } from "handlebars"; +import { + AbstractStartedContainer, + BoundPorts, + GenericContainer, + InspectResult, + StartedTestContainer, + Wait, + WaitStrategy, + getContainerRuntimeClient, + waitForContainer, +} from "testcontainers"; + +const REDPANDA_PORT = 9092; +const REDPANDA_ADMIN_PORT = 9644; +const SCHEMA_REGISTRY_PORT = 8081; +const REST_PROXY_PORT = 8082; +const STARTER_SCRIPT = "/testcontainers_start.sh"; +const WAIT_FOR_SCRIPT_MESSAGE = "Waiting for script..."; + +export class RedpandaContainer extends GenericContainer { + private originalWaitinStrategy: WaitStrategy; + + constructor(image = "docker.redpanda.com/redpandadata/redpanda:v23.3.10") { + super(image); + this.withExposedPorts(REDPANDA_PORT, REDPANDA_ADMIN_PORT, SCHEMA_REGISTRY_PORT, REST_PROXY_PORT) + .withUser("root:root") + .withWaitStrategy(Wait.forLogMessage("Successfully started Redpanda!")) + .withCopyFilesToContainer([ + { + source: path.join(__dirname, "bootstrap.yaml"), + target: "/etc/redpanda/.bootstrap.yaml", + }, + ]); + this.originalWaitinStrategy = this.waitStrategy; + } + + public override async start(): Promise { + return new StartedRedpandaContainer(await super.start()); + } + + protected override async beforeContainerCreated(): Promise { + // Change the wait strategy to wait for a log message from a fake starter script + // so that we can put a real starter script in place at that moment + this.originalWaitinStrategy = this.waitStrategy; + this.waitStrategy = Wait.forLogMessage(WAIT_FOR_SCRIPT_MESSAGE); + this.withEntrypoint(["sh"]); + this.withCommand([ + "-c", + `echo '${WAIT_FOR_SCRIPT_MESSAGE}'; while [ ! -f ${STARTER_SCRIPT} ]; do sleep 0.1; done; ${STARTER_SCRIPT}`, + ]); + } + + protected override async containerStarted( + container: StartedTestContainer, + inspectResult: InspectResult + ): Promise { + const command = "#!/bin/bash\nrpk redpanda start --mode dev-container --smp=1 --memory=1G"; + await container.copyContentToContainer([{ content: command, target: STARTER_SCRIPT, mode: 0o777 }]); + await container.copyContentToContainer([ + { + content: this.renderRedpandaFile(container.getHost(), container.getMappedPort(REDPANDA_PORT)), + target: "/etc/redpanda/redpanda.yaml", + }, + ]); + + const client = await getContainerRuntimeClient(); + const dockerContainer = client.container.getById(container.getId()); + const boundPorts = BoundPorts.fromInspectResult(client.info.containerRuntime.hostIps, inspectResult).filter( + this.exposedPorts + ); + await waitForContainer(client, dockerContainer, this.originalWaitinStrategy, boundPorts); + } + + private renderRedpandaFile(host: string, port: number): string { + const template = compile(fs.readFileSync(path.join(__dirname, "redpanda.yaml.hbs"), "utf-8")); + return template({ + kafkaApi: { + advertisedHost: host, + advertisedPort: port, + }, + }); + } +} + +export class StartedRedpandaContainer extends AbstractStartedContainer { + constructor(startedTestContainer: StartedTestContainer) { + super(startedTestContainer); + } + + public getBootstrapServers(): string { + return `${this.getHost()}:${this.getMappedPort(REDPANDA_PORT)}`; + } + + public getSchemaRegistryAddress(): string { + return `http://${this.getHost()}:${this.getMappedPort(SCHEMA_REGISTRY_PORT)}`; + } + + public getAdminAddress(): string { + return `http://${this.getHost()}:${this.getMappedPort(REDPANDA_ADMIN_PORT)}`; + } + + public getRestProxyAddress(): string { + return `http://${this.getHost()}:${this.getMappedPort(REST_PROXY_PORT)}`; + } +} diff --git a/packages/modules/redpanda/src/redpanda.yaml.hbs b/packages/modules/redpanda/src/redpanda.yaml.hbs new file mode 100644 index 000000000..67cb26236 --- /dev/null +++ b/packages/modules/redpanda/src/redpanda.yaml.hbs @@ -0,0 +1,61 @@ +# Injected by testcontainers + +redpanda: + admin: + address: 0.0.0.0 + port: 9644 + + kafka_api: + - address: 0.0.0.0 + name: external + port: 9092 + authentication_method: none + + # This listener is required for the schema registry client. The schema + # registry client connects via an advertised listener like a normal Kafka + # client would do. It can't use the other listener because the mapped + # port is not accessible from within the Redpanda container. + - address: 0.0.0.0 + name: internal + port: 9093 + authentication_method: none + + advertised_kafka_api: + - address: {{ kafkaApi.advertisedHost }} + name: external + port: {{ kafkaApi.advertisedPort }} + - address: 127.0.0.1 + name: internal + port: 9093 + +schema_registry: + schema_registry_api: + - address: "0.0.0.0" + name: main + port: 8081 + authentication_method: none + +schema_registry_client: + brokers: + - address: localhost + port: 9093 + +pandaproxy: + pandaproxy_api: + - address: 0.0.0.0 + port: 8082 + name: proxy-internal + advertised_pandaproxy_api: + - address: 127.0.0.1 + port: 8082 + name: proxy-internal + +pandaproxy_client: + brokers: + - address: localhost + port: 9093 + +rpk: + kafka_api: + brokers: + - localhost:9093 diff --git a/packages/modules/redpanda/tsconfig.build.json b/packages/modules/redpanda/tsconfig.build.json new file mode 100644 index 000000000..0222f6ff1 --- /dev/null +++ b/packages/modules/redpanda/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "exclude": [ + "build", + "jest.config.ts", + "src/**/*.test.ts" + ], + "references": [ + { + "path": "../../testcontainers" + } + ] +} \ No newline at end of file diff --git a/packages/modules/redpanda/tsconfig.json b/packages/modules/redpanda/tsconfig.json new file mode 100644 index 000000000..39b165817 --- /dev/null +++ b/packages/modules/redpanda/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "build", + "paths": { + "testcontainers": [ + "../../testcontainers/src" + ] + } + }, + "exclude": [ + "build", + "jest.config.ts" + ], + "references": [ + { + "path": "../../testcontainers" + } + ] +} \ No newline at end of file