@ball-lang/cli 1.24.0 → 1.26.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/README.md +30 -2
- package/dist/cli_core.d.ts +90 -0
- package/dist/cli_core.d.ts.map +1 -0
- package/dist/cli_core.js +121 -0
- package/dist/cli_core.js.map +1 -0
- package/dist/compiled_cli.d.ts +276 -0
- package/dist/compiled_cli.d.ts.map +1 -0
- package/dist/compiled_cli.js +1938 -0
- package/dist/compiled_cli.js.map +1 -0
- package/dist/index.js +71 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/cli_core.ts +171 -0
- package/src/compiled_cli.ts +1736 -0
- package/src/index.ts +97 -3
package/src/index.ts
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
13
13
|
import { fileURLToPath } from 'node:url';
|
|
14
14
|
import { dirname, join } from 'node:path';
|
|
15
|
-
import { BallEngine } from '@ball-lang/engine';
|
|
16
15
|
import {
|
|
17
16
|
analyzeCapabilities,
|
|
18
17
|
checkPolicy,
|
|
@@ -20,6 +19,24 @@ import {
|
|
|
20
19
|
type Program,
|
|
21
20
|
} from './capability_analyzer.ts';
|
|
22
21
|
|
|
22
|
+
// `@ball-lang/engine` (compiled_engine.ts) and `./cli_core.ts`
|
|
23
|
+
// (compiled_cli.ts) are BOTH auto-generated by compiling a self-hosted Ball
|
|
24
|
+
// program through `@ball-lang/compiler`, and each installs its own runtime
|
|
25
|
+
// preamble as a side effect of module evaluation — including monkey-patching
|
|
26
|
+
// shared native prototypes (`Map.prototype.get`/`entries`/`keys`/`values`).
|
|
27
|
+
// That patching is idempotent against being installed *once*, but NOT against
|
|
28
|
+
// a second, independently-compiled preamble installing on top of it: the
|
|
29
|
+
// second artifact's "capture the native method before shadowing it" step
|
|
30
|
+
// actually captures the FIRST artifact's already-shadowed version, and a
|
|
31
|
+
// later call against a genuine native Map throws ("Method Map.prototype.entries
|
|
32
|
+
// called on incompatible receiver"). Every `ball` invocation is a fresh,
|
|
33
|
+
// single-command process, so the fix is to never let both load in the same
|
|
34
|
+
// one: import each compiled engine LAZILY, only inside the command handler
|
|
35
|
+
// that actually needs it (`cmdRun` / the info-validate-tree-version handlers
|
|
36
|
+
// below), instead of eagerly at module top level.
|
|
37
|
+
type EngineModule = typeof import('@ball-lang/engine');
|
|
38
|
+
type CliCoreModule = typeof import('./cli_core.ts');
|
|
39
|
+
|
|
23
40
|
const VERSION = readVersion();
|
|
24
41
|
|
|
25
42
|
const USAGE = `ball — the Ball language CLI (v${VERSION})
|
|
@@ -29,7 +46,11 @@ USAGE
|
|
|
29
46
|
|
|
30
47
|
COMMANDS
|
|
31
48
|
run <program.ball.json> Execute a Ball program and print stdout.
|
|
49
|
+
info <program.ball.json> Inspect ball program structure.
|
|
50
|
+
validate <program.ball.json> Check ball program validity.
|
|
51
|
+
tree <program.ball.json> Print module/import structure.
|
|
32
52
|
audit <program.ball.json> Static capability analysis (I/O, fs, network, ...).
|
|
53
|
+
version Print version.
|
|
33
54
|
|
|
34
55
|
OPTIONS
|
|
35
56
|
-h, --help Print this help message.
|
|
@@ -187,6 +208,7 @@ async function cmdRun(args: ParsedArgs): Promise<number> {
|
|
|
187
208
|
return 1;
|
|
188
209
|
}
|
|
189
210
|
|
|
211
|
+
const { BallEngine }: EngineModule = await import('@ball-lang/engine');
|
|
190
212
|
const program = loadProgram(programPath);
|
|
191
213
|
const engine = new BallEngine(program as any, {
|
|
192
214
|
stdout: (msg: string) => process.stdout.write(msg + '\n'),
|
|
@@ -205,6 +227,68 @@ async function cmdRun(args: ParsedArgs): Promise<number> {
|
|
|
205
227
|
return 0;
|
|
206
228
|
}
|
|
207
229
|
|
|
230
|
+
// ── info / validate / tree ──────────────────────────────────────────────────
|
|
231
|
+
//
|
|
232
|
+
// All three delegate their report text to `cli_core.ts` (a thin wrapper over
|
|
233
|
+
// `compiled_cli.ts`, compiled from `dart/shared/lib/cli_core.dart` — see
|
|
234
|
+
// CLAUDE.md's "Regenerate compiled TS CLI core" recipe), so the computed
|
|
235
|
+
// output is byte-identical to the native Dart CLI's (proven by
|
|
236
|
+
// `test/cli_core_parity_test.ts`). Only argv parsing / usage-error text stays
|
|
237
|
+
// TS-local, matching `cmdRun`/`cmdAudit`'s existing style.
|
|
238
|
+
|
|
239
|
+
async function cmdInfo(args: ParsedArgs): Promise<number> {
|
|
240
|
+
const programPath = args.positional[0];
|
|
241
|
+
if (!programPath) {
|
|
242
|
+
process.stderr.write('ball: info requires a program path\n\n');
|
|
243
|
+
process.stderr.write(USAGE);
|
|
244
|
+
return 1;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const cliCore: CliCoreModule = await import('./cli_core.ts');
|
|
248
|
+
const program = loadProgram(programPath);
|
|
249
|
+
process.stdout.write(cliCore.infoReport(program) + '\n');
|
|
250
|
+
return 0;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function cmdValidate(args: ParsedArgs): Promise<number> {
|
|
254
|
+
const programPath = args.positional[0];
|
|
255
|
+
if (!programPath) {
|
|
256
|
+
process.stderr.write('ball: validate requires a program path\n\n');
|
|
257
|
+
process.stderr.write(USAGE);
|
|
258
|
+
return 1;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const cliCore: CliCoreModule = await import('./cli_core.ts');
|
|
262
|
+
const program = loadProgram(programPath);
|
|
263
|
+
const report = cliCore.validateReport(program);
|
|
264
|
+
if (cliCore.validateOk(program)) {
|
|
265
|
+
process.stdout.write(report + '\n');
|
|
266
|
+
return 0;
|
|
267
|
+
}
|
|
268
|
+
process.stderr.write(report + '\n');
|
|
269
|
+
return 1;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async function cmdTree(args: ParsedArgs): Promise<number> {
|
|
273
|
+
const programPath = args.positional[0];
|
|
274
|
+
if (!programPath) {
|
|
275
|
+
process.stderr.write('ball: tree requires a program path\n\n');
|
|
276
|
+
process.stderr.write(USAGE);
|
|
277
|
+
return 1;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const cliCore: CliCoreModule = await import('./cli_core.ts');
|
|
281
|
+
const program = loadProgram(programPath);
|
|
282
|
+
process.stdout.write(cliCore.treeReport(program) + '\n');
|
|
283
|
+
return 0;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async function cmdVersion(): Promise<number> {
|
|
287
|
+
const cliCore: CliCoreModule = await import('./cli_core.ts');
|
|
288
|
+
process.stdout.write(`${cliCore.versionLine(VERSION)}\n`);
|
|
289
|
+
return 0;
|
|
290
|
+
}
|
|
291
|
+
|
|
208
292
|
function cmdAudit(args: ParsedArgs): number {
|
|
209
293
|
const programPath = args.positional[0];
|
|
210
294
|
if (!programPath) {
|
|
@@ -266,15 +350,25 @@ async function main(argv: string[]): Promise<number> {
|
|
|
266
350
|
}
|
|
267
351
|
|
|
268
352
|
if (args.flags['version'] === true || args.flags['v'] === true) {
|
|
269
|
-
|
|
270
|
-
|
|
353
|
+
// Matches the Dart CLI's `version`/`--version`/`-v` cases (all three
|
|
354
|
+
// dispatch to the same `cli_core.versionLine`) — see the `case 'version'`
|
|
355
|
+
// branch below for the bare-command spelling.
|
|
356
|
+
return await cmdVersion();
|
|
271
357
|
}
|
|
272
358
|
|
|
273
359
|
switch (args.command) {
|
|
274
360
|
case 'run':
|
|
275
361
|
return await cmdRun(args);
|
|
362
|
+
case 'info':
|
|
363
|
+
return await cmdInfo(args);
|
|
364
|
+
case 'validate':
|
|
365
|
+
return await cmdValidate(args);
|
|
366
|
+
case 'tree':
|
|
367
|
+
return await cmdTree(args);
|
|
276
368
|
case 'audit':
|
|
277
369
|
return cmdAudit(args);
|
|
370
|
+
case 'version':
|
|
371
|
+
return await cmdVersion();
|
|
278
372
|
case undefined:
|
|
279
373
|
process.stdout.write(USAGE);
|
|
280
374
|
return 0;
|