@ball-lang/cli 0.1.0 → 1.3.5

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 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
- return JSON.parse(raw);
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
- process.stderr.write(`ball: ${message}\n`);
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(main(process.argv.slice(2)));
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": "0.1.0",
3
+ "version": "1.3.5",
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": "^0.2.0"
60
+ "@ball-lang/engine": "^1.3.5"
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
- return JSON.parse(raw) as Program;
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
- process.stderr.write(`ball: ${message}\n`);
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(main(process.argv.slice(2)));
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
+ }