makefx 1.0.4 → 1.0.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/makefx.mjs +71 -27
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -176,4 +176,4 @@ Run `makefx --help` or `makefx help <command>` for command-specific options.
176
176
  - Media generation guide: https://makefx.app/docs/media-playbooks
177
177
  - Source: https://github.com/krasnoperov/inventory
178
178
 
179
- Version: 1.0.4
179
+ Version: 1.0.5
package/makefx.mjs CHANGED
@@ -7,7 +7,9 @@ import { spawn } from "node:child_process";
7
7
  import { mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
8
8
  import os from "node:os";
9
9
  import path from "node:path";
10
- import { createReadStream } from "node:fs";
10
+ import { createReadStream, createWriteStream } from "node:fs";
11
+ import { Readable } from "node:stream";
12
+ import { pipeline } from "node:stream/promises";
11
13
  import https from "node:https";
12
14
  //#region \0rolldown/runtime.js
13
15
  var __create = Object.create;
@@ -3215,7 +3217,7 @@ var require_websocket = /* @__PURE__ */ __commonJSMin(((exports, module) => {
3215
3217
  var net = __require("net");
3216
3218
  var tls = __require("tls");
3217
3219
  var { randomBytes: randomBytes$1, createHash: createHash$2 } = __require("crypto");
3218
- var { Duplex: Duplex$2, Readable } = __require("stream");
3220
+ var { Duplex: Duplex$2, Readable: Readable$1 } = __require("stream");
3219
3221
  var { URL: URL$1 } = __require("url");
3220
3222
  var PerMessageDeflate = require_permessage_deflate();
3221
3223
  var Receiver = require_receiver();
@@ -5873,11 +5875,40 @@ async function downloadFile(input) {
5873
5875
  }
5874
5876
  const headers = {};
5875
5877
  if (input.accessToken) headers.Authorization = `Bearer ${input.accessToken}`;
5876
- const response = await fetch(`${input.baseUrl}${input.requestPath}`, { headers });
5877
- if (!response.ok) throw new Error(`Failed to download ${input.requestPath}: ${response.status} ${response.statusText}`);
5878
- const buffer = new Uint8Array(await response.arrayBuffer());
5878
+ const requestUrl = `${input.baseUrl}${input.requestPath}`;
5879
+ let response;
5880
+ try {
5881
+ response = await fetch(requestUrl, { headers });
5882
+ } catch (error) {
5883
+ throw new Error(`Failed to download ${input.requestPath}: ${formatFetchError(error)}`);
5884
+ }
5885
+ if (!response.ok) {
5886
+ const errorText = await readErrorText(response);
5887
+ throw new Error(`Failed to download ${input.requestPath}: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}`);
5888
+ }
5879
5889
  await mkdir(path.dirname(input.outputPath), { recursive: true });
5880
- await writeFile(input.outputPath, buffer);
5890
+ if (!response.body) throw new Error(`Failed to download ${input.requestPath}: response body was empty`);
5891
+ try {
5892
+ await pipeline(Readable.fromWeb(response.body), createWriteStream(input.outputPath));
5893
+ } catch (error) {
5894
+ throw new Error(`Failed to write download ${input.requestPath} to ${input.outputPath}: ${formatFetchError(error)}`);
5895
+ }
5896
+ return {
5897
+ headers: response.headers,
5898
+ requestUrl
5899
+ };
5900
+ }
5901
+ async function readErrorText(response) {
5902
+ try {
5903
+ return (await response.text()).slice(0, 500).trim();
5904
+ } catch {
5905
+ return "";
5906
+ }
5907
+ }
5908
+ function formatFetchError(error) {
5909
+ if (!(error instanceof Error)) return String(error);
5910
+ const cause = error.cause instanceof Error ? ` (${error.cause.message})` : "";
5911
+ return `${error.message}${cause}`;
5881
5912
  }
5882
5913
  async function downloadImage(input) {
5883
5914
  await downloadFile({
@@ -8679,24 +8710,24 @@ async function executeAssets(parsed, deps = defaultDeps$3) {
8679
8710
  const ref = parsed.positionals[1];
8680
8711
  if (!ref) throw new Error("Variant ID or legacy image key is required: makefx assets download <variant-id-or-legacy-image-key> -o <file>");
8681
8712
  const outputPath = getOutputPath(parsed);
8682
- const resolved = await resolveDownloadRef(ref, ctx, deps);
8683
- await deps.downloadFile({
8713
+ const resolved = resolveDownloadRef(ref, ctx);
8714
+ const metadata = getDownloadedVariantMetadata(resolved, await deps.downloadFile({
8684
8715
  baseUrl: ctx.baseUrl,
8685
8716
  accessToken: ctx.accessToken,
8686
8717
  requestPath: resolved.requestPath,
8687
8718
  outputPath,
8688
8719
  force: ctx.force
8689
- });
8720
+ }));
8690
8721
  await recordDownloadedMirror({
8691
8722
  ctx,
8692
8723
  deps,
8693
8724
  outputPath,
8694
- variant: resolved.variant
8725
+ variant: metadata.mirrorVariant
8695
8726
  });
8696
- deps.print(`Downloaded ${resolved.mediaKey} to ${outputPath}`);
8727
+ deps.print(`Downloaded ${metadata.mediaKey} to ${outputPath}`);
8697
8728
  return {
8698
8729
  type: "download",
8699
- mediaKey: resolved.mediaKey,
8730
+ mediaKey: metadata.mediaKey,
8700
8731
  outputPath,
8701
8732
  variant: resolved.variant
8702
8733
  };
@@ -8881,7 +8912,7 @@ async function fetchJson(ctx, deps, apiPath) {
8881
8912
  }
8882
8913
  return response.json();
8883
8914
  }
8884
- async function resolveDownloadRef(ref, ctx, deps) {
8915
+ function resolveDownloadRef(ref, ctx) {
8885
8916
  if (looksLikeStorageKey(ref)) {
8886
8917
  if (!isLegacyImageStorageKey(ref)) throw new Error("Direct media key downloads are not supported. Pass a variant ID so the authenticated media endpoint can authorize the download.");
8887
8918
  return {
@@ -8889,19 +8920,32 @@ async function resolveDownloadRef(ref, ctx, deps) {
8889
8920
  requestPath: `/api/images/${ref}`
8890
8921
  };
8891
8922
  }
8892
- const assets = await listAssets(ctx, deps);
8893
- for (const asset of assets) {
8894
- const variant = (await getAssetDetails(ctx, deps, asset.id)).variants.find((candidate) => candidate.id === ref);
8895
- if (!variant) continue;
8896
- const mediaKey = variant.media_key || variant.image_key;
8897
- if (mediaKey) return {
8898
- mediaKey,
8899
- requestPath: `/api/spaces/${encodeURIComponent(ctx.spaceId)}/variants/${encodeURIComponent(variant.id)}/media`,
8900
- variant
8901
- };
8902
- throw new Error(`Variant ${ref} has no downloadable media; status is ${variant.status}`);
8903
- }
8904
- throw new Error(`Variant not found in space ${ctx.spaceId}: ${ref}`);
8923
+ return {
8924
+ mediaKey: ref,
8925
+ requestPath: `/api/spaces/${encodeURIComponent(ctx.spaceId)}/variants/${encodeURIComponent(ref)}/media`
8926
+ };
8927
+ }
8928
+ function getDownloadedVariantMetadata(resolved, download) {
8929
+ if (resolved.variant) return {
8930
+ mediaKey: resolved.variant.media_key || resolved.variant.image_key || resolved.mediaKey,
8931
+ mirrorVariant: resolved.variant
8932
+ };
8933
+ const headers = download?.headers;
8934
+ const variantId = headers?.get("x-makefx-variant-id");
8935
+ const assetId = headers?.get("x-makefx-asset-id");
8936
+ const mediaKind = headers?.get("x-makefx-media-kind");
8937
+ const mediaKey = headers?.get("x-makefx-media-key") || resolved.mediaKey;
8938
+ if (!variantId || !assetId) return { mediaKey };
8939
+ return {
8940
+ mediaKey,
8941
+ mirrorVariant: {
8942
+ id: variantId,
8943
+ asset_id: assetId,
8944
+ media_kind: mediaKind || "image",
8945
+ media_key: mediaKey,
8946
+ image_key: mediaKey.startsWith("images/") ? mediaKey : null
8947
+ }
8948
+ };
8905
8949
  }
8906
8950
  function looksLikeStorageKey(value) {
8907
8951
  return value.includes("/") || [
@@ -9460,7 +9504,7 @@ Options:
9460
9504
  }
9461
9505
  //#endregion
9462
9506
  //#region src/cli/index.ts
9463
- var CLI_VERSION = "1.0.4+20bbdda462d5";
9507
+ var CLI_VERSION = "1.0.5+22056848942e";
9464
9508
  async function main() {
9465
9509
  const argv = process$1.argv.slice(2);
9466
9510
  if (argv[0] === "--") argv.shift();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makefx",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Command-line interface for AI-assisted game asset production with Make Effects.",
5
5
  "license": "MIT",
6
6
  "type": "module",