diff --git a/services/premiere-plugin-uxp/src/api.js b/services/premiere-plugin-uxp/src/api.js index eb10f2b..cfb4cd6 100644 --- a/services/premiere-plugin-uxp/src/api.js +++ b/services/premiere-plugin-uxp/src/api.js @@ -1,4 +1,4 @@ -// Dragonflight API client — v2.1.4 +// Dragonflight API client — v2.1.5 // UXP fetch() notes: // • redirect:'manual' is NOT a supported option — UXP auto-follows redirects // • Authorization is stripped by UXP on cross-origin redirects (security fix) @@ -31,6 +31,21 @@ function trimUrl(u) { return String(u || '').replace(/\/+$/, ''); } + // Pull the human-readable error string out of an API error response. + // mam-api returns { error: "..." } (sometimes with a code); fall back to + // the raw text, then to the HTTP status line. + async function _errText(r) { + const raw = await r.text().catch(() => ''); + if (raw) { + try { + const j = JSON.parse(raw); + if (j && (j.error || j.message)) return j.error || j.message; + } catch (_) { /* not JSON — use raw */ } + return raw.slice(0, 240); + } + return 'HTTP ' + r.status; + } + // Core request — adds Bearer only for same-server URLs. // No redirect option — UXP handles redirects automatically. API.request = async function (urlOrPath, opts) { @@ -143,7 +158,11 @@ headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(clips), }); - if (!r.ok) throw new Error('Clip push HTTP ' + r.status); + if (!r.ok) { + // Surface the server's real reason (e.g. cross-project asset, bad frame + // fields) instead of a bare status code — conform failures were opaque. + throw new Error('Clip push failed (HTTP ' + r.status + '): ' + (await _errText(r))); + } return r.json(); };