@rhost/testkit 0.1.1 → 1.3.2

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 (110) hide show
  1. package/README.md +393 -5
  2. package/ROADMAP.md +241 -0
  3. package/dist/benchmark.d.ts +44 -0
  4. package/dist/benchmark.d.ts.map +1 -0
  5. package/dist/benchmark.js +118 -0
  6. package/dist/benchmark.js.map +1 -0
  7. package/dist/cli/deploy.d.ts +2 -0
  8. package/dist/cli/deploy.d.ts.map +1 -0
  9. package/dist/cli/deploy.js +120 -0
  10. package/dist/cli/deploy.js.map +1 -0
  11. package/dist/cli/fmt.d.ts +2 -0
  12. package/dist/cli/fmt.d.ts.map +1 -0
  13. package/dist/cli/fmt.js +119 -0
  14. package/dist/cli/fmt.js.map +1 -0
  15. package/dist/cli/index.d.ts +3 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +81 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/cli/init.d.ts +2 -0
  20. package/dist/cli/init.d.ts.map +1 -0
  21. package/dist/cli/init.js +210 -0
  22. package/dist/cli/init.js.map +1 -0
  23. package/dist/cli/validate.d.ts +2 -0
  24. package/dist/cli/validate.d.ts.map +1 -0
  25. package/dist/cli/validate.js +126 -0
  26. package/dist/cli/validate.js.map +1 -0
  27. package/dist/cli/watch.d.ts +2 -0
  28. package/dist/cli/watch.d.ts.map +1 -0
  29. package/dist/cli/watch.js +136 -0
  30. package/dist/cli/watch.js.map +1 -0
  31. package/dist/client.d.ts +56 -0
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +117 -30
  34. package/dist/client.js.map +1 -1
  35. package/dist/container.d.ts.map +1 -1
  36. package/dist/container.js +1 -1
  37. package/dist/container.js.map +1 -1
  38. package/dist/deployer.d.ts +86 -0
  39. package/dist/deployer.d.ts.map +1 -0
  40. package/dist/deployer.js +154 -0
  41. package/dist/deployer.js.map +1 -0
  42. package/dist/expect.d.ts +27 -1
  43. package/dist/expect.d.ts.map +1 -1
  44. package/dist/expect.js +47 -2
  45. package/dist/expect.js.map +1 -1
  46. package/dist/index.d.ts +10 -3
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +39 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/preflight.d.ts +70 -0
  51. package/dist/preflight.d.ts.map +1 -0
  52. package/dist/preflight.js +121 -0
  53. package/dist/preflight.js.map +1 -0
  54. package/dist/reporter.d.ts +2 -0
  55. package/dist/reporter.d.ts.map +1 -1
  56. package/dist/reporter.js +24 -1
  57. package/dist/reporter.js.map +1 -1
  58. package/dist/runner.d.ts +83 -2
  59. package/dist/runner.d.ts.map +1 -1
  60. package/dist/runner.js +137 -8
  61. package/dist/runner.js.map +1 -1
  62. package/dist/snapshots.d.ts +84 -0
  63. package/dist/snapshots.d.ts.map +1 -0
  64. package/dist/snapshots.js +230 -0
  65. package/dist/snapshots.js.map +1 -0
  66. package/dist/validator/builtins.d.ts +18 -0
  67. package/dist/validator/builtins.d.ts.map +1 -0
  68. package/dist/validator/builtins.js +265 -0
  69. package/dist/validator/builtins.js.map +1 -0
  70. package/dist/validator/checker.d.ts +13 -0
  71. package/dist/validator/checker.d.ts.map +1 -0
  72. package/dist/validator/checker.js +111 -0
  73. package/dist/validator/checker.js.map +1 -0
  74. package/dist/validator/clobber.d.ts +7 -0
  75. package/dist/validator/clobber.d.ts.map +1 -0
  76. package/dist/validator/clobber.js +102 -0
  77. package/dist/validator/clobber.js.map +1 -0
  78. package/dist/validator/compat.d.ts +19 -0
  79. package/dist/validator/compat.d.ts.map +1 -0
  80. package/dist/validator/compat.js +58 -0
  81. package/dist/validator/compat.js.map +1 -0
  82. package/dist/validator/formatter.d.ts +21 -0
  83. package/dist/validator/formatter.d.ts.map +1 -0
  84. package/dist/validator/formatter.js +120 -0
  85. package/dist/validator/formatter.js.map +1 -0
  86. package/dist/validator/index.d.ts +57 -0
  87. package/dist/validator/index.d.ts.map +1 -0
  88. package/dist/validator/index.js +133 -0
  89. package/dist/validator/index.js.map +1 -0
  90. package/dist/validator/parser.d.ts +16 -0
  91. package/dist/validator/parser.d.ts.map +1 -0
  92. package/dist/validator/parser.js +260 -0
  93. package/dist/validator/parser.js.map +1 -0
  94. package/dist/validator/tokenizer.d.ts +28 -0
  95. package/dist/validator/tokenizer.d.ts.map +1 -0
  96. package/dist/validator/tokenizer.js +174 -0
  97. package/dist/validator/tokenizer.js.map +1 -0
  98. package/dist/validator/types.d.ts +55 -0
  99. package/dist/validator/types.d.ts.map +1 -0
  100. package/dist/validator/types.js +6 -0
  101. package/dist/validator/types.js.map +1 -0
  102. package/dist/watcher.d.ts +44 -0
  103. package/dist/watcher.d.ts.map +1 -0
  104. package/dist/watcher.js +297 -0
  105. package/dist/watcher.js.map +1 -0
  106. package/dist/world.d.ts +79 -0
  107. package/dist/world.d.ts.map +1 -1
  108. package/dist/world.js +167 -1
  109. package/dist/world.js.map +1 -1
  110. package/package.json +19 -3
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ // ---------------------------------------------------------------------------
3
+ // RhostWatcher — file-watch driven test re-runner
4
+ // ---------------------------------------------------------------------------
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.RhostWatcher = void 0;
40
+ exports.discoverTestFiles = discoverTestFiles;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const child_process_1 = require("child_process");
44
+ // ---------------------------------------------------------------------------
45
+ // RhostWatcher class
46
+ // ---------------------------------------------------------------------------
47
+ class RhostWatcher {
48
+ constructor(options) {
49
+ this.options = options;
50
+ this.watcher = null;
51
+ this.debounceTimer = null;
52
+ this.pendingFiles = new Set();
53
+ this.currentProcess = null;
54
+ this.stopped = false;
55
+ this.runCount = 0;
56
+ this.debounceMs = options.debounceMs ?? 300;
57
+ this.clearScreen = options.clearScreen !== false;
58
+ }
59
+ /**
60
+ * Start watching. Runs an initial pass immediately, then re-runs on change.
61
+ * Blocks until `stop()` is called (or SIGINT).
62
+ */
63
+ async start() {
64
+ const files = this.options.files;
65
+ if (files.length === 0) {
66
+ console.error('rhost-testkit: No test files to watch.');
67
+ return;
68
+ }
69
+ this.printBanner(files);
70
+ // Initial run
71
+ await this.runFiles(files, 'initial');
72
+ if (this.stopped)
73
+ return;
74
+ // Set up filesystem watching
75
+ const watchRoot = this.commonRoot(files.map((f) => path.dirname(f)));
76
+ this.setupWatcher(watchRoot, new Set(files.map((f) => path.resolve(f))));
77
+ // Block until stopped
78
+ await new Promise((resolve) => {
79
+ const poll = setInterval(() => {
80
+ if (this.stopped) {
81
+ clearInterval(poll);
82
+ resolve();
83
+ }
84
+ }, 100);
85
+ // Ensure this timer doesn't prevent Node from exiting naturally
86
+ if (typeof poll.unref === 'function')
87
+ poll.unref();
88
+ });
89
+ }
90
+ /** Graceful shutdown: cancel pending timers, close watcher, kill child. */
91
+ async stop() {
92
+ this.stopped = true;
93
+ if (this.debounceTimer) {
94
+ clearTimeout(this.debounceTimer);
95
+ this.debounceTimer = null;
96
+ }
97
+ if (this.watcher) {
98
+ this.watcher.close();
99
+ this.watcher = null;
100
+ }
101
+ if (this.currentProcess) {
102
+ try {
103
+ this.currentProcess.kill('SIGTERM');
104
+ }
105
+ catch {
106
+ // already exited
107
+ }
108
+ this.currentProcess = null;
109
+ }
110
+ }
111
+ // -------------------------------------------------------------------------
112
+ // Internal: filesystem watcher setup
113
+ // -------------------------------------------------------------------------
114
+ setupWatcher(watchRoot, testFileSet) {
115
+ try {
116
+ this.watcher = fs.watch(watchRoot, { recursive: true }, (event, filename) => {
117
+ if (!filename || this.stopped)
118
+ return;
119
+ const resolved = path.isAbsolute(filename)
120
+ ? filename
121
+ : path.resolve(watchRoot, filename);
122
+ if (!testFileSet.has(resolved))
123
+ return;
124
+ this.pendingFiles.add(resolved);
125
+ if (this.debounceTimer)
126
+ clearTimeout(this.debounceTimer);
127
+ this.debounceTimer = setTimeout(() => {
128
+ this.debounceTimer = null;
129
+ const changed = Array.from(this.pendingFiles);
130
+ this.pendingFiles.clear();
131
+ this.runFiles(changed, 'changed').catch((err) => {
132
+ console.error('Watch run error:', err.message);
133
+ });
134
+ }, this.debounceMs);
135
+ });
136
+ this.watcher.on('error', (err) => {
137
+ if (!this.stopped) {
138
+ console.error('\nWatcher error:', err.message);
139
+ }
140
+ });
141
+ }
142
+ catch (err) {
143
+ console.error(`\nrhost-testkit: Failed to start file watcher: ${err.message}`);
144
+ console.error('Tip: if you need recursive watching on older Linux, install chokidar: npm install chokidar --save-dev');
145
+ }
146
+ }
147
+ // -------------------------------------------------------------------------
148
+ // Internal: running files
149
+ // -------------------------------------------------------------------------
150
+ async runFiles(files, reason) {
151
+ if (this.stopped)
152
+ return;
153
+ // Kill any already-running child process
154
+ if (this.currentProcess) {
155
+ try {
156
+ this.currentProcess.kill('SIGTERM');
157
+ }
158
+ catch { /* ignore */ }
159
+ this.currentProcess = null;
160
+ }
161
+ this.runCount++;
162
+ if (this.clearScreen && this.runCount > 1) {
163
+ process.stdout.write('\x1b[2J\x1b[H');
164
+ }
165
+ this.printRunHeader(files, reason);
166
+ for (const file of files) {
167
+ if (this.stopped)
168
+ break;
169
+ await this.spawnFile(file);
170
+ }
171
+ }
172
+ spawnFile(file) {
173
+ return new Promise((resolve) => {
174
+ const ext = path.extname(file).toLowerCase();
175
+ const isTs = ext === '.ts' || ext === '.tsx';
176
+ // For TypeScript files, prefer ts-node via npx (always available in devDeps).
177
+ // For JS, use the current Node binary directly.
178
+ const cmd = isTs ? 'npx' : process.execPath;
179
+ const args = isTs ? ['ts-node', '--transpile-only', file] : [file];
180
+ const proc = (0, child_process_1.spawn)(cmd, args, {
181
+ stdio: 'inherit',
182
+ shell: false,
183
+ env: { ...process.env },
184
+ });
185
+ this.currentProcess = proc;
186
+ proc.on('close', () => {
187
+ this.currentProcess = null;
188
+ resolve();
189
+ });
190
+ proc.on('error', (err) => {
191
+ if (isTs && err.message.includes('ENOENT')) {
192
+ console.error(`\nrhost-testkit: could not find ts-node. Install it: npm install ts-node --save-dev`);
193
+ }
194
+ else {
195
+ console.error(`\nrhost-testkit: failed to run ${path.basename(file)}: ${err.message}`);
196
+ }
197
+ this.currentProcess = null;
198
+ resolve();
199
+ });
200
+ });
201
+ }
202
+ // -------------------------------------------------------------------------
203
+ // Internal: output formatting
204
+ // -------------------------------------------------------------------------
205
+ printBanner(files) {
206
+ const cwd = process.cwd();
207
+ const rel = files.map((f) => path.relative(cwd, f));
208
+ console.log('\x1b[36m╔══════════════════════════════════════════════════╗\x1b[0m');
209
+ console.log('\x1b[36m║\x1b[0m rhost-testkit \x1b[33mwatch mode\x1b[0m' + ' '.repeat(20) + '\x1b[36m║\x1b[0m');
210
+ console.log('\x1b[36m╚══════════════════════════════════════════════════╝\x1b[0m');
211
+ console.log(`\nWatching ${files.length} file${files.length !== 1 ? 's' : ''}:`);
212
+ for (const f of rel) {
213
+ console.log(` \x1b[90m${f}\x1b[0m`);
214
+ }
215
+ console.log('\nPress \x1b[1mCtrl+C\x1b[0m to stop.\n');
216
+ }
217
+ printRunHeader(files, reason) {
218
+ const sep = '─'.repeat(50);
219
+ const cwd = process.cwd();
220
+ const rel = files.map((f) => path.relative(cwd, f)).join(', ');
221
+ if (reason === 'initial') {
222
+ console.log(`\x1b[36m${sep}\x1b[0m`);
223
+ console.log(` \x1b[1mInitial run\x1b[0m — ${files.length} file${files.length !== 1 ? 's' : ''}`);
224
+ console.log(`\x1b[36m${sep}\x1b[0m\n`);
225
+ }
226
+ else {
227
+ const now = new Date().toLocaleTimeString();
228
+ console.log(`\x1b[33m${sep}\x1b[0m`);
229
+ console.log(` \x1b[1mChanged\x1b[0m [${now}]: \x1b[33m${rel}\x1b[0m`);
230
+ console.log(`\x1b[33m${sep}\x1b[0m\n`);
231
+ }
232
+ }
233
+ // -------------------------------------------------------------------------
234
+ // Internal: utilities
235
+ // -------------------------------------------------------------------------
236
+ /**
237
+ * Find the longest common directory path shared by all given dirs.
238
+ * Falls back to '/' (or drive root on Windows) if nothing in common.
239
+ */
240
+ commonRoot(dirs) {
241
+ if (dirs.length === 0)
242
+ return process.cwd();
243
+ if (dirs.length === 1)
244
+ return dirs[0];
245
+ const sep = path.sep;
246
+ const parts = dirs.map((d) => path.resolve(d).split(sep));
247
+ const reference = parts[0];
248
+ const common = [];
249
+ for (let i = 0; i < reference.length; i++) {
250
+ if (parts.every((p) => p[i] === reference[i])) {
251
+ common.push(reference[i]);
252
+ }
253
+ else {
254
+ break;
255
+ }
256
+ }
257
+ const result = common.join(sep);
258
+ return result || sep;
259
+ }
260
+ }
261
+ exports.RhostWatcher = RhostWatcher;
262
+ // ---------------------------------------------------------------------------
263
+ // File discovery helper (used by the CLI)
264
+ // ---------------------------------------------------------------------------
265
+ /**
266
+ * Recursively walk `rootDir` and return all test files matching
267
+ * `*.test.ts`, `*.test.js`, `*.spec.ts`, `*.spec.js`.
268
+ * Skips `node_modules`, `dist`, `.git`, `.next`, `.turbo`.
269
+ */
270
+ function discoverTestFiles(rootDir) {
271
+ const files = [];
272
+ walkDir(path.resolve(rootDir), files);
273
+ return files;
274
+ }
275
+ const SKIP_DIRS = new Set(['node_modules', 'dist', '.git', '.next', '.turbo', 'coverage']);
276
+ const TEST_FILE_RE = /\.(test|spec)\.(ts|tsx|js|jsx)$/;
277
+ function walkDir(dir, out) {
278
+ if (SKIP_DIRS.has(path.basename(dir)))
279
+ return;
280
+ let entries;
281
+ try {
282
+ entries = fs.readdirSync(dir, { withFileTypes: true });
283
+ }
284
+ catch {
285
+ return;
286
+ }
287
+ for (const entry of entries) {
288
+ const full = path.join(dir, entry.name);
289
+ if (entry.isDirectory()) {
290
+ walkDir(full, out);
291
+ }
292
+ else if (entry.isFile() && TEST_FILE_RE.test(entry.name)) {
293
+ out.push(full);
294
+ }
295
+ }
296
+ }
297
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
package/dist/world.d.ts CHANGED
@@ -1,4 +1,33 @@
1
1
  import { RhostClient } from './client';
