@rhost/testkit 1.3.1 → 1.4.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.
- package/SECURITY.md +11 -0
- package/dist/client.d.ts +8 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -0
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +28 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +94 -0
- package/dist/config.js.map +1 -0
- package/dist/container.d.ts +18 -5
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +57 -9
- package/dist/container.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/SECURITY.md
CHANGED
|
@@ -96,6 +96,17 @@ Remaining fix: examples should refuse to run against non-localhost hosts without
|
|
|
96
96
|
|
|
97
97
|
---
|
|
98
98
|
|
|
99
|
+
### Audit — 2026-03-28 ✓ FIXED
|
|
100
|
+
|
|
101
|
+
| ID | Severity | File | Finding | Fix |
|
|
102
|
+
|----|----------|------|---------|-----|
|
|
103
|
+
| M-NEW-1 | MEDIUM | `src/config.ts:56,59` | `loadConfig()` resolved `scriptsDir`/`mushConfig` with `path.resolve()`, allowing absolute paths or `../..` traversal to escape the project root. A tampered `rhost.config.json` could cause arbitrary host directories to be copied into Docker containers. | Added `resolveConfined()` guard: throws if resolved path does not start with the project root. Tests: `h3-config-path-traversal.test.ts` (8 tests). |
|
|
104
|
+
| L-NEW-1 | LOW | `src/__tests__/security/` | No security test for config path traversal guard | Covered by `h3-config-path-traversal.test.ts` above |
|
|
105
|
+
| L-NEW-2 | LOW | `.github/workflows/security-tests.yml` | Missing `permissions:` block; default GitHub token scopes depend on org policy | Added `permissions: contents: read` |
|
|
106
|
+
| H-NEW-1 | LOW | `scripts/jobs_db.py` | Raw psycopg2 exception strings (including `DETAIL:`, `HINT:` lines) returned to MUSH callers via `err(str(e))`, exposing schema internals | Added `_sanitize_db_error()` that strips diagnostic lines before returning; wired into both exception handlers. Tests: `h4-db-error-detail-leak.test.ts` (3 tests). |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
99
110
|
### Fixed (previous audit cycles)
|
|
100
111
|
|
|
101
112
|
| ID | Severity | File | Finding | Fix |
|
package/dist/client.d.ts
CHANGED
|
@@ -24,6 +24,13 @@ export interface RhostClientOptions {
|
|
|
24
24
|
* Default: 0 (no delay)
|
|
25
25
|
*/
|
|
26
26
|
paceMs?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Milliseconds to wait after sending a command and before sending the
|
|
29
|
+
* sentinel. Useful when commands produce deferred output (e.g. via
|
|
30
|
+
* @trigger or @wait 0) that arrives after the main response.
|
|
31
|
+
* Default: 0
|
|
32
|
+
*/
|
|
33
|
+
commandSettleMs?: number;
|
|
27
34
|
/**
|
|
28
35
|
* Timeout in milliseconds for the raw TCP connection to be established.
|
|
29
36
|
* If the server accepts the socket but then stalls, the connect will be
|
|
@@ -67,6 +74,7 @@ export declare class RhostClient {
|
|
|
67
74
|
private bannerTimeout;
|
|
68
75
|
private doStripAnsi;
|
|
69
76
|
private paceMs;
|
|
77
|
+
private commandSettleMs;
|
|
70
78
|
private connectTimeout;
|
|
71
79
|
constructor(options?: RhostClientOptions);
|
|
72
80
|
/**
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,MAAM,WAAW,kBAAkB;IAC/B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD,MAAM,WAAW,cAAc;IAC3B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,MAAM,CAAS;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,MAAM,WAAW,kBAAkB;IAC/B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD,MAAM,WAAW,cAAc;IAC3B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,GAAE,kBAAuB;IAU5C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9B;;;OAGG;IACG,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB9D;;;;;;;;;;OAUG;IACG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjE;;;;;;;OAOG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/D;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAmB3E,4DAA4D;IAC5D,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAI7C,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAI9C,8CAA8C;IACxC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YAanB,YAAY;YA8BZ,eAAe;YA8Bf,eAAe;IAQ7B,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,MAAM;CAGjB"}
|
package/dist/client.js
CHANGED
|
@@ -28,6 +28,7 @@ class RhostClient {
|
|
|
28
28
|
this.defaultTimeout = options.timeout ?? 10000;
|
|
29
29
|
this.bannerTimeout = options.bannerTimeout ?? 300;
|
|
30
30
|
this.doStripAnsi = options.stripAnsi !== false;
|
|
31
|
+
this.commandSettleMs = options.commandSettleMs ?? 0;
|
|
31
32
|
this.paceMs = options.paceMs ?? 0;
|
|
32
33
|
this.connectTimeout = options.connectTimeout ?? 10000;
|
|
33
34
|
}
|
|
@@ -171,6 +172,9 @@ class RhostClient {
|
|
|
171
172
|
const endMarker = `RHOST_CMD_END_${id}`;
|
|
172
173
|
const ms = timeout ?? this.defaultTimeout;
|
|
173
174
|
this.conn.send(cmd);
|
|
175
|
+
if (this.commandSettleMs > 0) {
|
|
176
|
+
await new Promise(r => setTimeout(r, this.commandSettleMs));
|
|
177
|
+
}
|
|
174
178
|
this.conn.send(`@pemit me=${endMarker}`);
|
|
175
179
|
const lines = [];
|
|
176
180
|
while (true) {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AASA,8BAEC;AAXD,mCAAoC;AACpC,6CAA8C;AAE9C,oDAAoD;AACpD,yDAAyD;AACzD,gCAAgC;AAChC,MAAM,OAAO,GAAG,0DAA0D,CAAC;AAE3E,uDAAuD;AACvD,SAAgB,SAAS,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AASA,8BAEC;AAXD,mCAAoC;AACpC,6CAA8C;AAE9C,oDAAoD;AACpD,yDAAyD;AACzD,gCAAgC;AAChC,MAAM,OAAO,GAAG,0DAA0D,CAAC;AAE3E,uDAAuD;AACvD,SAAgB,SAAS,CAAC,CAAS;IAC/B,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAkED;;;;;;;;;GASG;AACH,MAAa,WAAW;IAUpB,YAAY,UAA8B,EAAE;QACxC,IAAI,CAAC,IAAI,GAAG,IAAI,2BAAc,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;QAClF,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;QAC/C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,GAAG,CAAC;QAClD,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC;QAC/C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,KAAK,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACT,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7C,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,QAAgB;QAC1C,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAAC,kFAAkF,CAAC,CAAC;QAC7G,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,UAAU,CAAC,kFAAkF,CAAC,CAAC;QAC7G,CAAC;QACD,0EAA0E;QAC1E,uEAAuE;QACvE,2DAA2D;QAC3D,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,UAAU,CAAC,2DAA2D,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,QAAQ,GAAG,eAAe,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAChD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC;QACxC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,IAAI,CAAC,UAAkB,EAAE,OAAgB;QAC3C,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACpE,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,OAAgB;QACvC,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,KAAK,CAAC,OAAO,CAAC,KAAa,EAAE,UAA0B,EAAE;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC;QACpC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC;QAExC,sDAAsD;QACtD,MAAM,GAAG,GACL,IAAI,KAAK,MAAM;YACX,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC;YAChD,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEzE,IAAI,OAAO,EAAE,CAAC;YACV,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACtF,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,GAAG,CAAC;IACf,CAAC;IAED,4DAA4D;IAC5D,MAAM,CAAC,OAA+B;QAClC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,CAAC,OAA+B;QACnC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,UAAU;QACZ,IAAI,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACL,iBAAiB;QACrB,CAAC;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,4EAA4E;IAC5E,iEAAiE;IACjE,4EAA4E;IAEpE,KAAK,CAAC,YAAY,CACtB,UAAkB,EAClB,KAAc,EACd,OAAgB;QAEhB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,WAAW,GAAG,oBAAoB,EAAE,EAAE,CAAC;QAC7C,MAAM,SAAS,GAAG,kBAAkB,EAAE,EAAE,CAAC;QACzC,MAAM,EAAE,GAAG,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC;QAE1C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,WAAW,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;QAEzC,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAE5C,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,OAAO,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,MAAM;YACjE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAEO,KAAK,CAAC,eAAe,CACzB,GAAW,EACX,KAAc,EACd,OAAgB;QAEhB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,iBAAiB,EAAE,EAAE,CAAC;QACxC,MAAM,EAAE,GAAG,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC;QAE1C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;QAEzC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,OAAO,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,MAAM;YACjE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,4EAA4E;IAC5E,kBAAkB;IAClB,4EAA4E;IAEpE,KAAK,CAAC,eAAe,CAAC,MAAc,EAAE,SAAiB;QAC3D,OAAO,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACnD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACxD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,OAAO;QACvC,CAAC;IACL,CAAC;IAEO,WAAW,CAAC,MAAc;QAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,MAAM,OAAO,GAAG,GAAG,EAAE;gBACjB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;qBACvB,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;qBACrB,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAChC,CAAC,CAAC;YACF,OAAO,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,MAAM;QACV,OAAO,IAAA,mBAAU,GAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACrE,CAAC;CACJ;AAnOD,kCAmOC;AAED,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC;AACjD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAElF,SAAS,iBAAiB,CAAC,KAAa,EAAE,OAAe,EAAE,IAAwB;IAC/E,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,oCAAoC;IACtF,MAAM,OAAO,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAEzD,6DAA6D;IAC7D,MAAM,UAAU,GAAG,aAAa,OAAO,KAAK,CAAC;IAC7C,MAAM,UAAU,GAAG,GAAG,UAAU,GAAG,KAAK,GAAG,CAAC;IAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IAEjF,6DAA6D;IAC7D,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;IAEpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC;IAE3C,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACJ,6CAA6C;QAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;QAC7C,CAAC;IACL,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;AAC1C,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const CONFIG_FILENAME = "rhost.config.json";
|
|
2
|
+
export interface RhostConfig {
|
|
3
|
+
/**
|
|
4
|
+
* Path to a directory of execscript files that will be copied into the
|
|
5
|
+
* container at `/home/rhost/game/scripts`, replacing the built-in scripts.
|
|
6
|
+
* Relative to the directory containing `rhost.config.json` (or the cwd
|
|
7
|
+
* when config is supplied programmatically).
|
|
8
|
+
*/
|
|
9
|
+
scriptsDir?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Path to a MUSH server configuration file that will be copied into the
|
|
12
|
+
* container, replacing the default `mush.config` used by RhostMUSH.
|
|
13
|
+
* Relative to the directory containing `rhost.config.json`.
|
|
14
|
+
*/
|
|
15
|
+
mushConfig?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Load `rhost.config.json` from `searchDir` (default: `process.cwd()`).
|
|
19
|
+
*
|
|
20
|
+
* Returns `null` when no config file is found — this is not an error; the
|
|
21
|
+
* container simply starts with its built-in defaults.
|
|
22
|
+
*
|
|
23
|
+
* @throws SyntaxError when the file exists but is not valid JSON.
|
|
24
|
+
* @throws Error when `scriptsDir` or `mushConfig` resolve to a path
|
|
25
|
+
* outside the project directory (path traversal guard).
|
|
26
|
+
*/
|
|
27
|
+
export declare function loadConfig(searchDir?: string): RhostConfig | null;
|
|
28
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAEnD,MAAM,WAAW,WAAW;IACxB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,SAAS,GAAE,MAAsB,GAAG,WAAW,GAAG,IAAI,CAgChF"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CONFIG_FILENAME = void 0;
|
|
37
|
+
exports.loadConfig = loadConfig;
|
|
38
|
+
/**
|
|
39
|
+
* rhost.config.json loader
|
|
40
|
+
*
|
|
41
|
+
* Users can place a `rhost.config.json` at the root of their project to
|
|
42
|
+
* customise how RhostContainer starts. All paths in the config are resolved
|
|
43
|
+
* relative to the directory that contains the config file.
|
|
44
|
+
*
|
|
45
|
+
* Minimal example:
|
|
46
|
+
* ```json
|
|
47
|
+
* {
|
|
48
|
+
* "scriptsDir": "./scripts",
|
|
49
|
+
* "mushConfig": "./mush.conf"
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
const fs = __importStar(require("fs"));
|
|
54
|
+
const path = __importStar(require("path"));
|
|
55
|
+
exports.CONFIG_FILENAME = 'rhost.config.json';
|
|
56
|
+
/**
|
|
57
|
+
* Load `rhost.config.json` from `searchDir` (default: `process.cwd()`).
|
|
58
|
+
*
|
|
59
|
+
* Returns `null` when no config file is found — this is not an error; the
|
|
60
|
+
* container simply starts with its built-in defaults.
|
|
61
|
+
*
|
|
62
|
+
* @throws SyntaxError when the file exists but is not valid JSON.
|
|
63
|
+
* @throws Error when `scriptsDir` or `mushConfig` resolve to a path
|
|
64
|
+
* outside the project directory (path traversal guard).
|
|
65
|
+
*/
|
|
66
|
+
function loadConfig(searchDir = process.cwd()) {
|
|
67
|
+
const configPath = path.join(searchDir, exports.CONFIG_FILENAME);
|
|
68
|
+
if (!fs.existsSync(configPath)) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const raw = fs.readFileSync(configPath, 'utf8');
|
|
72
|
+
const parsed = JSON.parse(raw);
|
|
73
|
+
// Resolve relative paths to absolute, anchored at the config file location,
|
|
74
|
+
// then assert they remain within the project root (searchDir).
|
|
75
|
+
const root = path.resolve(searchDir) + path.sep;
|
|
76
|
+
const base = path.dirname(configPath);
|
|
77
|
+
function resolveConfined(field, value) {
|
|
78
|
+
const resolved = path.resolve(base, value);
|
|
79
|
+
if (!resolved.startsWith(root) && resolved !== path.resolve(searchDir)) {
|
|
80
|
+
throw new Error(`rhost.config.json: "${field}" must be within the project directory.\n` +
|
|
81
|
+
` Project root : ${path.resolve(searchDir)}\n` +
|
|
82
|
+
` Resolved path: ${resolved}`);
|
|
83
|
+
}
|
|
84
|
+
return resolved;
|
|
85
|
+
}
|
|
86
|
+
if (parsed.scriptsDir) {
|
|
87
|
+
parsed.scriptsDir = resolveConfined('scriptsDir', parsed.scriptsDir);
|
|
88
|
+
}
|
|
89
|
+
if (parsed.mushConfig) {
|
|
90
|
+
parsed.mushConfig = resolveConfined('mushConfig', parsed.mushConfig);
|
|
91
|
+
}
|
|
92
|
+
return parsed;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,gCAgCC;AA/ED;;;;;;;;;;;;;;GAcG;AACH,uCAAyB;AACzB,2CAA6B;AAEhB,QAAA,eAAe,GAAG,mBAAmB,CAAC;AAmBnD;;;;;;;;;GASG;AACH,SAAgB,UAAU,CAAC,YAAoB,OAAO,CAAC,GAAG,EAAE;IACxD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,uBAAe,CAAC,CAAC;IACzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;IAE9C,4EAA4E;IAC5E,+DAA+D;IAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEtC,SAAS,eAAe,CAAC,KAAa,EAAE,KAAa;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,QAAQ,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CACX,uBAAuB,KAAK,2CAA2C;gBACvE,oBAAoB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI;gBAC/C,oBAAoB,QAAQ,EAAE,CACjC,CAAC;QACN,CAAC;QACD,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,CAAC,UAAU,GAAG,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,CAAC,UAAU,GAAG,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
package/dist/container.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RhostConfig } from './config';
|
|
1
2
|
export interface ContainerConnectionInfo {
|
|
2
3
|
host: string;
|
|
3
4
|
port: number;
|
|
@@ -5,28 +6,40 @@ export interface ContainerConnectionInfo {
|
|
|
5
6
|
export declare class RhostContainer {
|
|
6
7
|
private started;
|
|
7
8
|
private readonly factory;
|
|
9
|
+
private readonly config;
|
|
8
10
|
private constructor();
|
|
9
11
|
/**
|
|
10
12
|
* Use a pre-built Docker image.
|
|
11
13
|
* Build it first with: `docker build -t rhostmush:latest .`
|
|
12
|
-
*
|
|
14
|
+
*
|
|
15
|
+
* @param image Docker image name. Defaults to `lcanady/rhostmush:latest`.
|
|
16
|
+
* @param config Optional config overrides. If omitted, `rhost.config.json`
|
|
17
|
+
* is loaded from `process.cwd()` when present.
|
|
13
18
|
*/
|
|
14
|
-
static fromImage(image?: string): RhostContainer;
|
|
19
|
+
static fromImage(image?: string, config?: RhostConfig): RhostContainer;
|
|
15
20
|
/**
|
|
16
21
|
* Build the image from the Dockerfile in the rhostmush-docker project root.
|
|
17
22
|
*
|
|
18
23
|
* The first build clones and compiles RhostMUSH from source — allow 5-10
|
|
19
24
|
* minutes. Subsequent runs reuse Docker's layer cache.
|
|
20
25
|
*
|
|
21
|
-
* @param projectRoot
|
|
26
|
+
* @param projectRoot Path to the rhostmush-docker directory.
|
|
22
27
|
* Defaults to `../` relative to this file (i.e. the repo root).
|
|
28
|
+
* @param config Optional config overrides. If omitted, `rhost.config.json`
|
|
29
|
+
* is loaded from `process.cwd()` when present.
|
|
23
30
|
*/
|
|
24
|
-
static fromSource(projectRoot?: string): RhostContainer;
|
|
31
|
+
static fromSource(projectRoot?: string, config?: RhostConfig): RhostContainer;
|
|
25
32
|
/**
|
|
26
33
|
* Start the container. Blocks until port 4201 is accepting connections.
|
|
27
34
|
* Returns the host and dynamically-assigned port to pass to `RhostClient`.
|
|
28
35
|
*
|
|
29
|
-
*
|
|
36
|
+
* If `config.scriptsDir` is set, the directory is copied into the container
|
|
37
|
+
* at `/home/rhost/game/scripts` before startup.
|
|
38
|
+
*
|
|
39
|
+
* If `config.mushConfig` is set, the file is copied into the container at
|
|
40
|
+
* `/home/rhost/game/mush.config` before startup.
|
|
41
|
+
*
|
|
42
|
+
* @param startupTimeout Max ms to wait for the server to be ready.
|
|
30
43
|
* Default: 120000 (2 min). Increase for slow machines or first builds.
|
|
31
44
|
*/
|
|
32
45
|
start(startupTimeout?: number): Promise<ContainerConnectionInfo>;
|
package/dist/container.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,WAAW,EAAc,MAAM,UAAU,CAAC;AAEnD,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AAUD,qBAAa,cAAc;IACvB,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC,OAAO;IAKP;;;;;;;OAOG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,SAA6B,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc;IAK1F;;;;;;;;;;OAUG;IACH,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,cAAc;IAY7E;;;;;;;;;;;;OAYG;IACG,KAAK,CAAC,cAAc,SAAU,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAqCvE,oEAAoE;IAC9D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,kEAAkE;IAClE,iBAAiB,IAAI,uBAAuB;CAS/C"}
|
package/dist/container.js
CHANGED
|
@@ -48,21 +48,42 @@ exports.RhostContainer = void 0;
|
|
|
48
48
|
* for port 4201 to be accepting connections before returning.
|
|
49
49
|
*
|
|
50
50
|
* Default wizard credentials for the minimal_db: Wizard / Nyctasia
|
|
51
|
+
*
|
|
52
|
+
* Custom scripts and config
|
|
53
|
+
* ─────────────────────────
|
|
54
|
+
* Pass a `RhostConfig` (or place `rhost.config.json` in your project root)
|
|
55
|
+
* to inject a custom scripts directory or MUSH config file into the container
|
|
56
|
+
* before it starts:
|
|
57
|
+
*
|
|
58
|
+
* RhostContainer.fromSource(undefined, { scriptsDir: './my-scripts' })
|
|
59
|
+
*
|
|
60
|
+
* See `src/config.ts` for the full `RhostConfig` interface.
|
|
51
61
|
*/
|
|
62
|
+
const fs = __importStar(require("fs"));
|
|
52
63
|
const path = __importStar(require("path"));
|
|
53
64
|
const testcontainers_1 = require("testcontainers");
|
|
65
|
+
const config_1 = require("./config");
|
|
66
|
+
/** Path inside the container where execscript files live. */
|
|
67
|
+
const CONTAINER_SCRIPTS_PATH = '/home/rhost/game/scripts';
|
|
68
|
+
/** Path inside the container where mush.config lives. */
|
|
69
|
+
const CONTAINER_MUSH_CONFIG_PATH = '/home/rhost/game/mush.config';
|
|
54
70
|
class RhostContainer {
|
|
55
|
-
constructor(factory) {
|
|
71
|
+
constructor(factory, config) {
|
|
56
72
|
this.started = null;
|
|
57
73
|
this.factory = factory;
|
|
74
|
+
this.config = config;
|
|
58
75
|
}
|
|
59
76
|
/**
|
|
60
77
|
* Use a pre-built Docker image.
|
|
61
78
|
* Build it first with: `docker build -t rhostmush:latest .`
|
|
62
|
-
*
|
|
79
|
+
*
|
|
80
|
+
* @param image Docker image name. Defaults to `lcanady/rhostmush:latest`.
|
|
81
|
+
* @param config Optional config overrides. If omitted, `rhost.config.json`
|
|
82
|
+
* is loaded from `process.cwd()` when present.
|
|
63
83
|
*/
|
|
64
|
-
static fromImage(image = 'lcanady/rhostmush:latest') {
|
|
65
|
-
|
|
84
|
+
static fromImage(image = 'lcanady/rhostmush:latest', config) {
|
|
85
|
+
const cfg = config ?? (0, config_1.loadConfig)() ?? {};
|
|
86
|
+
return new RhostContainer(async () => new testcontainers_1.GenericContainer(image), cfg);
|
|
66
87
|
}
|
|
67
88
|
/**
|
|
68
89
|
* Build the image from the Dockerfile in the rhostmush-docker project root.
|
|
@@ -70,26 +91,53 @@ class RhostContainer {
|
|
|
70
91
|
* The first build clones and compiles RhostMUSH from source — allow 5-10
|
|
71
92
|
* minutes. Subsequent runs reuse Docker's layer cache.
|
|
72
93
|
*
|
|
73
|
-
* @param projectRoot
|
|
94
|
+
* @param projectRoot Path to the rhostmush-docker directory.
|
|
74
95
|
* Defaults to `../` relative to this file (i.e. the repo root).
|
|
96
|
+
* @param config Optional config overrides. If omitted, `rhost.config.json`
|
|
97
|
+
* is loaded from `process.cwd()` when present.
|
|
75
98
|
*/
|
|
76
|
-
static fromSource(projectRoot) {
|
|
99
|
+
static fromSource(projectRoot, config) {
|
|
77
100
|
const root = projectRoot
|
|
78
101
|
? path.resolve(projectRoot)
|
|
79
102
|
: path.resolve(__dirname, '../');
|
|
103
|
+
const cfg = config ?? (0, config_1.loadConfig)() ?? {};
|
|
80
104
|
return new RhostContainer(async () => {
|
|
81
105
|
return testcontainers_1.GenericContainer.fromDockerfile(root).build();
|
|
82
|
-
});
|
|
106
|
+
}, cfg);
|
|
83
107
|
}
|
|
84
108
|
/**
|
|
85
109
|
* Start the container. Blocks until port 4201 is accepting connections.
|
|
86
110
|
* Returns the host and dynamically-assigned port to pass to `RhostClient`.
|
|
87
111
|
*
|
|
88
|
-
*
|
|
112
|
+
* If `config.scriptsDir` is set, the directory is copied into the container
|
|
113
|
+
* at `/home/rhost/game/scripts` before startup.
|
|
114
|
+
*
|
|
115
|
+
* If `config.mushConfig` is set, the file is copied into the container at
|
|
116
|
+
* `/home/rhost/game/mush.config` before startup.
|
|
117
|
+
*
|
|
118
|
+
* @param startupTimeout Max ms to wait for the server to be ready.
|
|
89
119
|
* Default: 120000 (2 min). Increase for slow machines or first builds.
|
|
90
120
|
*/
|
|
91
121
|
async start(startupTimeout = 120000) {
|
|
92
|
-
|
|
122
|
+
let base = await this.factory();
|
|
123
|
+
if (this.config.scriptsDir) {
|
|
124
|
+
if (!fs.existsSync(this.config.scriptsDir)) {
|
|
125
|
+
throw new Error(`RhostContainer: scriptsDir not found: ${this.config.scriptsDir}`);
|
|
126
|
+
}
|
|
127
|
+
base = base.withCopyDirectoriesToContainer([{
|
|
128
|
+
source: this.config.scriptsDir,
|
|
129
|
+
target: CONTAINER_SCRIPTS_PATH,
|
|
130
|
+
}]);
|
|
131
|
+
}
|
|
132
|
+
if (this.config.mushConfig) {
|
|
133
|
+
if (!fs.existsSync(this.config.mushConfig)) {
|
|
134
|
+
throw new Error(`RhostContainer: mushConfig not found: ${this.config.mushConfig}`);
|
|
135
|
+
}
|
|
136
|
+
base = base.withCopyFilesToContainer([{
|
|
137
|
+
source: this.config.mushConfig,
|
|
138
|
+
target: CONTAINER_MUSH_CONFIG_PATH,
|
|
139
|
+
}]);
|
|
140
|
+
}
|
|
93
141
|
this.started = await base
|
|
94
142
|
.withExposedPorts(4201)
|
|
95
143
|
.withWaitStrategy(testcontainers_1.Wait.forListeningPorts().withStartupTimeout(startupTimeout))
|
package/dist/container.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { RhostClient, RhostClientOptions, PreviewOptions, stripAnsi } from './client';
|
|
2
2
|
export { MushConnection } from './connection';
|
|
3
3
|
export { RhostContainer, ContainerConnectionInfo } from './container';
|
|
4
|
+
export { loadConfig, RhostConfig, CONFIG_FILENAME } from './config';
|
|
4
5
|
export { RhostAssert, RhostAssertionError, AssertionResult, isRhostError } from './assertions';
|
|
5
6
|
export { RhostExpect, RhostExpectError } from './expect';
|
|
6
7
|
export { RhostWorld, WorldSnapshot, WorldDiff, WorldObjectDiff, WorldSideEffectError } from './world';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGtF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG/F,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGtG,OAAO,EACH,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,GACjB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EACH,WAAW,EACX,aAAa,EACb,SAAS,EACT,WAAW,EACX,MAAM,EACN,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,UAAU,GACb,MAAM,UAAU,CAAC;AAGlB,OAAO,EACH,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,kBAAkB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1G,OAAO,EACH,MAAM,EACN,eAAe,EACf,eAAe,EACf,eAAe,EACf,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGtF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGpE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG/F,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAGtG,OAAO,EACH,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,GACjB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,OAAO,EACH,WAAW,EACX,aAAa,EACb,SAAS,EACT,WAAW,EACX,MAAM,EACN,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,UAAU,GACb,MAAM,UAAU,CAAC;AAGlB,OAAO,EACH,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG5E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,kBAAkB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1G,OAAO,EACH,MAAM,EACN,eAAe,EACf,eAAe,EACf,eAAe,EACf,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.discoverTestFiles = exports.RhostWatcher = exports.formatSnapshotDiff = exports.SnapshotManager = exports.restoreSnapshot = exports.snapshotObjects = exports.parseDeployFile = exports.deploy = exports.formatBenchResults = exports.runBench = exports.RhostBenchmark = exports.format = exports.BUILTIN_FUNCTIONS = exports.compatibilityReport = exports.validateFile = exports.validate = exports.RhostRunner = exports.Reporter = exports.PreflightError = exports.assertConfigEquals = exports.assertFunctionMissing = exports.assertFunctionExists = exports.preflightCheck = exports.preflight = exports.WorldSideEffectError = exports.WorldSnapshot = exports.RhostWorld = exports.RhostExpectError = exports.RhostExpect = exports.isRhostError = exports.RhostAssertionError = exports.RhostAssert = exports.RhostContainer = exports.MushConnection = exports.stripAnsi = exports.RhostClient = void 0;
|
|
3
|
+
exports.discoverTestFiles = exports.RhostWatcher = exports.formatSnapshotDiff = exports.SnapshotManager = exports.restoreSnapshot = exports.snapshotObjects = exports.parseDeployFile = exports.deploy = exports.formatBenchResults = exports.runBench = exports.RhostBenchmark = exports.format = exports.BUILTIN_FUNCTIONS = exports.compatibilityReport = exports.validateFile = exports.validate = exports.RhostRunner = exports.Reporter = exports.PreflightError = exports.assertConfigEquals = exports.assertFunctionMissing = exports.assertFunctionExists = exports.preflightCheck = exports.preflight = exports.WorldSideEffectError = exports.WorldSnapshot = exports.RhostWorld = exports.RhostExpectError = exports.RhostExpect = exports.isRhostError = exports.RhostAssertionError = exports.RhostAssert = exports.CONFIG_FILENAME = exports.loadConfig = exports.RhostContainer = exports.MushConnection = exports.stripAnsi = exports.RhostClient = void 0;
|
|
4
4
|
// Core client
|
|
5
5
|
var client_1 = require("./client");
|
|
6
6
|
Object.defineProperty(exports, "RhostClient", { enumerable: true, get: function () { return client_1.RhostClient; } });
|
|
@@ -11,6 +11,10 @@ Object.defineProperty(exports, "MushConnection", { enumerable: true, get: functi
|
|
|
11
11
|
// Container
|
|
12
12
|
var container_1 = require("./container");
|
|
13
13
|
Object.defineProperty(exports, "RhostContainer", { enumerable: true, get: function () { return container_1.RhostContainer; } });
|
|
14
|
+
// Config
|
|
15
|
+
var config_1 = require("./config");
|
|
16
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
|
|
17
|
+
Object.defineProperty(exports, "CONFIG_FILENAME", { enumerable: true, get: function () { return config_1.CONFIG_FILENAME; } });
|
|
14
18
|
// Assertions (backward-compat)
|
|
15
19
|
var assertions_1 = require("./assertions");
|
|
16
20
|
Object.defineProperty(exports, "RhostAssert", { enumerable: true, get: function () { return assertions_1.RhostAssert; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,cAAc;AACd,mCAAsF;AAA7E,qGAAA,WAAW,OAAA;AAAsC,mGAAA,SAAS,OAAA;AAEnE,aAAa;AACb,2CAA8C;AAArC,4GAAA,cAAc,OAAA;AAEvB,YAAY;AACZ,yCAAsE;AAA7D,2GAAA,cAAc,OAAA;AAEvB,+BAA+B;AAC/B,2CAA+F;AAAtF,yGAAA,WAAW,OAAA;AAAE,iHAAA,mBAAmB,OAAA;AAAmB,0GAAA,YAAY,OAAA;AAExE,iBAAiB;AACjB,mCAAyD;AAAhD,qGAAA,WAAW,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AAEtC,wBAAwB;AACxB,iCAAsG;AAA7F,mGAAA,UAAU,OAAA;AAAE,sGAAA,aAAa,OAAA;AAA8B,6GAAA,oBAAoB,OAAA;AAEpF,wBAAwB;AACxB,yCAUqB;AATjB,sGAAA,SAAS,OAAA;AACT,2GAAA,cAAc,OAAA;AACd,iHAAA,oBAAoB,OAAA;AACpB,kHAAA,qBAAqB,OAAA;AACrB,+GAAA,kBAAkB,OAAA;AAIlB,2GAAA,cAAc,OAAA;AAGlB,WAAW;AACX,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AAEjB,iBAAiB;AACjB,mCAakB;AAZd,qGAAA,WAAW,OAAA;AAcf,6CAA6C;AAC7C,yCAYqB;AAXjB,qGAAA,QAAQ,OAAA;AACR,yGAAA,YAAY,OAAA;AACZ,gHAAA,mBAAmB,OAAA;AAKnB,8GAAA,iBAAiB,OAAA;AAMrB,qBAAqB;AACrB,mDAA4E;AAAnE,mGAAA,MAAM,OAAA;AAEf,iBAAiB;AACjB,yCAA0G;AAAjG,2GAAA,cAAc,OAAA;AAAE,qGAAA,QAAQ,OAAA;AAAE,+GAAA,kBAAkB,OAAA;AAErD,kBAAkB;AAClB,uCASoB;AARhB,kGAAA,MAAM,OAAA;AACN,2GAAA,eAAe,OAAA;AACf,2GAAA,eAAe,OAAA;AACf,2GAAA,eAAe,OAAA;AAOnB,mBAAmB;AACnB,yCAAsH;AAA7G,4GAAA,eAAe,OAAA;AAAsD,+GAAA,kBAAkB,OAAA;AAEhG,aAAa;AACb,qCAA0E;AAAjE,uGAAA,YAAY,OAAA;AAAgB,4GAAA,iBAAiB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,cAAc;AACd,mCAAsF;AAA7E,qGAAA,WAAW,OAAA;AAAsC,mGAAA,SAAS,OAAA;AAEnE,aAAa;AACb,2CAA8C;AAArC,4GAAA,cAAc,OAAA;AAEvB,YAAY;AACZ,yCAAsE;AAA7D,2GAAA,cAAc,OAAA;AAEvB,SAAS;AACT,mCAAoE;AAA3D,oGAAA,UAAU,OAAA;AAAe,yGAAA,eAAe,OAAA;AAEjD,+BAA+B;AAC/B,2CAA+F;AAAtF,yGAAA,WAAW,OAAA;AAAE,iHAAA,mBAAmB,OAAA;AAAmB,0GAAA,YAAY,OAAA;AAExE,iBAAiB;AACjB,mCAAyD;AAAhD,qGAAA,WAAW,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AAEtC,wBAAwB;AACxB,iCAAsG;AAA7F,mGAAA,UAAU,OAAA;AAAE,sGAAA,aAAa,OAAA;AAA8B,6GAAA,oBAAoB,OAAA;AAEpF,wBAAwB;AACxB,yCAUqB;AATjB,sGAAA,SAAS,OAAA;AACT,2GAAA,cAAc,OAAA;AACd,iHAAA,oBAAoB,OAAA;AACpB,kHAAA,qBAAqB,OAAA;AACrB,+GAAA,kBAAkB,OAAA;AAIlB,2GAAA,cAAc,OAAA;AAGlB,WAAW;AACX,uCAAsC;AAA7B,oGAAA,QAAQ,OAAA;AAEjB,iBAAiB;AACjB,mCAakB;AAZd,qGAAA,WAAW,OAAA;AAcf,6CAA6C;AAC7C,yCAYqB;AAXjB,qGAAA,QAAQ,OAAA;AACR,yGAAA,YAAY,OAAA;AACZ,gHAAA,mBAAmB,OAAA;AAKnB,8GAAA,iBAAiB,OAAA;AAMrB,qBAAqB;AACrB,mDAA4E;AAAnE,mGAAA,MAAM,OAAA;AAEf,iBAAiB;AACjB,yCAA0G;AAAjG,2GAAA,cAAc,OAAA;AAAE,qGAAA,QAAQ,OAAA;AAAE,+GAAA,kBAAkB,OAAA;AAErD,kBAAkB;AAClB,uCASoB;AARhB,kGAAA,MAAM,OAAA;AACN,2GAAA,eAAe,OAAA;AACf,2GAAA,eAAe,OAAA;AACf,2GAAA,eAAe,OAAA;AAOnB,mBAAmB;AACnB,yCAAsH;AAA7G,4GAAA,eAAe,OAAA;AAAsD,+GAAA,kBAAkB,OAAA;AAEhG,aAAa;AACb,qCAA0E;AAAjE,uGAAA,YAAY,OAAA;AAAgB,4GAAA,iBAAiB,OAAA"}
|