rightsize 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +4 -0
  3. package/README.md +255 -0
  4. package/dist/backend-docker/backend.d.ts +53 -0
  5. package/dist/backend-docker/backend.d.ts.map +1 -0
  6. package/dist/backend-docker/backend.js +336 -0
  7. package/dist/backend-docker/backend.js.map +1 -0
  8. package/dist/backend-docker/client.d.ts +82 -0
  9. package/dist/backend-docker/client.d.ts.map +1 -0
  10. package/dist/backend-docker/client.js +190 -0
  11. package/dist/backend-docker/client.js.map +1 -0
  12. package/dist/backend-docker/frames.d.ts +44 -0
  13. package/dist/backend-docker/frames.d.ts.map +1 -0
  14. package/dist/backend-docker/frames.js +105 -0
  15. package/dist/backend-docker/frames.js.map +1 -0
  16. package/dist/backend-docker/index.d.ts +5 -0
  17. package/dist/backend-docker/index.d.ts.map +1 -0
  18. package/dist/backend-docker/index.js +20 -0
  19. package/dist/backend-docker/index.js.map +1 -0
  20. package/dist/backend-docker/json.d.ts +13 -0
  21. package/dist/backend-docker/json.d.ts.map +1 -0
  22. package/dist/backend-docker/json.js +47 -0
  23. package/dist/backend-docker/json.js.map +1 -0
  24. package/dist/backend-docker/labels.d.ts +11 -0
  25. package/dist/backend-docker/labels.d.ts.map +1 -0
  26. package/dist/backend-docker/labels.js +13 -0
  27. package/dist/backend-docker/labels.js.map +1 -0
  28. package/dist/backend-docker/port-conflict.d.ts +9 -0
  29. package/dist/backend-docker/port-conflict.d.ts.map +1 -0
  30. package/dist/backend-docker/port-conflict.js +12 -0
  31. package/dist/backend-docker/port-conflict.js.map +1 -0
  32. package/dist/backend-docker/provider.d.ts +22 -0
  33. package/dist/backend-docker/provider.d.ts.map +1 -0
  34. package/dist/backend-docker/provider.js +36 -0
  35. package/dist/backend-docker/provider.js.map +1 -0
  36. package/dist/backend-msb/backend.d.ts +169 -0
  37. package/dist/backend-msb/backend.d.ts.map +1 -0
  38. package/dist/backend-msb/backend.js +664 -0
  39. package/dist/backend-msb/backend.js.map +1 -0
  40. package/dist/backend-msb/commands.d.ts +28 -0
  41. package/dist/backend-msb/commands.d.ts.map +1 -0
  42. package/dist/backend-msb/commands.js +67 -0
  43. package/dist/backend-msb/commands.js.map +1 -0
  44. package/dist/backend-msb/exec-tunnel.d.ts +33 -0
  45. package/dist/backend-msb/exec-tunnel.d.ts.map +1 -0
  46. package/dist/backend-msb/exec-tunnel.js +163 -0
  47. package/dist/backend-msb/exec-tunnel.js.map +1 -0
  48. package/dist/backend-msb/follow-replay.d.ts +14 -0
  49. package/dist/backend-msb/follow-replay.d.ts.map +1 -0
  50. package/dist/backend-msb/follow-replay.js +20 -0
  51. package/dist/backend-msb/follow-replay.js.map +1 -0
  52. package/dist/backend-msb/image-cache.d.ts +25 -0
  53. package/dist/backend-msb/image-cache.d.ts.map +1 -0
  54. package/dist/backend-msb/image-cache.js +27 -0
  55. package/dist/backend-msb/image-cache.js.map +1 -0
  56. package/dist/backend-msb/index.d.ts +6 -0
  57. package/dist/backend-msb/index.d.ts.map +1 -0
  58. package/dist/backend-msb/index.js +21 -0
  59. package/dist/backend-msb/index.js.map +1 -0
  60. package/dist/backend-msb/invoke.d.ts +24 -0
  61. package/dist/backend-msb/invoke.d.ts.map +1 -0
  62. package/dist/backend-msb/invoke.js +73 -0
  63. package/dist/backend-msb/invoke.js.map +1 -0
  64. package/dist/backend-msb/ls-json.d.ts +23 -0
  65. package/dist/backend-msb/ls-json.d.ts.map +1 -0
  66. package/dist/backend-msb/ls-json.js +113 -0
  67. package/dist/backend-msb/ls-json.js.map +1 -0
  68. package/dist/backend-msb/network-links.d.ts +7 -0
  69. package/dist/backend-msb/network-links.d.ts.map +1 -0
  70. package/dist/backend-msb/network-links.js +31 -0
  71. package/dist/backend-msb/network-links.js.map +1 -0
  72. package/dist/backend-msb/platform.d.ts +29 -0
  73. package/dist/backend-msb/platform.d.ts.map +1 -0
  74. package/dist/backend-msb/platform.js +128 -0
  75. package/dist/backend-msb/platform.js.map +1 -0
  76. package/dist/backend-msb/port-conflict.d.ts +10 -0
  77. package/dist/backend-msb/port-conflict.d.ts.map +1 -0
  78. package/dist/backend-msb/port-conflict.js +16 -0
  79. package/dist/backend-msb/port-conflict.js.map +1 -0
  80. package/dist/backend-msb/provider.d.ts +10 -0
  81. package/dist/backend-msb/provider.d.ts.map +1 -0
  82. package/dist/backend-msb/provider.js +40 -0
  83. package/dist/backend-msb/provider.js.map +1 -0
  84. package/dist/backend-msb/provisioner.d.ts +19 -0
  85. package/dist/backend-msb/provisioner.d.ts.map +1 -0
  86. package/dist/backend-msb/provisioner.js +332 -0
  87. package/dist/backend-msb/provisioner.js.map +1 -0
  88. package/dist/backend-msb/reaper.d.ts +10 -0
  89. package/dist/backend-msb/reaper.d.ts.map +1 -0
  90. package/dist/backend-msb/reaper.js +73 -0
  91. package/dist/backend-msb/reaper.js.map +1 -0
  92. package/dist/core/backend.d.ts +98 -0
  93. package/dist/core/backend.d.ts.map +1 -0
  94. package/dist/core/backend.js +2 -0
  95. package/dist/core/backend.js.map +1 -0
  96. package/dist/core/backends.d.ts +37 -0
  97. package/dist/core/backends.d.ts.map +1 -0
  98. package/dist/core/backends.js +127 -0
  99. package/dist/core/backends.js.map +1 -0
  100. package/dist/core/cleanup.d.ts +37 -0
  101. package/dist/core/cleanup.d.ts.map +1 -0
  102. package/dist/core/cleanup.js +86 -0
  103. package/dist/core/cleanup.js.map +1 -0
  104. package/dist/core/errors.d.ts +51 -0
  105. package/dist/core/errors.d.ts.map +1 -0
  106. package/dist/core/errors.js +66 -0
  107. package/dist/core/errors.js.map +1 -0
  108. package/dist/core/free-ports.d.ts +23 -0
  109. package/dist/core/free-ports.d.ts.map +1 -0
  110. package/dist/core/free-ports.js +63 -0
  111. package/dist/core/free-ports.js.map +1 -0
  112. package/dist/core/generic-container.d.ts +145 -0
  113. package/dist/core/generic-container.d.ts.map +1 -0
  114. package/dist/core/generic-container.js +385 -0
  115. package/dist/core/generic-container.js.map +1 -0
  116. package/dist/core/model.d.ts +60 -0
  117. package/dist/core/model.d.ts.map +1 -0
  118. package/dist/core/model.js +2 -0
  119. package/dist/core/model.js.map +1 -0
  120. package/dist/core/mountable-file.d.ts +25 -0
  121. package/dist/core/mountable-file.d.ts.map +1 -0
  122. package/dist/core/mountable-file.js +64 -0
  123. package/dist/core/mountable-file.js.map +1 -0
  124. package/dist/core/network.d.ts +58 -0
  125. package/dist/core/network.d.ts.map +1 -0
  126. package/dist/core/network.js +84 -0
  127. package/dist/core/network.js.map +1 -0
  128. package/dist/core/run-id.d.ts +18 -0
  129. package/dist/core/run-id.d.ts.map +1 -0
  130. package/dist/core/run-id.js +18 -0
  131. package/dist/core/run-id.js.map +1 -0
  132. package/dist/core/wait.d.ts +59 -0
  133. package/dist/core/wait.d.ts.map +1 -0
  134. package/dist/core/wait.js +239 -0
  135. package/dist/core/wait.js.map +1 -0
  136. package/dist/index.d.ts +26 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.js +22 -0
  139. package/dist/index.js.map +1 -0
  140. package/dist/modules/arango.d.ts +14 -0
  141. package/dist/modules/arango.d.ts.map +1 -0
  142. package/dist/modules/arango.js +37 -0
  143. package/dist/modules/arango.js.map +1 -0
  144. package/dist/modules/clickhouse.d.ts +37 -0
  145. package/dist/modules/clickhouse.d.ts.map +1 -0
  146. package/dist/modules/clickhouse.js +69 -0
  147. package/dist/modules/clickhouse.js.map +1 -0
  148. package/dist/modules/flink.d.ts +65 -0
  149. package/dist/modules/flink.d.ts.map +1 -0
  150. package/dist/modules/flink.js +125 -0
  151. package/dist/modules/flink.js.map +1 -0
  152. package/dist/modules/floci.d.ts +46 -0
  153. package/dist/modules/floci.d.ts.map +1 -0
  154. package/dist/modules/floci.js +62 -0
  155. package/dist/modules/floci.js.map +1 -0
  156. package/dist/modules/index.d.ts +31 -0
  157. package/dist/modules/index.d.ts.map +1 -0
  158. package/dist/modules/index.js +31 -0
  159. package/dist/modules/index.js.map +1 -0
  160. package/dist/modules/kafka.d.ts +11 -0
  161. package/dist/modules/kafka.d.ts.map +1 -0
  162. package/dist/modules/kafka.js +41 -0
  163. package/dist/modules/kafka.js.map +1 -0
  164. package/dist/modules/keycloak.d.ts +40 -0
  165. package/dist/modules/keycloak.d.ts.map +1 -0
  166. package/dist/modules/keycloak.js +67 -0
  167. package/dist/modules/keycloak.js.map +1 -0
  168. package/dist/modules/mariadb.d.ts +56 -0
  169. package/dist/modules/mariadb.d.ts.map +1 -0
  170. package/dist/modules/mariadb.js +89 -0
  171. package/dist/modules/mariadb.js.map +1 -0
  172. package/dist/modules/memcached.d.ts +24 -0
  173. package/dist/modules/memcached.d.ts.map +1 -0
  174. package/dist/modules/memcached.js +105 -0
  175. package/dist/modules/memcached.js.map +1 -0
  176. package/dist/modules/mongodb.d.ts +19 -0
  177. package/dist/modules/mongodb.d.ts.map +1 -0
  178. package/dist/modules/mongodb.js +69 -0
  179. package/dist/modules/mongodb.js.map +1 -0
  180. package/dist/modules/mysql.d.ts +61 -0
  181. package/dist/modules/mysql.d.ts.map +1 -0
  182. package/dist/modules/mysql.js +101 -0
  183. package/dist/modules/mysql.js.map +1 -0
  184. package/dist/modules/neo4j.d.ts +60 -0
  185. package/dist/modules/neo4j.d.ts.map +1 -0
  186. package/dist/modules/neo4j.js +83 -0
  187. package/dist/modules/neo4j.js.map +1 -0
  188. package/dist/modules/pinot.d.ts +30 -0
  189. package/dist/modules/pinot.d.ts.map +1 -0
  190. package/dist/modules/pinot.js +49 -0
  191. package/dist/modules/pinot.js.map +1 -0
  192. package/dist/modules/postgres.d.ts +29 -0
  193. package/dist/modules/postgres.d.ts.map +1 -0
  194. package/dist/modules/postgres.js +73 -0
  195. package/dist/modules/postgres.js.map +1 -0
  196. package/dist/modules/rabbitmq.d.ts +46 -0
  197. package/dist/modules/rabbitmq.d.ts.map +1 -0
  198. package/dist/modules/rabbitmq.js +68 -0
  199. package/dist/modules/rabbitmq.js.map +1 -0
  200. package/dist/modules/redis.d.ts +15 -0
  201. package/dist/modules/redis.d.ts.map +1 -0
  202. package/dist/modules/redis.js +24 -0
  203. package/dist/modules/redis.js.map +1 -0
  204. package/dist/modules/redpanda.d.ts +27 -0
  205. package/dist/modules/redpanda.d.ts.map +1 -0
  206. package/dist/modules/redpanda.js +58 -0
  207. package/dist/modules/redpanda.js.map +1 -0
  208. package/dist/modules/spring-cloud-config.d.ts +18 -0
  209. package/dist/modules/spring-cloud-config.d.ts.map +1 -0
  210. package/dist/modules/spring-cloud-config.js +28 -0
  211. package/dist/modules/spring-cloud-config.js.map +1 -0
  212. package/dist/modules/wiremock.d.ts +21 -0
  213. package/dist/modules/wiremock.d.ts.map +1 -0
  214. package/dist/modules/wiremock.js +32 -0
  215. package/dist/modules/wiremock.js.map +1 -0
  216. package/package.json +104 -0