2
+ export interface WorldObjectDiff {
3
+ dbref: string;
4
+ added: string[];
5
+ removed: string[];
6
+ }
7
+ export interface WorldDiff {
8
+ clean: boolean;
9
+ created: string[];
10
+ destroyed: string[];
11
+ modified: WorldObjectDiff[];
12
+ }
13
+ export declare class WorldSideEffectError extends Error {
14
+ readonly diff: WorldDiff;
15
+ constructor(diff: WorldDiff, message: string);
16
+ }
17
+ interface ObjectSnapshot {
18
+ attrs: string[];
19
+ }
20
+ export declare class WorldSnapshot {
21
+ private readonly world;
22
+ /** Internal state map, exposed for test inspection as _state. */
23
+ readonly _state: Record<string, ObjectSnapshot>;
24
+ private readonly trackedDbrefsCopy;
25
+ constructor(world: RhostWorld, state: Record<string, ObjectSnapshot>, trackedDbrefsCopy: string[]);
26
+ /** Compare current world state against this snapshot and return a diff. */
27
+ diff(): Promise<WorldDiff>;
28
+ /** Throw a WorldSideEffectError if anything has changed since the snapshot. */
29
+ assertNoChanges(): Promise<void>;
30
+ }
2
31
  /**
3
32
  * RhostWorld — fixture manager for creating and cleaning up in-game objects
4
33
  * during test runs.
@@ -48,10 +77,59 @@ export declare class RhostWorld {
48
77
  * Sets a flag: `@set dbref=FLAG` or `@set dbref=!FLAG` to clear.
49
78
  */
