@ball-lang/cli 0.1.0 → 1.3.4
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 +2 -0
- package/dist/index.js +64 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +59 -8
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Command-line interface for the [Ball programming language](https://github.com/ball-lang/ball). Runs Ball programs and performs static capability analysis, powered by [`@ball-lang/engine`](https://www.npmjs.com/package/@ball-lang/engine).
|
|
6
6
|
|
|
7
|
+
> Note: `@ball-lang/cli` depends on a published `@ball-lang/engine`. Keep its dependency range in `package.json` aligned with the current engine major (the engine is at 1.x) so npm can resolve a compatible engine — a stale `^0.3.0` range will not accept engine 1.x.
|
|
8
|
+
|
|
7
9
|
## Install
|
|
8
10
|
|
|
9
11
|
```bash
|
package/dist/index.js
CHANGED
|
@@ -110,19 +110,57 @@ function loadProgram(path) {
|
|
|
110
110
|
}
|
|
111
111
|
fail(`Could not read ${path}: ${err.message}`);
|
|
112
112
|
}
|
|
113
|
+
let parsed;
|
|
113
114
|
try {
|
|
114
|
-
|
|
115
|
+
parsed = JSON.parse(raw);
|
|
115
116
|
}
|
|
116
117
|
catch (e) {
|
|
117
118
|
const err = e;
|
|
118
119
|
fail(`Invalid JSON in ${path}: ${err.message}`);
|
|
119
120
|
}
|
|
121
|
+
try {
|
|
122
|
+
return unwrapBallFile(parsed);
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
const err = e;
|
|
126
|
+
fail(`Invalid ball file ${path}: ${err.message}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Ball files are self-describing `google.protobuf.Any` envelopes. Strip the
|
|
131
|
+
* `@type` key (if present) to recover the bare proto3-JSON Program; bare
|
|
132
|
+
* Program objects without `@type` pass through unchanged.
|
|
133
|
+
*/
|
|
134
|
+
function unwrapBallFile(json) {
|
|
135
|
+
if (json === null || typeof json !== 'object' || Array.isArray(json))
|
|
136
|
+
return json;
|
|
137
|
+
const obj = json;
|
|
138
|
+
const type = obj['@type'];
|
|
139
|
+
if (type === undefined)
|
|
140
|
+
return json;
|
|
141
|
+
const ok = typeof type === 'string' &&
|
|
142
|
+
(type.endsWith('/ball.v1.Program') || type.endsWith('/ball.v1.Module'));
|
|
143
|
+
if (!ok)
|
|
144
|
+
throw new Error(`unknown ball file @type: ${JSON.stringify(type)}`);
|
|
145
|
+
const body = {};
|
|
146
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
147
|
+
if (k !== '@type')
|
|
148
|
+
body[k] = v;
|
|
149
|
+
}
|
|
150
|
+
return body;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Abort the current command with a user-facing error. Thrown (not
|
|
154
|
+
* process.exit) so the entrypoint can set process.exitCode and let the
|
|
155
|
+
* process drain naturally — a hard exit() discards buffered stdout/stderr
|
|
156
|
+
* pipe writes, truncating program output mid-stream (issue #138).
|
|
157
|
+
*/
|
|
158
|
+
class CliError extends Error {
|
|
120
159
|
}
|
|
121
160
|
function fail(message) {
|
|
122
|
-
|
|
123
|
-
process.exit(1);
|
|
161
|
+
throw new CliError(message);
|
|
124
162
|
}
|
|
125
|
-
function cmdRun(args) {
|
|
163
|
+
async function cmdRun(args) {
|
|
126
164
|
const programPath = args.positional[0];
|
|
127
165
|
if (!programPath) {
|
|
128
166
|
process.stderr.write('ball: run requires a program path\n\n');
|
|
@@ -134,8 +172,11 @@ function cmdRun(args) {
|
|
|
134
172
|
stdout: (msg) => process.stdout.write(msg + '\n'),
|
|
135
173
|
stderr: (msg) => process.stderr.write(msg + '\n'),
|
|
136
174
|
});
|
|
175
|
+
// run() is async (Promise<string[]>). Without the await, process.exit(0)
|
|
176
|
+
// fired before the program executed — `ball run` printed NOTHING and
|
|
177
|
+
// swallowed runtime errors as unhandled rejections (issue #138).
|
|
137
178
|
try {
|
|
138
|
-
engine.run();
|
|
179
|
+
await engine.run();
|
|
139
180
|
}
|
|
140
181
|
catch (e) {
|
|
141
182
|
const err = e;
|
|
@@ -188,7 +229,7 @@ function cmdAudit(args) {
|
|
|
188
229
|
}
|
|
189
230
|
return 0;
|
|
190
231
|
}
|
|
191
|
-
function main(argv) {
|
|
232
|
+
async function main(argv) {
|
|
192
233
|
const args = parseArgs(argv);
|
|
193
234
|
if (args.flags['help'] === true || args.flags['h'] === true) {
|
|
194
235
|
process.stdout.write(USAGE);
|
|
@@ -200,7 +241,7 @@ function main(argv) {
|
|
|
200
241
|
}
|
|
201
242
|
switch (args.command) {
|
|
202
243
|
case 'run':
|
|
203
|
-
return cmdRun(args);
|
|
244
|
+
return await cmdRun(args);
|
|
204
245
|
case 'audit':
|
|
205
246
|
return cmdAudit(args);
|
|
206
247
|
case undefined:
|
|
@@ -212,5 +253,20 @@ function main(argv) {
|
|
|
212
253
|
return 1;
|
|
213
254
|
}
|
|
214
255
|
}
|
|
215
|
-
process.exit(
|
|
256
|
+
// Set exitCode instead of process.exit(): a hard exit drops whatever part
|
|
257
|
+
// of the engine's output is still buffered in the stdout pipe (the fib
|
|
258
|
+
// test saw "0 1 1 2" of 8 lines). With exitCode the process exits when
|
|
259
|
+
// the event loop drains, after all writes flush.
|
|
260
|
+
try {
|
|
261
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
262
|
+
}
|
|
263
|
+
catch (e) {
|
|
264
|
+
if (e instanceof CliError) {
|
|
265
|
+
process.stderr.write(`ball: ${e.message}\n`);
|
|
266
|
+
process.exitCode = 1;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
throw e;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
216
272
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ball-lang/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"description": "Command-line interface for the Ball programming language. Runs Ball programs and performs static capability analysis.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"node": ">=22.0.0"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@ball-lang/engine": "^
|
|
60
|
+
"@ball-lang/engine": "^1.3.4"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@types/node": "^22.15.0",
|
package/src/index.ts
CHANGED
|
@@ -126,20 +126,55 @@ function loadProgram(path: string): Program {
|
|
|
126
126
|
}
|
|
127
127
|
fail(`Could not read ${path}: ${err.message}`);
|
|
128
128
|
}
|
|
129
|
+
let parsed: unknown;
|
|
129
130
|
try {
|
|
130
|
-
|
|
131
|
+
parsed = JSON.parse(raw);
|
|
131
132
|
} catch (e) {
|
|
132
133
|
const err = e as Error;
|
|
133
134
|
fail(`Invalid JSON in ${path}: ${err.message}`);
|
|
134
135
|
}
|
|
136
|
+
try {
|
|
137
|
+
return unwrapBallFile(parsed) as Program;
|
|
138
|
+
} catch (e) {
|
|
139
|
+
const err = e as Error;
|
|
140
|
+
fail(`Invalid ball file ${path}: ${err.message}`);
|
|
141
|
+
}
|
|
135
142
|
}
|
|
136
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Ball files are self-describing `google.protobuf.Any` envelopes. Strip the
|
|
146
|
+
* `@type` key (if present) to recover the bare proto3-JSON Program; bare
|
|
147
|
+
* Program objects without `@type` pass through unchanged.
|
|
148
|
+
*/
|
|
149
|
+
function unwrapBallFile(json: unknown): unknown {
|
|
150
|
+
if (json === null || typeof json !== 'object' || Array.isArray(json)) return json;
|
|
151
|
+
const obj = json as Record<string, unknown>;
|
|
152
|
+
const type = obj['@type'];
|
|
153
|
+
if (type === undefined) return json;
|
|
154
|
+
const ok =
|
|
155
|
+
typeof type === 'string' &&
|
|
156
|
+
(type.endsWith('/ball.v1.Program') || type.endsWith('/ball.v1.Module'));
|
|
157
|
+
if (!ok) throw new Error(`unknown ball file @type: ${JSON.stringify(type)}`);
|
|
158
|
+
const body: Record<string, unknown> = {};
|
|
159
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
160
|
+
if (k !== '@type') body[k] = v;
|
|
161
|
+
}
|
|
162
|
+
return body;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Abort the current command with a user-facing error. Thrown (not
|
|
167
|
+
* process.exit) so the entrypoint can set process.exitCode and let the
|
|
168
|
+
* process drain naturally — a hard exit() discards buffered stdout/stderr
|
|
169
|
+
* pipe writes, truncating program output mid-stream (issue #138).
|
|
170
|
+
*/
|
|
171
|
+
class CliError extends Error {}
|
|
172
|
+
|
|
137
173
|
function fail(message: string): never {
|
|
138
|
-
|
|
139
|
-
process.exit(1);
|
|
174
|
+
throw new CliError(message);
|
|
140
175
|
}
|
|
141
176
|
|
|
142
|
-
function cmdRun(args: ParsedArgs): number {
|
|
177
|
+
async function cmdRun(args: ParsedArgs): Promise<number> {
|
|
143
178
|
const programPath = args.positional[0];
|
|
144
179
|
if (!programPath) {
|
|
145
180
|
process.stderr.write('ball: run requires a program path\n\n');
|
|
@@ -153,8 +188,11 @@ function cmdRun(args: ParsedArgs): number {
|
|
|
153
188
|
stderr: (msg: string) => process.stderr.write(msg + '\n'),
|
|
154
189
|
});
|
|
155
190
|
|
|
191
|
+
// run() is async (Promise<string[]>). Without the await, process.exit(0)
|
|
192
|
+
// fired before the program executed — `ball run` printed NOTHING and
|
|
193
|
+
// swallowed runtime errors as unhandled rejections (issue #138).
|
|
156
194
|
try {
|
|
157
|
-
engine.run();
|
|
195
|
+
await engine.run();
|
|
158
196
|
} catch (e) {
|
|
159
197
|
const err = e as Error;
|
|
160
198
|
fail(`runtime error: ${err.message}`);
|
|
@@ -214,7 +252,7 @@ function cmdAudit(args: ParsedArgs): number {
|
|
|
214
252
|
return 0;
|
|
215
253
|
}
|
|
216
254
|
|
|
217
|
-
function main(argv: string[]): number {
|
|
255
|
+
async function main(argv: string[]): Promise<number> {
|
|
218
256
|
const args = parseArgs(argv);
|
|
219
257
|
|
|
220
258
|
if (args.flags['help'] === true || args.flags['h'] === true) {
|
|
@@ -229,7 +267,7 @@ function main(argv: string[]): number {
|
|
|
229
267
|
|
|
230
268
|
switch (args.command) {
|
|
231
269
|
case 'run':
|
|
232
|
-
return cmdRun(args);
|
|
270
|
+
return await cmdRun(args);
|
|
233
271
|
case 'audit':
|
|
234
272
|
return cmdAudit(args);
|
|
235
273
|
case undefined:
|
|
@@ -242,4 +280,17 @@ function main(argv: string[]): number {
|
|
|
242
280
|
}
|
|
243
281
|
}
|
|
244
282
|
|
|
245
|
-
process.exit(
|
|
283
|
+
// Set exitCode instead of process.exit(): a hard exit drops whatever part
|
|
284
|
+
// of the engine's output is still buffered in the stdout pipe (the fib
|
|
285
|
+
// test saw "0 1 1 2" of 8 lines). With exitCode the process exits when
|
|
286
|
+
// the event loop drains, after all writes flush.
|
|
287
|
+
try {
|
|
288
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
289
|
+
} catch (e) {
|
|
290
|
+
if (e instanceof CliError) {
|
|
291
|
+
process.stderr.write(`ball: ${e.message}\n`);
|
|
292
|
+
process.exitCode = 1;
|
|
293
|
+
} else {
|
|
294
|
+
throw e;
|
|
295
|
+
}
|
|
296
|
+
}
|