fix(premiere-plugin-uxp): v2.0.2 — resolve temp folder defensively (no os.tmpdir)
UXP's `os` is a stripped subset of Node's — `os.tmpdir()` isn't exposed in
the build PPro 26.0.x ships, so both Import Proxy and Import Hi-Res failed
immediately with "os.tmpdir is not a function".
Replace with a defensive resolver tried in order:
1. os.tmpdir if present (newer UXP builds)
2. require('uxp').storage.localFileSystem.getTemporaryFolder() → .nativePath
(the documented portable approach)
3. process.env.TEMP / TMP / LOCALAPPDATA\\Temp (Windows always sets these)
4. os.homedir() + AppData/Local/Temp
tempPath() is now async; both Import.proxy and Import.hires await it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
f1a3d6a24a
commit
4bea3c94f8
2 changed files with 34 additions and 11 deletions
|
|
@ -2,7 +2,7 @@
|
|||
"manifestVersion": 5,
|
||||
"id": "net.wilddragon.dragonflight.uxp",
|
||||
"name": "Dragonflight MAM",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"main": "index.html",
|
||||
"host": {
|
||||
"app": "premierepro",
|
||||
|
|
|
|||
|
|
@ -6,16 +6,39 @@
|
|||
const Import = {};
|
||||
|
||||
// Use UXP's Node-style fs for streaming writes (avoids buffering multi-GB
|
||||
// files in memory) and the `os` module for the temp dir. Both are exposed
|
||||
// when manifest declares "localFileSystem": "fullAccess".
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
// files in memory). `os` is a stripped subset — `os.tmpdir` is not exposed
|
||||
// in all UXP builds, so resolve the temp folder defensively below.
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
let os; try { os = require('os'); } catch (_) { os = {}; }
|
||||
let uxpFs;
|
||||
try { uxpFs = require('uxp').storage.localFileSystem; } catch (_) { uxpFs = null; }
|
||||
|
||||
// Pick a temp folder dragonflight downloads land in. Cleared on each
|
||||
// download to keep disk usage bounded.
|
||||
function tempPath(safeName) {
|
||||
return path.join(os.tmpdir(), 'dragonflight-' + safeName);
|
||||
// Resolve a writable temp folder using whichever API this UXP build
|
||||
// actually exposes. Returns an absolute path string suitable for both
|
||||
// fs.createWriteStream and premierepro.Project.importFiles.
|
||||
async function getTempBase() {
|
||||
// 1. Node-style os.tmpdir (newer UXP, simplest case)
|
||||
try { if (os.tmpdir) { const t = os.tmpdir(); if (typeof t === 'string' && t.length) return t; } } catch (_) {}
|
||||
// 2. UXP storage API — documented portable approach
|
||||
if (uxpFs && uxpFs.getTemporaryFolder) {
|
||||
try { const tmp = await uxpFs.getTemporaryFolder(); if (tmp && tmp.nativePath) return tmp.nativePath; } catch (_) {}
|
||||
}
|
||||
// 3. Windows env vars (always set under PPro)
|
||||
try {
|
||||
const e = (typeof process !== 'undefined' && process.env) || {};
|
||||
if (e.TEMP) return e.TEMP;
|
||||
if (e.TMP) return e.TMP;
|
||||
if (e.LOCALAPPDATA) return path.join(e.LOCALAPPDATA, 'Temp');
|
||||
} catch (_) {}
|
||||
// 4. Homedir + Windows-style fallback
|
||||
try { if (os.homedir) return path.join(os.homedir(), 'AppData', 'Local', 'Temp'); } catch (_) {}
|
||||
throw new Error('Could not determine a writable temp folder on this system');
|
||||
}
|
||||
|
||||
async function tempPath(safeName) {
|
||||
const base = await getTempBase();
|
||||
return path.join(base, 'dragonflight-' + safeName);
|
||||
}
|
||||
|
||||
// Stream the body of a fetch Response to a file on disk.
|
||||
|
|
@ -115,7 +138,7 @@
|
|||
// ── Proxy import: /stream returns a same-host /video URL ──────────
|
||||
Import.proxy = async function (asset) {
|
||||
const safeName = UI.sanitizeFilename((asset.display_name || asset.filename || asset.id) + '.mp4');
|
||||
const dest = tempPath(safeName);
|
||||
const dest = await tempPath(safeName);
|
||||
|
||||
UI.showProgress('Resolving proxy URL…', 4);
|
||||
const { url } = await API.getProxyUrl(asset.id);
|
||||
|
|
@ -140,7 +163,7 @@
|
|||
UI.showProgress('Resolving hi-res URL…', 4);
|
||||
const info = await API.getHiresInfo(asset.id);
|
||||
const safeName = UI.sanitizeFilename(info.filename || (asset.display_name || asset.id) + '.' + (info.ext || 'mxf'));
|
||||
const dest = tempPath(safeName);
|
||||
const dest = await tempPath(safeName);
|
||||
|
||||
UI.showProgress('Downloading ' + safeName + ' (' + UI.formatBytes(Number(info.file_size || 0)) + ')…', 8);
|
||||
// info.url is presigned S3 — DO NOT add Bearer (would break signature).
|
||||
|
|
|
|||
Loading…
Reference in a new issue