50
79
  flag(dbref: string, flag: string, clear?: boolean): Promise<void>;
80
+ /**
81
+ * Emits a message to a target object: `@pemit target=msg`.
82
+ */
83
+ pemit(target: string, msg: string): Promise<void>;
84
+ /**
85
+ * Emits a message to all objects in a room: `@remit room=msg`.
86
+ */
87
+ remit(room: string, msg: string): Promise<void>;
88
+ /**
89
+ * Forces an object to execute a command: `@force actor=cmd`.
90
+ */
91
+ force(actor: string, cmd: string): Promise<void>;
92
+ /**
93
+ * Sets a parent on an object: `@parent child=parent`.
94
+ */
95
+ parent(child: string, parentDbref: string): Promise<void>;
96
+ /**
97
+ * Creates a zone room via `@dig name` and sets the INHERIT_ZONE flag.
98
+ * Registers the dbref for automatic cleanup.
99
+ * Returns the dbref string like '#42'.
100
+ */
101
+ zone(name: string): Promise<string>;
102
+ /**
103
+ * Adds an object to a channel: `@channel/add chan=dbref`.
104
+ */
105
+ addToChannel(dbref: string, chan: string): Promise<void>;
106
+ /**
107
+ * Sets a quota on an object: `@quota/set dbref=n`.
108
+ */
109
+ grantQuota(dbref: string, n: number): Promise<void>;
110
+ /**
111
+ * Pauses execution for `ms` milliseconds.
112
+ * This is a plain JavaScript delay — not a MUSH @wait command.
113
+ */
114
+ wait(ms: number): Promise<void>;
115
+ /**
116
+ * Sends mail: `@mail to=subj/body`.
117
+ */
118
+ mail(to: string, subj: string, body: string): Promise<void>;
51
119
  /**
52
120
  * Triggers `@trigger dbref/ATTR=args`. Returns captured output lines.
53
121
  */
