@rhost/testkit 0.1.0 → 1.3.1

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 +48 -0
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +113 -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 @@
1
+ {"version":3,"file":"fmt.js","sourceRoot":"","sources":["../../src/cli/fmt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // ---------------------------------------------------------------------------
4
+ // rhost-testkit CLI entry point
5
+ // ---------------------------------------------------------------------------
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const validate_1 = require("./validate");
8
+ const watch_1 = require("./watch");
9
+ const init_1 = require("./init");
10
+ const deploy_1 = require("./deploy");
11
+ const fmt_1 = require("./fmt");
12
+ const args = process.argv.slice(2);
13
+ const cmd = args[0];
14
+ switch (cmd) {
15
+ case 'validate':
16
+ (0, validate_1.runValidateCli)(args.slice(1));
17
+ break;
18
+ case 'watch':
19
+ (0, watch_1.runWatchCli)(args.slice(1));
20
+ break;
21
+ case 'init':
22
+ (0, init_1.runInitCli)(args.slice(1));
23
+ break;
24
+ case 'deploy':
25
+ (0, deploy_1.runDeployCli)(args.slice(1));
26
+ break;
27
+ case 'fmt':
28
+ (0, fmt_1.runFmtCli)(args.slice(1));
29
+ break;
30
+ case '--version':
31
+ case '-v': {
32
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
33
+ const pkg = require('../../package.json');
34
+ console.log(pkg.version);
35
+ break;
36
+ }
37
+ case '--help':
38
+ case '-h':
39
+ case undefined:
40
+ printHelp();
41
+ break;
42
+ default:
43
+ console.error(`rhost-testkit: unknown command '${cmd}'\n`);
44
+ printHelp();
45
+ process.exit(1);
46
+ }
47
+ function printHelp() {
48
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
49
+ const pkg = require('../../package.json');
50
+ console.log(`
51
+ rhost-testkit v${pkg.version} — MUSHcode testing toolkit
52
+
53
+ USAGE
54
+ rhost-testkit <command> [options]
55
+
56
+ COMMANDS
57
+ validate Validate a softcode expression offline (no server needed)
58
+ watch Watch test files and re-run on change
59
+ init Generate CI/CD workflow templates
60
+ deploy Deploy a softcode file with automatic rollback on failure
61
+ fmt Format a softcode file (normalize whitespace)
62
+
63
+ OPTIONS
64
+ -v, --version Print version and exit
65
+ -h, --help Show this help
66
+
67
+ Run \`rhost-testkit <command> --help\` for command-specific options.
68
+
69
+ EXAMPLES
70
+ rhost-testkit validate "add(2,3)"
71
+ rhost-testkit validate --file mycode.mush
72
+ rhost-testkit watch
73
+ rhost-testkit watch src/__tests__/math.test.ts
74
+ rhost-testkit init --ci github
75
+ rhost-testkit init --ci gitlab
76
+ rhost-testkit deploy --file mycode.mush --dry-run
77
+ rhost-testkit fmt mycode.mush
78
+ rhost-testkit fmt --check mycode.mush
79
+ `.trim());
80
+ }
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";;AACA,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;;AAE9E,yCAA4C;AAC5C,mCAAsC;AACtC,iCAAoC;AACpC,qCAAwC;AACxC,+BAAkC;AAElC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAEpB,QAAQ,GAAG,EAAE,CAAC;IACZ,KAAK,UAAU;QACb,IAAA,yBAAc,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM;IAER,KAAK,OAAO;QACV,IAAA,mBAAW,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM;IAER,KAAK,MAAM;QACT,IAAA,iBAAU,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM;IAER,KAAK,QAAQ;QACX,IAAA,qBAAY,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM;IAER,KAAK,KAAK;QACR,IAAA,eAAS,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM;IAER,KAAK,WAAW,CAAC;IACjB,KAAK,IAAI,CAAC,CAAC,CAAC;QACV,8DAA8D;QAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM;IACR,CAAC;IAED,KAAK,QAAQ,CAAC;IACd,KAAK,IAAI,CAAC;IACV,KAAK,SAAS;QACZ,SAAS,EAAE,CAAC;QACZ,MAAM;IAER;QACE,OAAO,CAAC,KAAK,CAAC,mCAAmC,GAAG,KAAK,CAAC,CAAC;QAC3D,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,SAAS;IAChB,8DAA8D;IAC9D,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC;iBACG,GAAG,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4B3B,CAAC,IAAI,EAAE,CAAC,CAAC;AACV,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function runInitCli(args: string[], cwd?: string): void;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AA8FA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,IAAI,CA2D5E"}
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ // ---------------------------------------------------------------------------
3
+ // CLI handler: rhost-testkit init
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.runInitCli = runInitCli;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ // ---------------------------------------------------------------------------
43
+ // Templates
44
+ // ---------------------------------------------------------------------------
45
+ const GITHUB_WORKFLOW = `\
46
+ name: MUSH Tests
47
+
48
+ on: [push, pull_request]
49
+
50
+ jobs:
51
+ mush-tests:
52
+ runs-on: ubuntu-latest
53
+ permissions:
54
+ contents: read
55
+
56
+ steps:
57
+ - uses: actions/checkout@v4
58
+
59
+ - name: Set up Node.js
60
+ uses: actions/setup-node@v4
61
+ with:
62
+ node-version: '20'
63
+
64
+ - name: Install dependencies
65
+ run: npm ci
66
+
67
+ - name: Run tests
68
+ run: npm test
69
+
70
+ # ── Optional: integration tests against a real RhostMUSH container ──
71
+ # Uncomment the steps below, set RHOST_PASS in your repo secrets, and
72
+ # ensure your test:integration script exists in package.json.
73
+ #
74
+ # - name: Start RhostMUSH container
75
+ # run: |
76
+ # docker run -d --name rhost -p 4201:4201 rhostmush/rhostmush:latest
77
+ # sleep 10
78
+ #
79
+ # - name: Run integration tests
80
+ # run: npm run test:integration
81
+ # env:
82
+ # RHOST_HOST: localhost
83
+ # RHOST_PORT: 4201
84
+ # RHOST_PASS: \${{ secrets.RHOST_PASS }}
85
+ #
86
+ # - name: Stop container
87
+ # if: always()
88
+ # run: docker rm -f rhost
89
+ `;
90
+ const GITLAB_CI = `\
91
+ stages:
92
+ - test
93
+
94
+ mush-tests:
95
+ stage: test
96
+ image: node:20
97
+ script:
98
+ - npm ci
99
+ - npm test
100
+
101
+ # ── Optional: integration tests against a real RhostMUSH container ──
102
+ # Uncomment the job below, add RHOST_PASS to your CI/CD variables, and
103
+ # ensure your test:integration script exists in package.json.
104
+ #
105
+ # mush-integration:
106
+ # stage: test
107
+ # image: docker:latest
108
+ # services:
109
+ # - docker:dind
110
+ # variables:
111
+ # DOCKER_TLS_CERTDIR: ""
112
+ # before_script:
113
+ # - docker run -d --name rhost -p 4201:4201 rhostmush/rhostmush:latest
114
+ # - sleep 10
115
+ # script:
116
+ # - apk add --no-cache nodejs npm
117
+ # - npm ci
118
+ # - RHOST_HOST=localhost RHOST_PORT=4201 npm run test:integration
119
+ # after_script:
120
+ # - docker rm -f rhost
121
+ `;
122
+ // ---------------------------------------------------------------------------
123
+ // Public handler
124
+ // ---------------------------------------------------------------------------
125
+ function runInitCli(args, cwd = process.cwd()) {
126
+ let ci = null;
127
+ let force = false;
128
+ for (let i = 0; i < args.length; i++) {
129
+ const arg = args[i];
130
+ if (arg === '--ci') {
131
+ const val = args[++i];
132
+ if (!val || val.startsWith('-')) {
133
+ die("--ci requires a platform argument: 'github' or 'gitlab'");
134
+ }
135
+ ci = val;
136
+ }
137
+ else if (arg === '--force') {
138
+ force = true;
139
+ }
140
+ else if (arg === '--help' || arg === '-h') {
141
+ printHelp();
142
+ process.exit(0);
143
+ }
144
+ else if (!arg.startsWith('-')) {
145
+ die(`Unexpected argument: ${arg}`);
146
+ }
147
+ else {
148
+ die(`Unknown option: ${arg}`);
149
+ }
150
+ }
151
+ if (!ci) {
152
+ console.error("rhost-testkit init: --ci <platform> is required\n");
153
+ printHelp();
154
+ process.exit(1);
155
+ }
156
+ const targets = {
157
+ github: {
158
+ file: path.join(cwd, '.github', 'workflows', 'mush-tests.yml'),
159
+ content: GITHUB_WORKFLOW,
160
+ },
161
+ gitlab: {
162
+ file: path.join(cwd, '.gitlab-ci.yml'),
163
+ content: GITLAB_CI,
164
+ },
165
+ };
166
+ const target = targets[ci];
167
+ if (!target) {
168
+ die(`--ci: unknown platform '${ci}' — use 'github' or 'gitlab'`);
169
+ }
170
+ if (fs.existsSync(target.file) && !force) {
171
+ console.warn(`rhost-testkit init: ${target.file} already exists. Use --force to overwrite.`);
172
+ process.exit(0);
173
+ }
174
+ const dir = path.dirname(target.file);
175
+ if (!fs.existsSync(dir)) {
176
+ fs.mkdirSync(dir, { recursive: true });
177
+ }
178
+ fs.writeFileSync(target.file, target.content, 'utf8');
179
+ console.log(`rhost-testkit init: wrote ${target.file}`);
180
+ }
181
+ // ---------------------------------------------------------------------------
182
+ // Help
183
+ // ---------------------------------------------------------------------------
184
+ function printHelp() {
185
+ console.log(`
186
+ USAGE
187
+ rhost-testkit init --ci <platform>
188
+
189
+ PLATFORMS
190
+ github Generate .github/workflows/mush-tests.yml
191
+ gitlab Generate .gitlab-ci.yml
192
+
193
+ OPTIONS
194
+ --force Overwrite an existing file
195
+ -h, --help Show this help
196
+
197
+ EXAMPLES
198
+ rhost-testkit init --ci github
199
+ rhost-testkit init --ci gitlab
200
+ rhost-testkit init --ci github --force
201
+ `.trim());
202
+ }
203
+ // ---------------------------------------------------------------------------
204
+ // Helpers
205
+ // ---------------------------------------------------------------------------
206
+ function die(msg) {
207
+ console.error(`rhost-testkit init: ${msg}`);
208
+ process.exit(1);
209
+ }
210
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runValidateCli(args: string[]): void;
2
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/cli/validate.ts"],"names":[],"mappings":"AAMA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkDnD"}
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ // ---------------------------------------------------------------------------
3
+ // CLI handler: rhost-testkit validate
4
+ // ---------------------------------------------------------------------------
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runValidateCli = runValidateCli;
7
+ const validator_1 = require("../validator");
8
+ function runValidateCli(args) {
9
+ let expression = null;
10
+ let filePath = null;
11
+ let jsonOutput = false;
12
+ for (let i = 0; i < args.length; i++) {
13
+ const arg = args[i];
14
+ if (arg === '--file' || arg === '-f') {
15
+ filePath = args[++i];
16
+ if (!filePath) {
17
+ die('--file requires a path argument');
18
+ }
19
+ }
20
+ else if (arg === '--json') {
21
+ jsonOutput = true;
22
+ }
23
+ else if (arg === '--help' || arg === '-h') {
24
+ printHelp();
25
+ process.exit(0);
26
+ }
27
+ else if (!arg.startsWith('-')) {
28
+ expression = arg;
29
+ }
30
+ else {
31
+ die(`Unknown option: ${arg}`);
32
+ }
33
+ }
34
+ if (!expression && !filePath) {
35
+ console.error('Error: provide a softcode expression or --file <path>\n');
36
+ printHelp();
37
+ process.exit(1);
38
+ }
39
+ if (expression && filePath) {
40
+ die('Provide either an expression or --file, not both');
41
+ }
42
+ let result;
43
+ try {
44
+ result = filePath ? (0, validator_1.validateFile)(filePath) : (0, validator_1.validate)(expression);
45
+ }
46
+ catch (err) {
47
+ die(`Could not read file: ${err.message}`);
48
+ return; // unreachable — die() throws
49
+ }
50
+ if (jsonOutput) {
51
+ console.log(JSON.stringify(result, null, 2));
52
+ }
53
+ else {
54
+ printHuman(result, filePath ?? expression);
55
+ }
56
+ process.exit(result.valid ? 0 : 1);
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // Human-readable output
60
+ // ---------------------------------------------------------------------------
61
+ function printHuman(result, source) {
62
+ const { valid, diagnostics } = result;
63
+ const statusIcon = valid ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
64
+ const statusWord = valid ? '\x1b[32mvalid\x1b[0m' : '\x1b[31minvalid\x1b[0m';
65
+ console.log(`${statusIcon} ${statusWord} \x1b[90m${source}\x1b[0m`);
66
+ if (diagnostics.length === 0)
67
+ return;
68
+ const errors = diagnostics.filter((d) => d.severity === 'error');
69
+ const warnings = diagnostics.filter((d) => d.severity === 'warning');
70
+ for (const d of errors) {
71
+ console.log(formatDiag(d));
72
+ }
73
+ for (const d of warnings) {
74
+ console.log(formatDiag(d));
75
+ }
76
+ }
77
+ function formatDiag(d) {
78
+ const icon = d.severity === 'error' ? '\x1b[31m ✗\x1b[0m' : '\x1b[33m ⚠\x1b[0m';
79
+ return `${icon} \x1b[2m[${d.code}]\x1b[0m ${d.message} \x1b[90m(offset ${d.offset})\x1b[0m`;
80
+ }
81
+ // ---------------------------------------------------------------------------
82
+ // Help text
83
+ // ---------------------------------------------------------------------------
84
+ function printHelp() {
85
+ console.log(`
86
+ USAGE
87
+ rhost-testkit validate "<expression>"
88
+ rhost-testkit validate --file <path>
89
+
90
+ OPTIONS
91
+ -f, --file <path> Validate a softcode expression stored in a file
92
+ --json Output machine-readable JSON instead of human text
93
+ -h, --help Show this help
94
+
95
+ EXIT CODES
96
+ 0 Expression is valid (no errors; warnings are allowed)
97
+ 1 Expression has one or more errors
98
+
99
+ DIAGNOSTIC CODES
100
+ E001 Unclosed '(' — missing closing ')'
101
+ E002 Unexpected ')' with no matching '('
102
+ E003 Unclosed '[' — missing closing ']'
103
+ E004 Unexpected ']' with no matching '['
104
+ E006 Too few arguments for a known built-in function
105
+ E007 Too many arguments for a known built-in function
106
+ W001 Empty expression
107
+ W002 Empty argument (e.g. add(,3))
108
+ W003 Deprecated function
109
+ W005 Unknown function name (may be a UDF — only a warning)
110
+
111
+ EXAMPLES
112
+ rhost-testkit validate "add(2,3)"
113
+ rhost-testkit validate "add(2,3" # E001: unclosed paren
114
+ rhost-testkit validate "abs(1,2)" # E007: too many args
115
+ rhost-testkit validate --file funcs.mush
116
+ rhost-testkit validate --json "add(2,3)"
117
+ `.trim());
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // Helpers
121
+ // ---------------------------------------------------------------------------
122
+ function die(msg) {
123
+ console.error(`rhost-testkit validate: ${msg}`);
124
+ process.exit(1);
125
+ }
126
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/cli/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runWatchCli(args: string[]): void;
2
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/cli/watch.ts"],"names":[],"mappings":"AAOA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA4DhD"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ // ---------------------------------------------------------------------------
3
+ // CLI handler: rhost-testkit watch
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.runWatchCli = runWatchCli;
40
+ const path = __importStar(require("path"));
41
+ const watcher_1 = require("../watcher");
42
+ function runWatchCli(args) {
43
+ const opts = { files: [] };
44
+ const positional = [];
45
+ for (let i = 0; i < args.length; i++) {
46
+ const arg = args[i];
47
+ if (arg === '--debounce' || arg === '-d') {
48
+ const ms = parseInt(args[++i], 10);
49
+ if (isNaN(ms) || ms < 0) {
50
+ die('--debounce requires a non-negative integer (milliseconds)');
51
+ }
52
+ opts.debounceMs = ms;
53
+ }
54
+ else if (arg === '--no-clear') {
55
+ opts.clearScreen = false;
56
+ }
57
+ else if (arg === '--help' || arg === '-h') {
58
+ printHelp();
59
+ process.exit(0);
60
+ }
61
+ else if (!arg.startsWith('-')) {
62
+ positional.push(arg);
63
+ }
64
+ else {
65
+ die(`Unknown option: ${arg}`);
66
+ }
67
+ }
68
+ // Resolve test files: positional args take priority, else auto-discover
69
+ if (positional.length > 0) {
70
+ opts.files = positional.map((f) => path.resolve(f));
71
+ const missing = opts.files.filter((f) => {
72
+ try {
73
+ require('fs').accessSync(f);
74
+ return false;
75
+ }
76
+ catch {
77
+ return true;
78
+ }
79
+ });
80
+ if (missing.length > 0) {
81
+ die(`File(s) not found:\n${missing.map((f) => ` ${f}`).join('\n')}`);
82
+ }
83
+ }
84
+ else {
85
+ opts.files = (0, watcher_1.discoverTestFiles)(process.cwd());
86
+ if (opts.files.length === 0) {
87
+ console.error('rhost-testkit watch: No test files found.\n' +
88
+ 'Test files must match: *.test.ts, *.test.js, *.spec.ts, or *.spec.js\n' +
89
+ 'Or pass specific files: rhost-testkit watch path/to/test.ts');
90
+ process.exit(1);
91
+ }
92
+ }
93
+ const watcher = new watcher_1.RhostWatcher(opts);
94
+ // Clean shutdown on Ctrl+C
95
+ process.on('SIGINT', () => {
96
+ watcher.stop().then(() => {
97
+ console.log('\nWatch mode stopped.');
98
+ process.exit(0);
99
+ });
100
+ });
101
+ watcher.start().catch((err) => {
102
+ console.error('rhost-testkit watch: fatal error:', err.message);
103
+ process.exit(1);
104
+ });
105
+ }
106
+ // ---------------------------------------------------------------------------
107
+ // Help
108
+ // ---------------------------------------------------------------------------
109
+ function printHelp() {
110
+ console.log(`
111
+ USAGE
112
+ rhost-testkit watch [test-files...]
113
+
114
+ If no files are given, rhost-testkit auto-discovers *.test.ts / *.spec.ts
115
+ files under the current directory (excluding node_modules, dist, .git).
116
+
117
+ OPTIONS
118
+ -d, --debounce <ms> Debounce delay before re-running (default: 300)
119
+ --no-clear Don't clear the terminal between runs
120
+ -h, --help Show this help
121
+
122
+ EXAMPLES
123
+ rhost-testkit watch
124
+ rhost-testkit watch src/__tests__/math.test.ts
125
+ rhost-testkit watch src/__tests__/*.test.ts
126
+ rhost-testkit watch --debounce 500 --no-clear
127
+ `.trim());
128
+ }
129
+ // ---------------------------------------------------------------------------
130
+ // Helpers
131
+ // ---------------------------------------------------------------------------
132
+ function die(msg) {
133
+ console.error(`rhost-testkit watch: ${msg}`);
134
+ process.exit(1);
135
+ }
136
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/cli/watch.ts"],"names":[],"mappings":"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"}