makefx 2.0.1 → 2.0.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,11 @@
3
3
  The 1.x packages were built from the first version of makefx.app and do not
4
4
  work with the current service.
5
5
 
6
+ ## 2.0.2 — 2026-09-26
7
+
8
+ - `create --wait --json` now prints each asset's final ready or failed state instead of the queued state captured before waiting, and exits 1 with the failed asset's error when waiting ends in failure.
9
+ - Usage and unexpected errors are now also written as JSON to stdout under `--json`, and the `upload` error for an unrecognized file extension now names the supported upload types.
10
+
6
11
  ## 2.0.1 — 2026-09-24
7
12
 
8
13
  - Always print the login authorization URL, callback port, and an SSH tunnel command with the detected hostname so remote login can be completed from a local browser.
package/dist/makefx.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import process4 from "node:process";
4
+ import process5 from "node:process";
5
5
 
6
6
  // src/lib/project.ts
7
7
  var SERVICE_NAME = "makefx.app";
@@ -13,7 +13,7 @@ var ENVIRONMENT_ORIGINS = {
13
13
  };
14
14
 
15
15
  // src/lib/version.ts
16
- var CLI_VERSION = true ? "2.0.1" : "0.0.0-dev";
16
+ var CLI_VERSION = true ? "2.0.2" : "0.0.0-dev";
17
17
 
18
18
  // src/commands/convenience.ts
19
19
  import { randomUUID } from "node:crypto";