54
122
  trigger(dbref: string, attr: string, args?: string): Promise<string[]>;
123
+ /**
124
+ * Capture the current state of all tracked objects.
125
+ * Use the returned `WorldSnapshot` to assert no side effects occurred.
126
+ *
127
+ * @example
128
+ * const snap = await world.snapshot();
129
+ * await client.eval('some_expression_with_possible_side_effects()');
130
+ * await snap.assertNoChanges();
131
+ */
132
+ snapshot(): Promise<WorldSnapshot>;
55
133
  /**
56
134
  * Destroys all objects created by this world instance (in reverse order).
57
135
  */
@@ -59,4 +137,5 @@ export declare class RhostWorld {
59
137
  /** How many objects are tracked for cleanup. */
60
138
  get size(): number;
61
139
  }
140
+ export {};
62
141
  //# sourceMappingURL=world.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IAGP,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,MAAM,CAAgB;gBAED,MAAM,EAAE,WAAW;IAEhD,OAAO,CAAC,UAAU;IAQlB;;;;;OAKG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAa1D;;;;OAIG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAexC;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpE;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKvD;;OAEG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5D;;OAEG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrE;;OAEG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS5E;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,gDAAgD;IAChD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACJ"}
1
+ {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"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"}
package/dist/world.js CHANGED
@@ -1,6 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RhostWorld = void 0;
3
+ exports.RhostWorld = exports.WorldSnapshot = exports.WorldSideEffectError = void 0;
4
+ class WorldSideEffectError extends Error {
5
+ constructor(diff, message) {
6
+ super(message);
7
+ this.diff = diff;
8
+ this.name = 'WorldSideEffectError';
9
+ }
10
+ }
11
+ exports.WorldSideEffectError = WorldSideEffectError;
12
+ class WorldSnapshot {
13
+ constructor(world, state, trackedDbrefsCopy) {
14
+ this.world = world;
15
+ this._state = state;
16
+ this.trackedDbrefsCopy = trackedDbrefsCopy;
17
+ }
18
+ /** Compare current world state against this snapshot and return a diff. */
19
+ async diff() {
20
+ const currentDbrefs = [...this.world.dbrefs];
21
+ const beforeSet = new Set(this.trackedDbrefsCopy);
22
+ const afterSet = new Set(currentDbrefs);
23
+ const created = currentDbrefs.filter((d) => !beforeSet.has(d));
24
+ const destroyed = this.trackedDbrefsCopy.filter((d) => !afterSet.has(d));
25
+ const modified = [];
26
+ // Check objects present in both before and after
27
+ for (const dbref of this.trackedDbrefsCopy) {
28
+ if (!afterSet.has(dbref))
29
+ continue;
30
+ const beforeAttrs = new Set(this._state[dbref]?.attrs ?? []);
31
+ const currentAttrsStr = await this.world.client.eval(`lattr(${dbref})`);
32
+ const currentAttrs = currentAttrsStr
33
+ ? currentAttrsStr.split(' ').filter(Boolean)
34
+ : [];
35
+ const afterAttrs = new Set(currentAttrs);
36
+ const added = currentAttrs.filter((a) => !beforeAttrs.has(a));
37
+ const removed = [...beforeAttrs].filter((a) => !afterAttrs.has(a));
38
+ if (added.length > 0 || removed.length > 0) {
39
+ modified.push({ dbref, added, removed });
40
+ }
41
+ }
42
+ const clean = created.length === 0 && destroyed.length === 0 && modified.length === 0;
43
+ return { clean, created, destroyed, modified };
44
+ }
45
+ /** Throw a WorldSideEffectError if anything has changed since the snapshot. */
46
+ async assertNoChanges() {
47
+ const d = await this.diff();
48
+ if (d.clean)
49
+ return;
50
+ const lines = ['World state changed after snapshot (unexpected side effects):'];
51
+ if (d.created.length > 0)
52
+ lines.push(` Created: ${d.created.join(', ')}`);
53
+ if (d.destroyed.length > 0)
54
+ lines.push(` Destroyed: ${d.destroyed.join(', ')}`);
55
+ for (const mod of d.modified) {
56
+ if (mod.added.length > 0)
57
+ lines.push(` ${mod.dbref} — added attrs: ${mod.added.join(', ')}`);
58
+ if (mod.removed.length > 0)
59
+ lines.push(` ${mod.dbref} — removed attrs: ${mod.removed.join(', ')}`);
60
+ }
61
+ throw new WorldSideEffectError(d, lines.join('\n'));
62
+ }
63
+ }
64
+ exports.WorldSnapshot = WorldSnapshot;
4
65
  /**
5
66
  * RhostWorld — fixture manager for creating and cleaning up in-game objects
6
67
  * during test runs.
@@ -77,6 +138,7 @@ class RhostWorld {
77
138
  * Gets an attribute by evaluating `get(dbref/ATTR)`.
78
139
  */