@@ -0,0 +1,60 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ /**
3
+ * A single-node Neo4j Community container, queried over its HTTP Cypher
4
+ * transaction endpoint (`/db/neo4j/tx/commit`) — no bolt driver dependency
5
+ * needed, matching this library's HTTP-first module convention
6
+ * (`ClickHouseContainer`, `PinotContainer`). The bolt port (7687) is still
7
+ * exposed and its URI available via `boltUrl` for callers who do want a
8
+ * real driver.
9
+ *
10
+ * Defaults to a `neo4j`/`rightsize-test` username/password pair (the image
11
+ * refuses passwords under 8 characters — `neo4j`/`neo4j` is rejected at
12
+ * boot) so `httpUrl` plus basic auth is usable with zero configuration;
13
+ * call `withPassword` before `start()` to override it. The username is
14
+ * fixed by the image at `neo4j` — there is no env var to change it.
15
+ *
16
+ * ### Readiness — `Started.` is the exact log line, verified against a real boot
17
+ *
18
+ * Captured verbatim from `neo4j:5-community`:
19
+ *
20
+ * ```
21
+ * ... INFO Bolt enabled on 0.0.0.0:7687.
22
+ * ... INFO HTTP enabled on 0.0.0.0:7474.
23
+ * ... INFO Remote interface available at http://localhost:7474/
24
+ * ... INFO Started.
25
+ * ```
26
+ *
27
+ * `Started.` is logged only after both connectors are already listening, so
28
+ * it's both accurate and simpler than a two-port HTTP/bolt race. The dot in
29
+ * the regex is deliberately ESCAPED (`Started\\.`) — an unescaped dot would
30
+ * also match the literal character it's meant to require, but escaping is
31
+ * the correct contract for a real regex engine (`.` otherwise matches any
32
+ * character, not just itself).
33
+ *
34
+ * ### Memory — measured, needed the ladder
35
+ *
36
+ * At msb's default ~450MB microVM RAM, the server logs `Invalid memory
37
+ * configuration - exceeds physical memory` and shuts itself down cleanly
38
+ * (`Stopped.`) rather than hanging or getting OOM-killed — Neo4j's own
39
+ * memory-recommendation calculator sizes the page cache and heap off total
40
+ * visible RAM and refuses to start if the sums don't fit. A real boot with
41
+ * no memory cap sits at ~430MiB RSS, just over that default budget.
42
+ * `withMemoryLimit(1024)` is this module's default (verified: boots clean,
43
+ * the HTTP Cypher endpoint answers well within the startup timeout).
44
+ */
45
+ export declare class Neo4jContainer extends GenericContainer {
46
+ private passwordState;
47
+ constructor(image?: string);
48
+ static start(image?: string): Promise<Neo4jContainer>;
49
+ /** Overrides `NEO4J_AUTH`'s password half (default `rightsize-test`; the image requires at least 8 characters). */
50
+ withPassword(password: string): this;
51
+ /** The fixed admin username (`neo4j` — the image has no env var to change it). */
52
+ get username(): string;
53
+ /** The configured admin password (default `rightsize-test`). */
54
+ get password(): string;
55
+ /** The HTTP interface's base URL (Cypher transactions via `POST {httpUrl}/db/neo4j/tx/commit`). */
56
+ get httpUrl(): string;
57
+ /** The bolt interface's URI, for callers using a real bolt driver instead of the HTTP helpers. */
58
+ get boltUrl(): string;
59
+ }
60
+ //# sourceMappingURL=neo4j.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neo4j.d.ts","sourceRoot":"","sources":["../../src/modules/neo4j.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAOhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;IAClD,OAAO,CAAC,aAAa,CAAoB;gBAE7B,KAAK,SAAsB;WAQjB,KAAK,CAAC,KAAK,SAAsB,GAAG,OAAO,CAAC,cAAc,CAAC;IAIjF,mHAAmH;IACnH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,kFAAkF;IAClF,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,gEAAgE;IAChE,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,mGAAmG;IACnG,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,kGAAkG;IAClG,IAAI,OAAO,IAAI,MAAM,CAEpB;CACF"}
@@ -0,0 +1,83 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const HTTP_PORT = 7474;
4
+ const BOLT_PORT = 7687;
5
+ const DEFAULT_PASSWORD = "rightsize-test";
6
+ /**
7
+ * A single-node Neo4j Community container, queried over its HTTP Cypher
8
+ * transaction endpoint (`/db/neo4j/tx/commit`) — no bolt driver dependency
9
+ * needed, matching this library's HTTP-first module convention
10
+ * (`ClickHouseContainer`, `PinotContainer`). The bolt port (7687) is still
11
+ * exposed and its URI available via `boltUrl` for callers who do want a
12
+ * real driver.
13
+ *
14
+ * Defaults to a `neo4j`/`rightsize-test` username/password pair (the image
15
+ * refuses passwords under 8 characters — `neo4j`/`neo4j` is rejected at
16
+ * boot) so `httpUrl` plus basic auth is usable with zero configuration;
17
+ * call `withPassword` before `start()` to override it. The username is
18
+ * fixed by the image at `neo4j` — there is no env var to change it.
19
+ *
20
+ * ### Readiness — `Started.` is the exact log line, verified against a real boot
21
+ *
22
+ * Captured verbatim from `neo4j:5-community`:
23
+ *
24
+ * ```
25
+ * ... INFO Bolt enabled on 0.0.0.0:7687.
26
+ * ... INFO HTTP enabled on 0.0.0.0:7474.
27
+ * ... INFO Remote interface available at http://localhost:7474/
28
+ * ... INFO Started.
29
+ * ```
30
+ *
31
+ * `Started.` is logged only after both connectors are already listening, so
32
+ * it's both accurate and simpler than a two-port HTTP/bolt race. The dot in
33
+ * the regex is deliberately ESCAPED (`Started\\.`) — an unescaped dot would
34
+ * also match the literal character it's meant to require, but escaping is
35
+ * the correct contract for a real regex engine (`.` otherwise matches any
36
+ * character, not just itself).
37
+ *
38
+ * ### Memory — measured, needed the ladder
39
+ *
40
+ * At msb's default ~450MB microVM RAM, the server logs `Invalid memory
41
+ * configuration - exceeds physical memory` and shuts itself down cleanly
42
+ * (`Stopped.`) rather than hanging or getting OOM-killed — Neo4j's own
43
+ * memory-recommendation calculator sizes the page cache and heap off total
44
+ * visible RAM and refuses to start if the sums don't fit. A real boot with
45
+ * no memory cap sits at ~430MiB RSS, just over that default budget.
46
+ * `withMemoryLimit(1024)` is this module's default (verified: boots clean,
47
+ * the HTTP Cypher endpoint answers well within the startup timeout).
48
+ */
49
+ export class Neo4jContainer extends GenericContainer {
50
+ passwordState = DEFAULT_PASSWORD;
51
+ constructor(image = "neo4j:5-community") {
52
+ super(image);
53
+ this.withExposedPorts(HTTP_PORT, BOLT_PORT)
54
+ .withEnv("NEO4J_AUTH", `neo4j/${this.passwordState}`)
55
+ .withMemoryLimit(1024)
56
+ .waitingFor(Wait.forLogMessage(".*Started\\..*", 1).withStartupTimeout(120_000));
57
+ }
58
+ static async start(image = "neo4j:5-community") {
59
+ return (await new Neo4jContainer(image).start());
60
+ }
61
+ /** Overrides `NEO4J_AUTH`'s password half (default `rightsize-test`; the image requires at least 8 characters). */
62
+ withPassword(password) {
63
+ this.passwordState = password;
64
+ return this.withEnv("NEO4J_AUTH", `neo4j/${password}`);
65
+ }
66
+ /** The fixed admin username (`neo4j` — the image has no env var to change it). */
67
+ get username() {
68
+ return "neo4j";
69
+ }
70
+ /** The configured admin password (default `rightsize-test`). */
71
+ get password() {
72
+ return this.passwordState;
73
+ }
74
+ /** The HTTP interface's base URL (Cypher transactions via `POST {httpUrl}/db/neo4j/tx/commit`). */
75
+ get httpUrl() {
76
+ return `http://${this.host}:${this.getMappedPort(HTTP_PORT)}`;
77
+ }
78
+ /** The bolt interface's URI, for callers using a real bolt driver instead of the HTTP helpers. */
79
+ get boltUrl() {
80
+ return `bolt://${this.host}:${this.getMappedPort(BOLT_PORT)}`;
81
+ }
82
+ }
83
+ //# sourceMappingURL=neo4j.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neo4j.js","sourceRoot":"","sources":["../../src/modules/neo4j.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IAC1C,aAAa,GAAG,gBAAgB,CAAC;IAEzC,YAAY,KAAK,GAAG,mBAAmB;QACrC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC;aACxC,OAAO,CAAC,YAAY,EAAE,SAAS,IAAI,CAAC,aAAa,EAAE,CAAC;aACpD,eAAe,CAAC,IAAI,CAAC;aACrB,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrF,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,mBAAmB;QACrD,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAmB,CAAC;IACrE,CAAC;IAED,mHAAmH;IACnH,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,kFAAkF;IAClF,IAAI,QAAQ;QACV,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,gEAAgE;IAChE,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,mGAAmG;IACnG,IAAI,OAAO;QACT,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;IAChE,CAAC;IAED,kGAAkG;IAClG,IAAI,OAAO;QACT,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;IAChE,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ /**
3
+ * A single-container Apache Pinot QuickStart cluster (controller + broker +
4
+ * server + ZooKeeper, all four JVMs colocated in one image, started with
5
+ * `QuickStart -type EMPTY` for a clean cluster with no demo tables).
6
+ *
7
+ * Two pins here correct guesses that turned out wrong against the real
8
+ * 1.5.1 image:
9
+ *
10
+ * - The broker's query port is **8000**, not 8099. The image exposes
11
+ * 8096–8099 (controller admin, and various internal ports) plus 9000, but
12
+ * QuickStart's broker binds 8000 for client queries; 8099 is never opened
13
+ * by this entrypoint.
14
+ * - The image bakes `-Xmx4G` into the QuickStart launch scripts, so it needs
15
+ * `withMemoryLimit(4096)` on msb regardless of how modest the workload is.
16
+ * Measured on this machine: 2048/2560MB microVMs get OOM-killed outright;
17
+ * 3072MB boots but runs at ~99% memory pressure with Helix RPC timeouts
18
+ * under any load; 4096MB is the first limit that boots AND stays stable
19
+ * (~74% steady-state utilization). This is a hard floor, not a tunable
20
+ * default — do not lower it.
21
+ */
22
+ export declare class PinotContainer extends GenericContainer {
23
+ constructor(image?: string);
24
+ static start(image?: string): Promise<PinotContainer>;
25
+ /** The controller's REST base URL (schema/table admin, `/health`). */
26
+ get controllerUrl(): string;
27
+ /** The broker's query base URL. */
28
+ get brokerUrl(): string;
29
+ }
30
+ //# sourceMappingURL=pinot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinot.d.ts","sourceRoot":"","sources":["../../src/modules/pinot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAOhE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;gBACtC,KAAK,SAA4B;WAWvB,KAAK,CAAC,KAAK,SAA4B,GAAG,OAAO,CAAC,cAAc,CAAC;IAIvF,sEAAsE;IACtE,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED,mCAAmC;IACnC,IAAI,SAAS,IAAI,MAAM,CAEtB;CACF"}
@@ -0,0 +1,49 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const CONTROLLER_PORT = 9000;
4
+ const BROKER_PORT = 8000;
5
+ const STARTUP_TIMEOUT_MS = 180_000;
6
+ /**
7
+ * A single-container Apache Pinot QuickStart cluster (controller + broker +
8
+ * server + ZooKeeper, all four JVMs colocated in one image, started with
9
+ * `QuickStart -type EMPTY` for a clean cluster with no demo tables).
10
+ *
11
+ * Two pins here correct guesses that turned out wrong against the real
12
+ * 1.5.1 image:
13
+ *
14
+ * - The broker's query port is **8000**, not 8099. The image exposes
15
+ * 8096–8099 (controller admin, and various internal ports) plus 9000, but
16
+ * QuickStart's broker binds 8000 for client queries; 8099 is never opened
17
+ * by this entrypoint.
18
+ * - The image bakes `-Xmx4G` into the QuickStart launch scripts, so it needs
19
+ * `withMemoryLimit(4096)` on msb regardless of how modest the workload is.
20
+ * Measured on this machine: 2048/2560MB microVMs get OOM-killed outright;
21
+ * 3072MB boots but runs at ~99% memory pressure with Helix RPC timeouts
22
+ * under any load; 4096MB is the first limit that boots AND stays stable
23
+ * (~74% steady-state utilization). This is a hard floor, not a tunable
24
+ * default — do not lower it.
25
+ */
26
+ export class PinotContainer extends GenericContainer {
27
+ constructor(image = "apachepinot/pinot:1.5.1") {
28
+ super(image);
29
+ this.withExposedPorts(CONTROLLER_PORT, BROKER_PORT)
30
+ .withCommand("QuickStart", "-type", "EMPTY")
31
+ .withMemoryLimit(4096)
32
+ // A four-JVM cluster (controller+broker+server+ZK) cold-booting in one
33
+ // microVM/container is legitimately slow; 180s gives it room without
34
+ // masking a real hang.
35
+ .waitingFor(Wait.forHttp("/health").forPort(CONTROLLER_PORT).withStartupTimeout(STARTUP_TIMEOUT_MS));
36
+ }
37
+ static async start(image = "apachepinot/pinot:1.5.1") {
38
+ return (await new PinotContainer(image).start());
39
+ }
40
+ /** The controller's REST base URL (schema/table admin, `/health`). */
41
+ get controllerUrl() {
42
+ return `http://${this.host}:${this.getMappedPort(CONTROLLER_PORT)}`;
43
+ }
44
+ /** The broker's query base URL. */
45
+ get brokerUrl() {
46
+ return `http://${this.host}:${this.getMappedPort(BROKER_PORT)}`;
47
+ }
48
+ }
49
+ //# sourceMappingURL=pinot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinot.js","sourceRoot":"","sources":["../../src/modules/pinot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,eAAe,GAAG,IAAI,CAAC;AAC7B,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAEnC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IAClD,YAAY,KAAK,GAAG,yBAAyB;QAC3C,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,eAAe,EAAE,WAAW,CAAC;aAChD,WAAW,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC;aAC3C,eAAe,CAAC,IAAI,CAAC;YACtB,uEAAuE;YACvE,qEAAqE;YACrE,uBAAuB;aACtB,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACzG,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,yBAAyB;QAC3D,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAmB,CAAC;IACrE,CAAC;IAED,sEAAsE;IACtE,IAAI,aAAa;QACf,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,EAAE,CAAC;IACtE,CAAC;IAED,mCAAmC;IACnC,IAAI,SAAS;QACX,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;IAClE,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ /**
3
+ * A single-node PostgreSQL container. Defaults to a `test`/`test`/`test`
4
+ * user/password/database trio so `connectionString` is usable with zero
5
+ * configuration; call `withUsername`/`withPassword`/`withDatabase` before
6
+ * `start()` to override any of them.
7
+ */
8
+ export declare class PostgresContainer extends GenericContainer {
9
+ private usernameState;
10
+ private passwordState;
11
+ private databaseState;
12
+ constructor(image?: string);
13
+ static start(image?: string): Promise<PostgresContainer>;
14
+ /** Overrides `POSTGRES_USER` (default `test`). */
15
+ withUsername(username: string): this;
16
+ /** Overrides `POSTGRES_PASSWORD` (default `test`). */
17
+ withPassword(password: string): this;
18
+ /** Overrides `POSTGRES_DB` (default `test`). */
19
+ withDatabase(database: string): this;
20
+ /** The configured database user (default `test`). */
21
+ get username(): string;
22
+ /** The configured database password (default `test`). */
23
+ get password(): string;
24
+ /** The configured database name (default `test`). */
25
+ get databaseName(): string;
26
+ /** A `postgres://` connection string for the running container's `databaseName`. */
27
+ get connectionString(): string;
28
+ }
29
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/modules/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAKhE;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,gBAAgB;IACrD,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,aAAa,CAAU;gBAEnB,KAAK,SAAuB;WAyBlB,KAAK,CAAC,KAAK,SAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIrF,kDAAkD;IAClD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,sDAAsD;IACtD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,gDAAgD;IAChD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,qDAAqD;IACrD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,yDAAyD;IACzD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,qDAAqD;IACrD,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,oFAAoF;IACpF,IAAI,gBAAgB,IAAI,MAAM,CAE7B;CACF"}
@@ -0,0 +1,73 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const GUEST_PORT = 5432;
4
+ /**
5
+ * A single-node PostgreSQL container. Defaults to a `test`/`test`/`test`
6
+ * user/password/database trio so `connectionString` is usable with zero
7
+ * configuration; call `withUsername`/`withPassword`/`withDatabase` before
8
+ * `start()` to override any of them.
9
+ */
10
+ export class PostgresContainer extends GenericContainer {
11
+ usernameState = "test";
12
+ passwordState = "test";
13
+ databaseState = "test";
14
+ constructor(image = "postgres:18-alpine") {
15
+ super(image);
16
+ this.withExposedPorts(GUEST_PORT)
17
+ .withEnv("POSTGRES_USER", this.usernameState)
18
+ .withEnv("POSTGRES_PASSWORD", this.passwordState)
19
+ .withEnv("POSTGRES_DB", this.databaseState)
20
+ // The official postgres:*-alpine image bakes DOCKER_PG_LLVM_DEPS into
21
+ // its manifest with a literal tab character in the value (a
22
+ // package-list built with `\t\t` continuation). msb's krun VMM
23
+ // builder panics with InvalidAscii on that boot-env value before the
24
+ // guest ever starts (reproduced with zero rightsize-set env vars —
25
+ // it's the image, not us). Docker is unaffected. Overriding the var
26
+ // here wins over the image default in both backends' env-merge order
27
+ // and is a no-op for the build the image already baked, so it's a
28
+ // safe, backend-portable fix rather than an msb-only special case.
29
+ .withEnv("DOCKER_PG_LLVM_DEPS", "")
30
+ // The postgres entrypoint starts the server once to run initdb
31
+ // scripts against it, shuts it down, then starts it again for real —
32
+ // printing "database system is ready to accept connections" BOTH
33
+ // times. Waiting for the first occurrence races that restart: a
34
+ // client can connect to the init-time server just before it's torn
35
+ // down. times=2 waits for the second, durable listen.
36
+ .waitingFor(Wait.forLogMessage(".*database system is ready to accept connections.*", 2));
37
+ }
38
+ static async start(image = "postgres:18-alpine") {
39
+ return (await new PostgresContainer(image).start());
40
+ }
41
+ /** Overrides `POSTGRES_USER` (default `test`). */
42
+ withUsername(username) {
43
+ this.usernameState = username;
44
+ return this.withEnv("POSTGRES_USER", username);
45
+ }
46
+ /** Overrides `POSTGRES_PASSWORD` (default `test`). */
47
+ withPassword(password) {
48
+ this.passwordState = password;
49
+ return this.withEnv("POSTGRES_PASSWORD", password);
50
+ }
51
+ /** Overrides `POSTGRES_DB` (default `test`). */
52
+ withDatabase(database) {
53
+ this.databaseState = database;
54
+ return this.withEnv("POSTGRES_DB", database);
55
+ }
56
+ /** The configured database user (default `test`). */
57
+ get username() {
58
+ return this.usernameState;
59
+ }
60
+ /** The configured database password (default `test`). */
61
+ get password() {
62
+ return this.passwordState;
63
+ }
64
+ /** The configured database name (default `test`). */
65
+ get databaseName() {
66
+ return this.databaseState;
67
+ }
68
+ /** A `postgres://` connection string for the running container's `databaseName`. */
69
+ get connectionString() {
70
+ return `postgres://${this.usernameState}:${this.passwordState}@${this.host}:${this.getMappedPort(GUEST_PORT)}/${this.databaseState}`;
71
+ }
72
+ }
73
+ //# sourceMappingURL=postgres.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/modules/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB;;;;;GAKG;AACH,MAAM,OAAO,iBAAkB,SAAQ,gBAAgB;IAC7C,aAAa,GAAG,MAAM,CAAC;IACvB,aAAa,GAAG,MAAM,CAAC;IACvB,aAAa,GAAG,MAAM,CAAC;IAE/B,YAAY,KAAK,GAAG,oBAAoB;QACtC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC;aAC9B,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC;aAC5C,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC,aAAa,CAAC;aAChD,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC;YAC3C,sEAAsE;YACtE,4DAA4D;YAC5D,+DAA+D;YAC/D,qEAAqE;YACrE,mEAAmE;YACnE,oEAAoE;YACpE,qEAAqE;YACrE,kEAAkE;YAClE,mEAAmE;aAClE,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC;YACnC,+DAA+D;YAC/D,qEAAqE;YACrE,iEAAiE;YACjE,gEAAgE;YAChE,mEAAmE;YACnE,sDAAsD;aACrD,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,oDAAoD,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7F,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,oBAAoB;QACtD,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAsB,CAAC;IAC3E,CAAC;IAED,kDAAkD;IAClD,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,sDAAsD;IACtD,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,gDAAgD;IAChD,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,qDAAqD;IACrD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,yDAAyD;IACzD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,qDAAqD;IACrD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,oFAAoF;IACpF,IAAI,gBAAgB;QAClB,OAAO,cAAc,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;IACvI,CAAC;CACF"}
@@ -0,0 +1,46 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ /**
3
+ * A single-node RabbitMQ container with the management plugin enabled.
4
+ * Defaults to the image's own `guest`/`guest` credentials; call
5
+ * `withUsername`/`withPassword` before `start()` to override either (sets
6
+ * `RABBITMQ_DEFAULT_USER`/`RABBITMQ_DEFAULT_PASS`).
7
+ *
8
+ * Readiness waits on the boot log line captured from a real
9
+ * `rabbitmq:4-management-alpine` run: `Server startup complete; N plugins
10
+ * started.` — NOT the shorter "Server startup complete" alone some older
11
+ * 3.x docs quote, since 4.x always appends the plugin-count clause on the
12
+ * same line. The wait regex (`.*Server startup complete.*`) only matches the
13
+ * stable "Server startup complete" substring anywhere on the line, so the
14
+ * trailing plugin-count clause — which varies by which plugins are
15
+ * enabled — never has to match exactly. The management HTTP API's own
16
+ * `/api/health/checks/...` endpoints require authenticated requests to
17
+ * probe, which would need this module to bake in an HTTP+auth wait
18
+ * strategy just to watch a JVM-style health check that AMQP's own boot log
19
+ * already answers for free — the log wait is simpler and exercises exactly
20
+ * the readiness rightsize's Wait strategies are for.
21
+ *
22
+ * RabbitMQ 4.x behavior note (not this module's concern to fix, but the
23
+ * reason the IT declares durable/exclusive queues): 4.x rejects declaring a
24
+ * transient (non-durable), non-exclusive queue — a behavior change from
25
+ * 3.x. Consumers of this container must declare durable or exclusive
26
+ * queues; a transient shared queue now errors at declare time.
27
+ */
28
+ export declare class RabbitMQContainer extends GenericContainer {
29
+ private usernameState;
30
+ private passwordState;
31
+ constructor(image?: string);
32
+ static start(image?: string): Promise<RabbitMQContainer>;
33
+ /** Overrides `RABBITMQ_DEFAULT_USER` (default `guest`). */
34
+ withUsername(username: string): this;
35
+ /** Overrides `RABBITMQ_DEFAULT_PASS` (default `guest`). */
36
+ withPassword(password: string): this;
37
+ /** The configured AMQP username (default `guest`). */
38
+ get username(): string;
39
+ /** The configured AMQP password (default `guest`). */
40
+ get password(): string;
41
+ /** An `amqp://` connection URL for the running broker. */
42
+ get amqpUrl(): string;
43
+ /** The management HTTP API's base URL for the running broker. */
44
+ get managementUrl(): string;
45
+ }
46
+ //# sourceMappingURL=rabbitmq.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rabbitmq.d.ts","sourceRoot":"","sources":["../../src/modules/rabbitmq.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAMhE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,iBAAkB,SAAQ,gBAAgB;IACrD,OAAO,CAAC,aAAa,CAAW;IAChC,OAAO,CAAC,aAAa,CAAW;gBAEpB,KAAK,SAAiC;WAO5B,KAAK,CAAC,KAAK,SAAiC,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAI/F,2DAA2D;IAC3D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,2DAA2D;IAC3D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKpC,sDAAsD;IACtD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,sDAAsD;IACtD,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,0DAA0D;IAC1D,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,iEAAiE;IACjE,IAAI,aAAa,IAAI,MAAM,CAE1B;CACF"}
@@ -0,0 +1,68 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const AMQP_PORT = 5672;
4
+ const MANAGEMENT_PORT = 15672;
5
+ /**
6
+ * A single-node RabbitMQ container with the management plugin enabled.
7
+ * Defaults to the image's own `guest`/`guest` credentials; call
8
+ * `withUsername`/`withPassword` before `start()` to override either (sets
9
+ * `RABBITMQ_DEFAULT_USER`/`RABBITMQ_DEFAULT_PASS`).
10
+ *
11
+ * Readiness waits on the boot log line captured from a real
12
+ * `rabbitmq:4-management-alpine` run: `Server startup complete; N plugins
13
+ * started.` — NOT the shorter "Server startup complete" alone some older
14
+ * 3.x docs quote, since 4.x always appends the plugin-count clause on the
15
+ * same line. The wait regex (`.*Server startup complete.*`) only matches the
16
+ * stable "Server startup complete" substring anywhere on the line, so the
17
+ * trailing plugin-count clause — which varies by which plugins are
18
+ * enabled — never has to match exactly. The management HTTP API's own
19
+ * `/api/health/checks/...` endpoints require authenticated requests to
20
+ * probe, which would need this module to bake in an HTTP+auth wait
21
+ * strategy just to watch a JVM-style health check that AMQP's own boot log
22
+ * already answers for free — the log wait is simpler and exercises exactly
23
+ * the readiness rightsize's Wait strategies are for.
24
+ *
25
+ * RabbitMQ 4.x behavior note (not this module's concern to fix, but the
26
+ * reason the IT declares durable/exclusive queues): 4.x rejects declaring a
27
+ * transient (non-durable), non-exclusive queue — a behavior change from
28
+ * 3.x. Consumers of this container must declare durable or exclusive
29
+ * queues; a transient shared queue now errors at declare time.
30
+ */
31
+ export class RabbitMQContainer extends GenericContainer {
32
+ usernameState = "guest";
33
+ passwordState = "guest";
34
+ constructor(image = "rabbitmq:4-management-alpine") {
35
+ super(image);
36
+ this.withExposedPorts(AMQP_PORT, MANAGEMENT_PORT).waitingFor(Wait.forLogMessage(".*Server startup complete.*"));
37
+ }
38
+ static async start(image = "rabbitmq:4-management-alpine") {
39
+ return (await new RabbitMQContainer(image).start());
40
+ }
41
+ /** Overrides `RABBITMQ_DEFAULT_USER` (default `guest`). */
42
+ withUsername(username) {
43
+ this.usernameState = username;
44
+ return this.withEnv("RABBITMQ_DEFAULT_USER", username);
45
+ }
46
+ /** Overrides `RABBITMQ_DEFAULT_PASS` (default `guest`). */
47
+ withPassword(password) {
48
+ this.passwordState = password;
49
+ return this.withEnv("RABBITMQ_DEFAULT_PASS", password);
50
+ }
51
+ /** The configured AMQP username (default `guest`). */
52
+ get username() {
53
+ return this.usernameState;
54
+ }
55
+ /** The configured AMQP password (default `guest`). */
56
+ get password() {
57
+ return this.passwordState;
58
+ }
59
+ /** An `amqp://` connection URL for the running broker. */
60
+ get amqpUrl() {
61
+ return `amqp://${this.usernameState}:${this.passwordState}@${this.host}:${this.getMappedPort(AMQP_PORT)}`;
62
+ }
63
+ /** The management HTTP API's base URL for the running broker. */
64
+ get managementUrl() {
65
+ return `http://${this.host}:${this.getMappedPort(MANAGEMENT_PORT)}`;
66
+ }
67
+ }
68
+ //# sourceMappingURL=rabbitmq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rabbitmq.js","sourceRoot":"","sources":["../../src/modules/rabbitmq.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,SAAS,GAAG,IAAI,CAAC;AACvB,MAAM,eAAe,GAAG,KAAK,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,OAAO,iBAAkB,SAAQ,gBAAgB;IAC7C,aAAa,GAAG,OAAO,CAAC;IACxB,aAAa,GAAG,OAAO,CAAC;IAEhC,YAAY,KAAK,GAAG,8BAA8B;QAChD,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC,UAAU,CAC1D,IAAI,CAAC,aAAa,CAAC,6BAA6B,CAAC,CAClD,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,8BAA8B;QAChE,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAsB,CAAC;IAC3E,CAAC;IAED,2DAA2D;IAC3D,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED,2DAA2D;IAC3D,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED,sDAAsD;IACtD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,sDAAsD;IACtD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,0DAA0D;IAC1D,IAAI,OAAO;QACT,OAAO,UAAU,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;IAC5G,CAAC;IAED,iEAAiE;IACjE,IAAI,aAAa;QACf,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,EAAE,CAAC;IACtE,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ /**
3
+ * A single-node Redis container. Readiness is anchored on Redis's own
4
+ * "Ready to accept connections" log line rather than a TCP probe: on a loaded
5
+ * host the port forwarder can accept and hold a connection in the window
6
+ * between Redis binding its socket and actually serving, which a bare
7
+ * listening-port check cannot see through.
8
+ */
9
+ export declare class RedisContainer extends GenericContainer {
10
+ constructor(image?: string);
11
+ static start(image?: string): Promise<RedisContainer>;
12
+ /** A `redis://` connection URI for the running container. */
13
+ get uri(): string;
14
+ }
15
+ //# sourceMappingURL=redis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/modules/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAKhE;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,gBAAgB;gBACtC,KAAK,SAAqB;WAKhB,KAAK,CAAC,KAAK,SAAqB,GAAG,OAAO,CAAC,cAAc,CAAC;IAIhF,6DAA6D;IAC7D,IAAI,GAAG,IAAI,MAAM,CAEhB;CACF"}
@@ -0,0 +1,24 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const GUEST_PORT = 6379;
4
+ /**
5
+ * A single-node Redis container. Readiness is anchored on Redis's own
6
+ * "Ready to accept connections" log line rather than a TCP probe: on a loaded
7
+ * host the port forwarder can accept and hold a connection in the window
8
+ * between Redis binding its socket and actually serving, which a bare
9
+ * listening-port check cannot see through.
10
+ */
11
+ export class RedisContainer extends GenericContainer {
12
+ constructor(image = "redis:8.6-alpine") {
13
+ super(image);
14
+ this.withExposedPorts(GUEST_PORT).waitingFor(Wait.forLogMessage(".*Ready to accept connections.*", 1));
15
+ }
16
+ static async start(image = "redis:8.6-alpine") {
17
+ return (await new RedisContainer(image).start());
18
+ }
19
+ /** A `redis://` connection URI for the running container. */
20
+ get uri() {
21
+ return `redis://${this.host}:${this.getMappedPort(GUEST_PORT)}`;
22
+ }
23
+ }
24
+ //# sourceMappingURL=redis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/modules/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IAClD,YAAY,KAAK,GAAG,kBAAkB;QACpC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzG,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,kBAAkB;QACpD,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAmB,CAAC;IACrE,CAAC;IAED,6DAA6D;IAC7D,IAAI,GAAG;QACL,OAAO,WAAW,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;IAClE,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import type { ContainerSpec } from "../core/model.js";
3
+ /**
4
+ * A single-node Redpanda broker (Kafka API-compatible) with its schema
5
+ * registry enabled. Pinned to a versioned tag rather than `:latest`:
6
+ * `docker.redpanda.com` rate-limits anonymous pulls (seed it into the msb
7
+ * image cache once with `docker save <img> | msb load` ahead of integration
8
+ * runs), and a versioned tag makes that seed step reproducible.
9
+ */
10
+ export declare class RedpandaContainer extends GenericContainer {
11
+ constructor(image?: string);
12
+ static start(image?: string): Promise<RedpandaContainer>;
13
+ /**
14
+ * The advertised listener must carry the mapped host port, known only now
15
+ * (ports were allocated before boot) — the reason this hook exists at
16
+ * all. EXTERNAL advertises that mapped host port for host clients;
17
+ * INTERNAL advertises the fixed alias:port siblings resolve on the
18
+ * container network. See `KafkaContainer.customizeSpec` for the same
19
+ * trick applied to a single advertised listener.
20
+ */
21
+ protected customizeSpec(spec: ContainerSpec, mapped: (guest: number) => number): ContainerSpec;
22
+ /** The `PLAINTEXT://` bootstrap-servers address for the running broker (EXTERNAL listener). */
23
+ get bootstrapServers(): string;
24
+ /** The schema registry's base URI for the running broker. */
25
+ get schemaRegistryUrl(): string;
26
+ }
27
+ //# sourceMappingURL=redpanda.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redpanda.d.ts","sourceRoot":"","sources":["../../src/modules/redpanda.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAUtD;;;;;;GAMG;AACH,qBAAa,iBAAkB,SAAQ,gBAAgB;gBACzC,KAAK,SAAkC;WAO7B,KAAK,CACzB,KAAK,SAAkC,GACtC,OAAO,CAAC,iBAAiB,CAAC;IAI7B;;;;;;;OAOG;cACgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,aAAa;IAkBvG,+FAA+F;IAC/F,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,6DAA6D;IAC7D,IAAI,iBAAiB,IAAI,MAAM,CAE9B;CACF"}
@@ -0,0 +1,58 @@
1
+ import { GenericContainer } from "../core/generic-container.js";
2
+ import { Wait } from "../core/wait.js";
3
+ const EXTERNAL_PORT = 9092;
4
+ const INTERNAL_PORT = 9093;
5
+ const SCHEMA_REGISTRY_PORT = 8081;
6
+ // The alias siblings resolve INTERNAL through — native docker networks, or
7
+ // the msb exec-tunnel alias emulation.
8
+ const INTERNAL_ALIAS = "redpanda";
9
+ /**
10
+ * A single-node Redpanda broker (Kafka API-compatible) with its schema
11
+ * registry enabled. Pinned to a versioned tag rather than `:latest`:
12
+ * `docker.redpanda.com` rate-limits anonymous pulls (seed it into the msb
13
+ * image cache once with `docker save <img> | msb load` ahead of integration
14
+ * runs), and a versioned tag makes that seed step reproducible.
15
+ */
16
+ export class RedpandaContainer extends GenericContainer {
17
+ constructor(image = "redpandadata/redpanda:v24.2.4") {
18
+ super(image);
19
+ this.withExposedPorts(EXTERNAL_PORT, INTERNAL_PORT, SCHEMA_REGISTRY_PORT).waitingFor(Wait.forLogMessage(".*Successfully started Redpanda.*"));
20
+ }
21
+ static async start(image = "redpandadata/redpanda:v24.2.4") {
22
+ return (await new RedpandaContainer(image).start());
23
+ }
24
+ /**
25
+ * The advertised listener must carry the mapped host port, known only now
26
+ * (ports were allocated before boot) — the reason this hook exists at
27
+ * all. EXTERNAL advertises that mapped host port for host clients;
28
+ * INTERNAL advertises the fixed alias:port siblings resolve on the
29
+ * container network. See `KafkaContainer.customizeSpec` for the same
30
+ * trick applied to a single advertised listener.
31
+ */
32
+ customizeSpec(spec, mapped) {
33
+ const command = [
34
+ "redpanda",
35
+ "start",
36
+ "--mode",
37
+ "dev-container",
38
+ "--smp",
39
+ "1",
40
+ "--kafka-addr",
41
+ `EXTERNAL://0.0.0.0:${EXTERNAL_PORT},INTERNAL://0.0.0.0:${INTERNAL_PORT}`,
42
+ "--advertise-kafka-addr",
43
+ `EXTERNAL://127.0.0.1:${mapped(EXTERNAL_PORT)},INTERNAL://${INTERNAL_ALIAS}:${INTERNAL_PORT}`,
44
+ "--schema-registry-addr",
45
+ `0.0.0.0:${SCHEMA_REGISTRY_PORT}`,
46
+ ];
47
+ return { ...spec, command };
48
+ }
49
+ /** The `PLAINTEXT://` bootstrap-servers address for the running broker (EXTERNAL listener). */
50
+ get bootstrapServers() {
51
+ return `PLAINTEXT://${this.host}:${this.getMappedPort(EXTERNAL_PORT)}`;
52
+ }
53
+ /** The schema registry's base URI for the running broker. */
54
+ get schemaRegistryUrl() {
55
+ return `http://${this.host}:${this.getMappedPort(SCHEMA_REGISTRY_PORT)}`;
56
+ }
57
+ }
58
+ //# sourceMappingURL=redpanda.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redpanda.js","sourceRoot":"","sources":["../../src/modules/redpanda.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAGvC,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,aAAa,GAAG,IAAI,CAAC;AAC3B,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAElC,2EAA2E;AAC3E,uCAAuC;AACvC,MAAM,cAAc,GAAG,UAAU,CAAC;AAElC;;;;;;GAMG;AACH,MAAM,OAAO,iBAAkB,SAAQ,gBAAgB;IACrD,YAAY,KAAK,GAAG,+BAA+B;QACjD,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,EAAE,oBAAoB,CAAC,CAAC,UAAU,CAClF,IAAI,CAAC,aAAa,CAAC,mCAAmC,CAAC,CACxD,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,KAAK,CACzB,KAAK,GAAG,+BAA+B;QAEvC,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAsB,CAAC;IAC3E,CAAC;IAED;;;;;;;OAOG;IACgB,aAAa,CAAC,IAAmB,EAAE,MAAiC;QACrF,MAAM,OAAO,GAAG;YACd,UAAU;YACV,OAAO;YACP,QAAQ;YACR,eAAe;YACf,OAAO;YACP,GAAG;YACH,cAAc;YACd,sBAAsB,aAAa,uBAAuB,aAAa,EAAE;YACzE,wBAAwB;YACxB,wBAAwB,MAAM,CAAC,aAAa,CAAC,eAAe,cAAc,IAAI,aAAa,EAAE;YAC7F,wBAAwB;YACxB,WAAW,oBAAoB,EAAE;SAClC,CAAC;QACF,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IAED,+FAA+F;IAC/F,IAAI,gBAAgB;QAClB,OAAO,eAAe,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,CAAC;IACzE,CAAC;IAED,6DAA6D;IAC7D,IAAI,iBAAiB;QACnB,OAAO,UAAU,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,CAAC;IAC3E,CAAC;CACF"}