@@ -870,6 +870,7 @@ async function handleOpen(parsed, dependencies = defaults) {
870
870
 
871
871
  // src/commands/create.ts
872
872
  import { randomUUID as randomUUID2 } from "node:crypto";
873
+ import process2 from "node:process";
873
874
 
874
875
  // src/lib/json-schema.ts
875
876
  import { isDeepStrictEqual } from "node:util";
@@ -1093,7 +1094,7 @@ function validateJsonSchema(schema, input) {
1093
1094
  // src/commands/create.ts
1094
1095
  var defaults2 = {
1095
1096
  client: authenticatedToolClient,
1096
- write: (text2) => process.stdout.write(`${text2}
1097
+ write: (text2) => process2.stdout.write(`${text2}
1097
1098
  `),
1098
1099
  id: randomUUID2
1099
1100
  };
@@ -1360,13 +1361,13 @@ async function handleCreate(parsed, dependencies = defaults2) {
1360
1361
  }
1361
1362
  const args = createToolArguments(prepared, entry, dependencies.id());
1362
1363
  const created = await client.call("create_asset", args);
1363
- const assets = Array.isArray(created.assets) ? created.assets : [];
1364
+ let assets = Array.isArray(created.assets) ? created.assets : [];
1364
1365
  if (parsed.options.wait === "true" && !assets.some(({ renders_in }) => renders_in === "browser")) {
1365
1366
  const spaceId2 = prepared.spaceId;
1366
- const failures = await Promise.all(
1367
+ assets = await Promise.all(
1367
1368
  assets.map(async (asset) => {
1368
1369
  const assetId = asset.asset_id;
1369
- if (typeof assetId !== "string") return null;
1370
+ if (typeof assetId !== "string") return asset;
1370
1371
  while (true) {
1371
1372
  const result = await client.call("get_asset", {
1372
1373
  space_id: spaceId2,
@@ -1374,16 +1375,26 @@ async function handleCreate(parsed, dependencies = defaults2) {
1374
1375
  wait_seconds: 60
1375
1376
  });
1376
1377
  const current = result.asset;
1377
- if (current?.status === "ready") return null;
1378
- if (current?.status === "failed") {
1379
- const error = current.error;
1380
- return error?.message ?? `Asset ${assetId} failed.`;
1378
+ if (current?.status === "ready" || current?.status === "failed") {
1379
+ return current ? { ...asset, ...current } : asset;
1381
1380
  }
1382
1381
  }
1383
1382
  })
1384
1383
  );
1385
- const messages = failures.filter((message) => message !== null);
1386
- if (messages.length > 0) throw new Error(messages.join("\n"));
1384
+ created.assets = assets;
1385
+ const failed = assets.filter((asset) => asset.status === "failed");
1386
+ if (failed.length > 0) {
1387
+ if (parsed.options.json === "true") {
1388
+ dependencies.write(JSON.stringify(created, null, 2));
1389
+ process2.exitCode = 1;
1390
+ return;
1391
+ }
1392
+ const messages = failed.map((asset) => {
1393
+ const error = asset.error;
1394
+ return error?.message ?? `Asset ${String(asset.asset_id)} failed.`;
1395
+ });
1396
+ throw new Error(messages.join("\n"));
1397
+ }
1387
1398
  }
1388
1399
  if (parsed.options.json === "true") {
1389
1400
  dependencies.write(JSON.stringify(created, null, 2));
@@ -1397,7 +1408,7 @@ async function handleCreate(parsed, dependencies = defaults2) {
1397
1408
  }
1398
1409
 
1399
1410
  // src/commands/login.ts
1400
- import process2 from "node:process";
1411
+ import process3 from "node:process";
1401
1412
  import { hostname } from "node:os";
1402
1413
  async function handleLogin(parsed) {
1403
1414
  const isLocal = parsed.options.local === "true";
@@ -1408,7 +1419,7 @@ async function handleLogin(parsed) {
1408
1419
  const insecure = isLocal;
1409
1420
  if (insecure) {
1410
1421
  console.log("\u26A0\uFE0F SSL certificate verification disabled (local dev mode)");
1411
- process2.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
1422
+ process3.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
1412
1423
  }
1413
1424
  console.log(`Starting login for environment "${env}" using ${baseUrl}`);
1414
1425
  const server = await discoverAuthorizationServer(baseUrl);
@@ -1496,20 +1507,20 @@ async function handleLogout(parsed) {
1496
1507
  }
1497
1508
 
1498
1509
  // src/commands/mcp.ts
1499
- import process3 from "node:process";
1510
+ import process4 from "node:process";
1500
1511
  async function handleMcp(parsed) {
1501
1512
  const env = parsed.options.local === "true" ? "local" : parsed.options.env ?? DEFAULT_ENVIRONMENT;
1502
1513
  const loginHint = `Run: ${cliCommand()} login --env ${env}`;
1503
1514
  const stored = await loadStoredConfig(env);
1504
1515
  if (!stored) {
1505
1516
  console.error(`Not logged in for "${env}". ${loginHint}`);
1506
- process3.exitCode = 1;
1517
+ process4.exitCode = 1;
1507
1518
  return;
1508
1519
  }
1509
1520
  const config = await ensureFreshConfig(stored);
1510
1521
  if (!config) {
1511
1522
  console.error(`Credentials for "${env}" have expired. ${loginHint}`);
1512
- process3.exitCode = 1;
1523
+ process4.exitCode = 1;
1513
1524
  return;
1514
1525
  }
1515
1526
  const bridge = createMcpBridge({ config });
@@ -1519,15 +1530,15 @@ async function handleMcp(parsed) {
1519
1530
  case "accepted":
1520
1531
  return;
1521
1532
  case "response":
1522
- if (outcome.text) process3.stdout.write(`${outcome.text}
1533
+ if (outcome.text) process4.stdout.write(`${outcome.text}
1523
1534
  `);
1524
1535
  return;
1525
1536
  case "unauthorized":
1526
- if (outcome.text) process3.stdout.write(`${outcome.text}
1537
+ if (outcome.text) process4.stdout.write(`${outcome.text}
1527
1538
  `);
1528
1539
  console.error(`Access to "${env}" was revoked or has expired. ${loginHint}`);
1529
- process3.exitCode = 1;
1530
- process3.stdin.destroy();
1540
+ process4.exitCode = 1;
1541
+ process4.stdin.destroy();
1531
1542
  return;
1532
1543
  case "unreachable":
1533
1544
  console.error(`MCP request failed: ${outcome.message}`);
@@ -1536,8 +1547,8 @@ async function handleMcp(parsed) {
1536
1547
  }
1537
1548
  let buffer = "";
1538
1549
  const pending = [];
1539
- process3.stdin.setEncoding("utf8");
1540
- for await (const chunk of process3.stdin) {
1550
+ process4.stdin.setEncoding("utf8");
1551
+ for await (const chunk of process4.stdin) {
1541
1552
  buffer += chunk;
1542
1553
  let newline = buffer.indexOf("\n");
1543
1554
  while (newline !== -1) {
@@ -2339,7 +2350,12 @@ function uploadMime(parsed, path2) {
2339
2350
  const explicit = optional5(parsed, "mime");
2340
2351
  if (explicit) return explicit;
2341
2352
  const inferred = MIME_BY_EXTENSION[extname(path2).toLowerCase()];
2342
- if (!inferred) throw new CliUsageError("Cannot infer media type from --file; pass --mime <type>.");
2353
+ if (!inferred) {
2354
+ const supported = Object.keys(MIME_BY_EXTENSION).sort().join(", ");
2355
+ throw new CliUsageError(
2356
+ `Cannot infer media type from --file; supported uploads are ${supported} \u2014 pass --mime <type> to override.`
2357
+ );
2358
+ }
2343
2359
  return inferred;
2344
2360
  }
2345
2361
  function declaredRecipe(parsed) {
@@ -2563,11 +2579,16 @@ function reportCommandError(error, json2, output) {
2563
2579
  return 1;
2564
2580
  }
2565
2581
  if (error instanceof CliUsageError) {
2582
+ if (json2) output.stdout(`${JSON.stringify({ code: "usage", message: error.message })}
2583
+ `);
2566
2584
  output.stderr(`Error: ${error.message}
2567
2585
  `);
2568
2586
  return 2;
2569
2587
  }
2570
- output.stderr(`Error: ${error instanceof Error ? error.message : "Unexpected error occurred"}
2588
+ const message = error instanceof Error ? error.message : "Unexpected error occurred";
2589
+ if (json2) output.stdout(`${JSON.stringify({ code: "error", message })}
2590
+ `);
2591
+ output.stderr(`Error: ${message}
2571
2592
  `);
2572
2593
  return 1;
2573
2594
  }
@@ -2862,7 +2883,7 @@ async function handleSpaceVisibilityCommand(command, parsed, dependencies = defa
2862
2883
 
2863
2884
  // src/index.ts
2864
2885
  async function main() {
2865
- const [, , command, ...args] = process4.argv;
2886
+ const [, , command, ...args] = process5.argv;
2866
2887
  try {
2867
2888
  if (!command || command === "--help") {
2868
2889
  printHelp();
@@ -2882,9 +2903,9 @@ async function main() {
2882
2903
  await dispatchCommand(command, parsed);
2883
2904
  } catch (error) {
2884
2905
  const parsed = parseArgs(args);
2885
- process4.exitCode = reportCommandError(error, parsed.options.json === "true", {
2886
- stdout: (text2) => process4.stdout.write(text2),
2887
- stderr: (text2) => process4.stderr.write(text2)
2906
+ process5.exitCode = reportCommandError(error, parsed.options.json === "true", {
2907
+ stdout: (text2) => process5.stdout.write(text2),
2908
+ stderr: (text2) => process5.stderr.write(text2)
2888
2909
  });
2889
2910
  }
2890
2911
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makefx",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "Make images, video, and audio on makefx.app from your terminal or coding agent.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",