79
140
  async get(dbref, attr) {
141
+ this.guardInput('attr', attr);
80
142
  // Strip the '#' for the get() call — Rhost expects get(#42/ATTR)
81
143
  return (await this.client.eval(`get(${dbref}/${attr})`)).trim();
82
144
  }
@@ -95,6 +157,92 @@ class RhostWorld {
95
157
  const flagStr = clear ? `!${flag}` : flag;
96
158
  await this.client.command(`@set ${dbref}=${flagStr}`);
97
159
  }
160
+ /**
161
+ * Emits a message to a target object: `@pemit target=msg`.
162
+ */
163
+ async pemit(target, msg) {
164
+ this.guardInput('target', target);
165
+ this.guardInput('msg', msg);
166
+ await this.client.command(`@pemit ${target}=${msg}`);
167
+ }
168
+ /**
169
+ * Emits a message to all objects in a room: `@remit room=msg`.
170
+ */
171
+ async remit(room, msg) {
172
+ this.guardInput('room', room);
173
+ this.guardInput('msg', msg);
174
+ await this.client.command(`@remit ${room}=${msg}`);
175
+ }
176
+ /**
177
+ * Forces an object to execute a command: `@force actor=cmd`.
178
+ */
179
+ async force(actor, cmd) {
180
+ this.guardInput('actor', actor);
181
+ this.guardInput('cmd', cmd);
182
+ await this.client.command(`@force ${actor}=${cmd}`);
183
+ }
184
+ /**
185
+ * Sets a parent on an object: `@parent child=parent`.
186
+ */
187
+ async parent(child, parentDbref) {
188
+ this.guardInput('child', child);
189
+ this.guardInput('parent', parentDbref);
190
+ await this.client.command(`@parent ${child}=${parentDbref}`);
191
+ }
192
+ /**
193
+ * Creates a zone room via `@dig name` and sets the INHERIT_ZONE flag.
194
+ * Registers the dbref for automatic cleanup.
195
+ * Returns the dbref string like '#42'.
196
+ */
197
+ async zone(name) {
198
+ this.guardInput('name', name);
199
+ const lines = await this.client.command(`@dig ${name}`);
200
+ let dbref = null;
201
+ for (const line of lines) {
202
+ const m = line.match(/(?:room number\s+#?|#)(\d+)/i);
203
+ if (m) {
204
+ dbref = `#${m[1]}`;
205
+ break;
206
+ }
207
+ }
208
+ if (!dbref) {
209
+ throw new Error(`world.zone(${JSON.stringify(name)}) could not parse dbref from output: ${JSON.stringify(lines)}`);
210
+ }
211
+ await this.client.command(`@set ${dbref}=INHERIT_ZONE`);
212
+ this.dbrefs.push(dbref);
213
+ return dbref;
214
+ }
215
+ /**
216
+ * Adds an object to a channel: `@channel/add chan=dbref`.
217
+ */
218
+ async addToChannel(dbref, chan) {
219
+ this.guardInput('dbref', dbref);
220
+ this.guardInput('chan', chan);
221
+ await this.client.command(`@channel/add ${chan}=${dbref}`);
222
+ }
223
+ /**
224
+ * Sets a quota on an object: `@quota/set dbref=n`.
225
+ */
226
+ async grantQuota(dbref, n) {
227
+ this.guardInput('dbref', dbref);
228
+ await this.client.command(`@quota/set ${dbref}=${n}`);
229
+ }
230
+ /**
231
+ * Pauses execution for `ms` milliseconds.
232
+ * This is a plain JavaScript delay — not a MUSH @wait command.
233
+ */
234
+ wait(ms) {
235
+ return new Promise((resolve) => setTimeout(resolve, ms));
236
+ }
237
+ /**
238
+ * Sends mail: `@mail to=subj/body`.
239
+ */
240
+ async mail(to, subj, body) {
241
+ this.guardInput('to', to);
242
+ this.guardInput('subj', subj);
243
+ this.guardInput('body', body);
244
+ await this.client.command(`@mail ${to}=${subj}/${body}`);
245
+ }
98
246
  /**
99
247
  * Triggers `@trigger dbref/ATTR=args`. Returns captured output lines.
100
248
  */
@@ -107,6 +255,24 @@ class RhostWorld {
107
255
  : `@trigger ${dbref}/${attr}`;
108
256
  return this.client.command(cmd);
109
257
  }
258
+ /**
259
+ * Capture the current state of all tracked objects.
260
+ * Use the returned `WorldSnapshot` to assert no side effects occurred.
261
+ *
262
+ * @example
263
+ * const snap = await world.snapshot();
264
+ * await client.eval('some_expression_with_possible_side_effects()');
265
+ * await snap.assertNoChanges();
266
+ */
267
+ async snapshot() {
268
+ const state = {};
269
+ for (const dbref of this.dbrefs) {
270
+ const attrsStr = await this.client.eval(`lattr(${dbref})`);
271
+ const attrs = attrsStr ? attrsStr.split(' ').filter(Boolean) : [];
272
+ state[dbref] = { attrs };
273
+ }
274
+ return new WorldSnapshot(this, state, [...this.dbrefs]);
275
+ }
110
276
  /**
111
277
  * Destroys all objects created by this world instance (in reverse order).
112
278
  */
package/dist/world.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"world.js","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"world.js","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"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"}