Compare commits

..

4 commits

Author SHA1 Message Date
8aece9cbc4 fix(premiere-plugin): make build pipeline portable to Windows PowerShell 5.1
End-to-end verification on a fresh Windows machine surfaced three issues:

1. pwsh isn't installed by default — Windows ships powershell.exe (5.1).
   Switched all script invocations + docs from `pwsh` to `powershell`.
2. .NET's strict XML parser rejects manifest.xml because the <Resources>
   comment legally contains `--` (inside `--enable-nodejs`/`--mixed-context`
   CEF flag names). Switched build-installer.ps1 to regex extraction,
   matching what build-zxp.mjs already does.
3. winget installs Inno Setup 6 to %LOCALAPPDATA%\Programs by default, not
   Program Files (x86). Added the user-scope path to the ISCC.exe fallback
   list.

Verified: `powershell -File build-all.ps1` produces both artifacts —
dragonflight-premiere-panel-1.0.0.zxp (35 KB, signature valid)
dragonflight-premiere-panel-1.0.0-windows-setup.exe (2 MB).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 16:22:46 -04:00
0ff2625876 fix(premiere-plugin): remove broken Inno Setup [Code] heuristic
The Premiere-running check passed a Boolean to Exec's var ResultCode (Integer)
parameter — Pascal type error. The block also did nothing useful: it only
checked but never warned or prompted. Drop it. {InstallDelete] of the legacy
folder still works through the Tasks checkbox + Check function.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 16:18:19 -04:00
9266a1d471 fix(premiere-plugin): correct zxp-sign-cmd version + promise API; commit generated signing cert
The initial pass referenced zxp-sign-cmd@0.2.2 which never shipped (latest
is 2.0.0) and used the v1.x callback API. v2 is promise-based — rewrote
build-zxp.mjs accordingly.

Also commits the freshly-generated self-signed cert + passphrase from the
first local build run. From now on every build reuses these so Adobe's
ZXP signature-continuity rule is satisfied across versions.

Verified end-to-end: `npm install && node build-zxp.mjs` produces
dist/dragonflight-premiere-panel-1.0.0.zxp (34.7 KB), signature verifies,
cert valid until 2051.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 16:17:31 -04:00
f874009329 feat(premiere-plugin): ZXP + Windows installer build pipeline
Replaces the manual robocopy / install-windows.ps1 flow with two real
distributable artifacts:

  - dragonflight-premiere-panel-<version>.zxp          (Mac + Win)
  - dragonflight-premiere-panel-<version>-windows-setup.exe (Win)

The Windows installer copies the bundle to %APPDATA%\Adobe\CEP\extensions,
sets PlayerDebugMode=1 for CSXS 8..13, registers an uninstaller, and
offers to remove any legacy com.wilddragon.mam.panel folder so editors
don't end up with duplicate panels.

The .zxp is signed with a self-signed cert generated on first build and
committed to build/cert/ so signature continuity is preserved across
builds (Adobe rejects ZXP upgrades with a different cert fingerprint).

Also migrates the CEP bundle ID from com.wilddragon.mam.panel to
net.wilddragon.dragonflight.panel to match the wild-dragon -> dragonflight
repo rename. Manifest, .debug, CSInterface.js, install docs, and the
growing-files quickstart all updated.

build/ is normally swept by the root .gitignore; added an explicit
negation so the packaging pipeline stays tracked.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 16:13:20 -04:00
20 changed files with 587 additions and 98 deletions

3
.gitignore vendored
View file

@ -14,6 +14,9 @@ yarn-error.log*
# Build output
dist/
build/
# ...but the Premiere panel's packaging pipeline lives at build/ — keep it tracked.
!services/premiere-plugin/build/
!services/premiere-plugin/build/**
# OS
.DS_Store

View file

@ -29,15 +29,28 @@ and the panel relinks Premiere to the hi-res original.
## Premiere panel install
```
# macOS
rsync -a services/premiere-plugin/ ~/Library/Application\ Support/Adobe/CEP/extensions/com.wilddragon.mam.panel/
Grab the latest release artifact and run it — the installer handles the file
copy, registry/plist debug-mode flip, and removes any legacy
`com.wilddragon.mam.panel` install:
# Windows
robocopy services\premiere-plugin %APPDATA%\Adobe\CEP\extensions\com.wilddragon.mam.panel /MIR
- **Windows:** `dragonflight-premiere-panel-<version>-windows-setup.exe`
- **macOS / Win:** `dragonflight-premiere-panel-<version>.zxp` — install via
[Anastasiy's ZXP Installer](https://install.anastasiy.com/) (free GUI)
Releases live at
<https://forge.wilddragon.net/zgaetano/dragonflight/releases>.
Building locally (requires Windows for the `.exe`, any OS for the `.zxp`):
```
cd services/premiere-plugin/build
npm install
powershell -File build-all.ps1 # or: node build-zxp.mjs
```
Enable CEP debug:
The Windows installer takes care of `PlayerDebugMode`. If you installed the
ZXP and the panel does not appear in **Window → Extensions**, enable debug
mode manually:
```
# macOS

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<ExtensionList>
<Extension Id="com.wilddragon.mam.panel">
<Extension Id="net.wilddragon.dragonflight.panel">
<HostList>
<Host Name="PPRO" Port="7737"/>
</HostList>

View file

@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ns.adobe.com/CSXS/manifest http://ns.adobe.com/CSXS/manifest">
<ExtensionBundleVersion>1.0.0</ExtensionBundleVersion>
<ExtensionBundleId>com.wilddragon.mam.panel</ExtensionBundleId>
<ExtensionBundleId>net.wilddragon.dragonflight.panel</ExtensionBundleId>
<Author>Wild Dragon MAM</Author>
<License>
@ -14,7 +14,7 @@
<AbstractionLayerRequest Name="PProPanel"/>
</AbstractionLayers>
<Extension Id="com.wilddragon.mam.panel">
<Extension Id="net.wilddragon.dragonflight.panel">
<Type>Panel</Type>
<HostList>
<Host Name="PPRO" Version="[22.0,99.9]"/>

View file

@ -9,7 +9,7 @@ FILE STRUCTURE AND PURPOSES
CSXS/manifest.xml
-----------------
- CEP extension manifest file required by Adobe
- Defines extension ID: com.wilddragon.mam.panel
- Defines extension ID: net.wilddragon.dragonflight.panel
- Specifies Premiere Pro (PPRO) version compatibility: 22.0 to 99.9
- Sets panel dimensions: 400x700 (responsive 350-500px width)
- Declares CEP version 11.0 requirement
@ -173,20 +173,23 @@ PREMIERE PRO REQUIREMENTS
DEPLOYMENT INSTRUCTIONS
=======================
1. Copy entire com.wilddragon.mam.panel directory to CEP extensions folder:
Windows: C:\Users\USERNAME\AppData\Roaming\Adobe\CEP\extensions\
macOS: ~/Library/Application Support/Adobe/CEP/extensions/
Use the installer artifacts from the latest release:
https://forge.wilddragon.net/zgaetano/dragonflight/releases
2. Enable unsigned extension debugging (Windows Registry):
HKEY_CURRENT_USER\Software\Adobe\CSXS.11
Create DWORD: PlayerDebugMode = 1
Windows: dragonflight-premiere-panel-<version>-windows-setup.exe
Double-click. Installer copies bundle to
%APPDATA%\Adobe\CEP\extensions\net.wilddragon.dragonflight.panel\,
sets PlayerDebugMode=1 for CSXS 8..13, and removes any legacy
com.wilddragon.mam.panel install.
3. Enable unsigned extension debugging (macOS):
defaults write /Library/Preferences/com.adobe.CSXS.11 PlayerDebugMode 1
macOS: dragonflight-premiere-panel-<version>.zxp
Install with Anastasiy's ZXP Installer
(https://install.anastasiy.com/), then run once in Terminal:
defaults write com.adobe.CSXS.11 PlayerDebugMode 1
4. Restart Premiere Pro
Restart Premiere Pro, then: Window > Extensions > Wild Dragon MAM
5. Access panel via Window > Extensions > Wild Dragon MAM
To build the installers locally, see services/premiere-plugin/build/README.md.
DEVELOPMENT NOTES
=================

View file

@ -1,30 +1,40 @@
# Wild Dragon MAM - Premiere Pro Panel Quick Start
## Installation (5 minutes)
## Installation (1 minute)
Grab the installer from
<https://forge.wilddragon.net/zgaetano/dragonflight/releases>.
### Windows
```
1. Copy folder to:
C:\Users\<USERNAME>\AppData\Roaming\Adobe\CEP\extensions\com.wilddragon.mam.panel\
2. Open Registry Editor (regedit.exe)
Navigate to: HKEY_CURRENT_USER\Software\Adobe\CSXS.11
Create DWORD: PlayerDebugMode = 1
3. Restart Premiere Pro
1. Download dragonflight-premiere-panel-<version>-windows-setup.exe
2. Double-click it. Next -> Finish.
3. Restart Premiere Pro.
```
The installer copies the bundle to `%APPDATA%\Adobe\CEP\extensions\`,
sets `PlayerDebugMode=1` for CSXS 8..13, and offers to remove any legacy
`com.wilddragon.mam.panel` install.
### macOS
```
1. Copy folder to:
~/Library/Application Support/Adobe/CEP/extensions/com.wilddragon.mam.panel/
2. Open Terminal and run:
defaults write /Library/Preferences/com.adobe.CSXS.11 PlayerDebugMode 1
3. Restart Premiere Pro
1. Download dragonflight-premiere-panel-<version>.zxp
2. Open it with Anastasiy's ZXP Installer (https://install.anastasiy.com/)
3. Run once in Terminal:
defaults write com.adobe.CSXS.11 PlayerDebugMode 1
4. Restart Premiere Pro.
```
### Building from source
```
cd services/premiere-plugin/build
npm install
powershell -File build-all.ps1
```
See [`build/README.md`](build/README.md).
## Access the Panel
Window > Extensions > Wild Dragon MAM
@ -91,8 +101,9 @@ services/premiere-plugin/
│ └── main.js Panel logic
├── jsx/
│ └── premiere.jsx Premiere integration
├── build/ Installer build pipeline (.zxp + .exe)
├── README.md Full docs
└── QUICK_START.md This file
└── QUICK_START.md This file
```
## Troubleshooting

View file

@ -16,30 +16,41 @@ A professional media asset management (MAM) plugin for Adobe Premiere Pro that a
## Installation
### Windows
Grab the installer for your platform from the
[latest release](https://forge.wilddragon.net/zgaetano/dragonflight/releases):
1. Copy the entire `com.wilddragon.mam.panel` directory to:
```
C:\Users\<YourUsername>\AppData\Roaming\Adobe\CEP\extensions\com.wilddragon.mam.panel\
```
| File | Platform | How to install |
|------|----------|----------------|
| `dragonflight-premiere-panel-<version>-windows-setup.exe` | Windows | Double-click, Next → Finish. Copies the bundle, sets `PlayerDebugMode`, and removes any legacy `com.wilddragon.mam.panel` install. |
| `dragonflight-premiere-panel-<version>.zxp` | macOS + Windows | Install with [Anastasiy's ZXP Installer](https://install.anastasiy.com/) (free GUI). |
2. For unsigned extensions, enable debug mode in the Windows Registry:
- Open Registry Editor (`regedit.exe`)
- Navigate to: `HKEY_CURRENT_USER\Software\Adobe\CSXS.11`
- Create a new DWORD value named `PlayerDebugMode` and set it to `1`
- Restart Premiere Pro
### macOS ZXP — one extra step
### macOS
The `.zxp` is self-signed, so macOS editors must enable CEP debug mode once
before the panel will load:
1. Copy the entire `com.wilddragon.mam.panel` directory to:
```
~/Library/Application Support/Adobe/CEP/extensions/com.wilddragon.mam.panel/
```
```
defaults write com.adobe.CSXS.11 PlayerDebugMode 1
```
2. For unsigned extensions, enable debug mode in the plist:
- Open Terminal
- Run: `defaults write /Library/Preferences/com.adobe.CSXS.11 PlayerDebugMode 1`
- Restart Premiere Pro
Restart Premiere Pro afterward. The Windows `.exe` installer does this
automatically for every CEP version Premiere might use (CSXS 8 through 13).
### Building from source
If you do not want to install the release artifact, you can run the panel
straight from the source tree. See [`build/README.md`](build/README.md) for
the build pipeline, or copy the directory yourself:
```
# Windows (PowerShell, as the same user that runs Premiere)
robocopy . "$env:APPDATA\Adobe\CEP\extensions\net.wilddragon.dragonflight.panel" /MIR /XD build
# macOS
rsync -a --exclude=build/ ./ ~/Library/Application\ Support/Adobe/CEP/extensions/net.wilddragon.dragonflight.panel/
```
Then enable `PlayerDebugMode` as above.
### Access the Panel
@ -47,6 +58,22 @@ A professional media asset management (MAM) plugin for Adobe Premiere Pro that a
2. Go to **Window** > **Extensions** > **Wild Dragon MAM**
3. The panel will open as a floating window on the right side
### Upgrading from `com.wilddragon.mam.panel`
The bundle ID changed to `net.wilddragon.dragonflight.panel` as part of the
wild-dragon → dragonflight rename. The Windows installer offers to remove
the old folder for you (checkbox on the install wizard, default on). For ZXP
installs or manual copies, delete the legacy folder yourself or you will see
two panels in **Window → Extensions**:
```
# Windows
Remove-Item -Recurse -Force "$env:APPDATA\Adobe\CEP\extensions\com.wilddragon.mam.panel"
# macOS
rm -rf ~/Library/Application\ Support/Adobe/CEP/extensions/com.wilddragon.mam.panel
```
## Usage
### Connect to MAM Server
@ -102,7 +129,7 @@ To change the server URL:
## File Structure
```
com.wilddragon.mam.panel/
net.wilddragon.dragonflight.panel/ # installed bundle
├── CSXS/
│ └── manifest.xml # CEP extension manifest
├── css/
@ -113,8 +140,15 @@ com.wilddragon.mam.panel/
├── jsx/
│ └── premiere.jsx # Premiere Pro ExtendScript
├── index.html # Main panel UI
├── .debug # CEP debug configuration
├── .debug # CEP debug configuration
└── README.md # This file
build/ # not shipped — installer/.zxp build pipeline
├── README.md # how to build .zxp + .exe locally
├── build-all.ps1 # build both artifacts
├── build-zxp.mjs # ZXP signer
├── installer.iss # Inno Setup script
└── ...
```
## API Integration

View file

@ -0,0 +1,4 @@
node_modules/
dist/
stage/
*.log

View file

@ -0,0 +1,86 @@
# Premiere panel installer — build pipeline
Produces two artifacts from `services/premiere-plugin/`:
| File | Platform | How an editor installs it |
|------|----------|----------------------------|
| `dist/dragonflight-premiere-panel-<version>.zxp` | macOS + Windows | Drag into [Anastasiy's ZXP Installer](https://install.anastasiy.com/) |
| `dist/dragonflight-premiere-panel-<version>-windows-setup.exe` | Windows | Double-click, Next → Finish |
The version is read from `CSXS/manifest.xml`'s `<ExtensionBundleVersion>`. To
cut a new release: bump that one number, rebuild, attach the two files to a
Forgejo release tag.
## Prerequisites
| Building | Requires |
|----------|----------|
| `.zxp` only | Node 18+, runs on macOS / Linux / Windows |
| `.exe` | Windows + [Inno Setup 6](https://jrsoftware.org/isinfo.php) on `PATH` (`ISCC.exe`) |
| Both via `build-all.ps1` | Windows + Node 18+ + Inno Setup 6 |
Install Inno Setup with winget:
```
winget install --id JRSoftware.InnoSetup
```
## Build
```
cd services/premiere-plugin/build
npm install
powershell -File build-all.ps1
```
Artifacts land in `services/premiere-plugin/build/dist/`.
To build just one:
```
node build-zxp.mjs # cross-platform .zxp
powershell -File build-installer.ps1 # Windows .exe (needs ISCC.exe)
```
## Signing cert (.zxp)
The first `node build-zxp.mjs` run generates a self-signed cert at
`cert/dragonflight-selfsigned.p12` + passphrase at `cert/cert-passphrase.txt`.
**Commit both files** — they need to be stable across builds so Adobe accepts
ZXP upgrades in place. If you regenerate the cert, every editor who already
installed an older `.zxp` has to uninstall + reinstall.
The cert is self-signed → editors still need `PlayerDebugMode=1`. The Windows
`.exe` installer sets this automatically. ZXP installs on macOS need a manual
`defaults write com.adobe.CSXS.11 PlayerDebugMode 1`.
See `cert/README.md` for cert details + how to regenerate.
## What the installers do
Both install the bundle as `net.wilddragon.dragonflight.panel`. The Windows
`.exe` additionally:
1. Removes any legacy `com.wilddragon.mam.panel` folder (with a consent
checkbox, default on) — avoids editors seeing two panels in
**Window → Extensions**.
2. Sets `HKCU\Software\Adobe\CSXS.{8..13}\PlayerDebugMode = "1"` so unsigned
CEP extensions load.
3. Registers itself in Add/Remove Programs so uninstall reverses both.
## Layout
```
build/
├── README.md ← this file
├── package.json ← devDep: zxp-sign-cmd
├── .gitignore ← ignores dist/ + node_modules/
├── build-all.ps1 ← runs both builders
├── build-zxp.mjs ← Node: generates cert (first run), signs, packages
├── build-installer.ps1 ← wraps ISCC.exe with version + bundle-id flags
├── installer.iss ← Inno Setup script
└── cert/
├── README.md ← how to regenerate
├── dragonflight-selfsigned.p12 ← generated on first build (commit it)
└── cert-passphrase.txt ← generated on first build (commit it)
```

View file

@ -0,0 +1,34 @@
# Dragonflight Premiere panel — build everything
#
# Produces both artifacts in dist/:
# - dragonflight-premiere-panel-<version>.zxp (Mac + Win)
# - dragonflight-premiere-panel-<version>-windows-setup.exe (Win)
#
# Requires: Node 18+, Inno Setup 6 (ISCC.exe on PATH).
# Usage: pwsh -File build-all.ps1
$ErrorActionPreference = 'Stop'
Set-Location $PSScriptRoot
if (-not (Test-Path 'node_modules')) {
Write-Host 'Installing npm deps...'
npm install --no-audit --no-fund
if ($LASTEXITCODE -ne 0) { throw 'npm install failed' }
}
Write-Host ''
Write-Host '=== Building .zxp ==='
node build-zxp.mjs
if ($LASTEXITCODE -ne 0) { throw 'ZXP build failed' }
Write-Host ''
Write-Host '=== Building Windows .exe ==='
& (Join-Path $PSScriptRoot 'build-installer.ps1')
if ($LASTEXITCODE -ne 0) { throw 'Installer build failed' }
Write-Host ''
Write-Host 'All artifacts:'
Get-ChildItem -Path 'dist' | ForEach-Object {
$size = [math]::Round($_.Length / 1KB, 1)
Write-Host (' {0,8} KB {1}' -f $size, $_.Name)
}

View file

@ -0,0 +1,56 @@
# Dragonflight Premiere panel — Windows installer build
#
# Parses the version from ../CSXS/manifest.xml and hands it to ISCC.exe.
# Requires Inno Setup 6 on PATH (winget install JRSoftware.InnoSetup).
#
# Usage: pwsh -File build-installer.ps1
$ErrorActionPreference = 'Stop'
Set-Location $PSScriptRoot
$manifestPath = Join-Path $PSScriptRoot '..\CSXS\manifest.xml'
if (-not (Test-Path $manifestPath)) {
throw "Manifest not found at $manifestPath"
}
# Regex over XML because the manifest's <Resources> comment contains '--'
# (the --enable-nodejs/--mixed-context CEF flags), which is illegal per the
# XML spec — .NET's strict parser rejects the doc even though Adobe CEP
# tolerates it.
$manifestRaw = Get-Content -Raw -Path $manifestPath
if ($manifestRaw -notmatch '<ExtensionBundleVersion>([^<]+)</ExtensionBundleVersion>') {
throw 'Could not read <ExtensionBundleVersion> from manifest.xml'
}
$version = $Matches[1].Trim()
Write-Host "Dragonflight Premiere panel - Windows installer build v$version"
$iscc = Get-Command 'ISCC.exe' -ErrorAction SilentlyContinue
if (-not $iscc) {
# Common Inno Setup 6 install locations. winget user-scope drops it in
# %LOCALAPPDATA%\Programs; machine-wide installs land in Program Files.
$fallbacks = @(
"${env:LOCALAPPDATA}\Programs\Inno Setup 6\ISCC.exe",
"${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe",
"${env:ProgramFiles}\Inno Setup 6\ISCC.exe"
)
foreach ($p in $fallbacks) {
if (Test-Path $p) { $iscc = Get-Command $p; break }
}
if (-not $iscc) {
throw "ISCC.exe not found. Install Inno Setup 6: winget install JRSoftware.InnoSetup"
}
}
$distDir = Join-Path $PSScriptRoot 'dist'
New-Item -ItemType Directory -Force -Path $distDir | Out-Null
& $iscc.Source "/DMyAppVersion=$version" "installer.iss"
if ($LASTEXITCODE -ne 0) {
throw "ISCC failed with exit code $LASTEXITCODE"
}
$output = Join-Path $distDir "dragonflight-premiere-panel-$version-windows-setup.exe"
if (-not (Test-Path $output)) {
throw "Expected output not found: $output"
}
$size = [math]::Round((Get-Item $output).Length / 1KB, 1)
Write-Host "Built $output ($size KB)"

View file

@ -0,0 +1,98 @@
#!/usr/bin/env node
// Build a signed .zxp for the Dragonflight Premiere panel.
//
// - Reads version from ../CSXS/manifest.xml (<ExtensionBundleVersion>)
// - Generates a self-signed cert on first run (cert/dragonflight-selfsigned.p12)
// - Stages the panel bundle into stage/ (excludes build/ + dev cruft)
// - Calls zxp-sign-cmd to sign + package into dist/
//
// Usage: node build-zxp.mjs
// Output: dist/dragonflight-premiere-panel-<version>.zxp
import { mkdirSync, existsSync, readFileSync, writeFileSync, rmSync, cpSync, readdirSync, statSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';
import { randomBytes } from 'node:crypto';
import zxp from 'zxp-sign-cmd';
const HERE = dirname(fileURLToPath(import.meta.url));
const PANEL_DIR = resolve(HERE, '..');
const MANIFEST = join(PANEL_DIR, 'CSXS', 'manifest.xml');
const CERT_DIR = join(HERE, 'cert');
const CERT_FILE = join(CERT_DIR, 'dragonflight-selfsigned.p12');
const PASS_FILE = join(CERT_DIR, 'cert-passphrase.txt');
const STAGE_DIR = join(HERE, 'stage');
const DIST_DIR = join(HERE, 'dist');
// Top-level entries to exclude from the staged bundle.
const EXCLUDE = new Set(['build', 'install-windows.ps1', '.git', '.gitignore', 'node_modules']);
function readVersion() {
const xml = readFileSync(MANIFEST, 'utf8');
const m = xml.match(/<ExtensionBundleVersion>([^<]+)<\/ExtensionBundleVersion>/);
if (!m) throw new Error(`Could not find <ExtensionBundleVersion> in ${MANIFEST}`);
return m[1].trim();
}
async function ensureCert() {
mkdirSync(CERT_DIR, { recursive: true });
if (existsSync(CERT_FILE) && existsSync(PASS_FILE)) {
return readFileSync(PASS_FILE, 'utf8').trim();
}
console.log('No signing cert found — generating self-signed cert (one-time)…');
const passphrase = randomBytes(24).toString('base64url');
writeFileSync(PASS_FILE, passphrase + '\n', { mode: 0o600 });
await zxp.selfSignedCert({
country: 'US',
province: 'WA',
org: 'Wild Dragon LLC',
name: 'Wild Dragon LLC',
password: passphrase,
output: CERT_FILE,
validityDays: 365 * 25,
});
console.log(` wrote ${CERT_FILE}`);
console.log(` wrote ${PASS_FILE}`);
console.log(' >> COMMIT both files so future builds reuse them. <<');
return passphrase;
}
function stageBundle() {
if (existsSync(STAGE_DIR)) rmSync(STAGE_DIR, { recursive: true, force: true });
mkdirSync(STAGE_DIR, { recursive: true });
for (const entry of readdirSync(PANEL_DIR)) {
if (EXCLUDE.has(entry)) continue;
const src = join(PANEL_DIR, entry);
const dst = join(STAGE_DIR, entry);
cpSync(src, dst, { recursive: true });
}
}
async function signZxp(version, passphrase) {
mkdirSync(DIST_DIR, { recursive: true });
const output = join(DIST_DIR, `dragonflight-premiere-panel-${version}.zxp`);
if (existsSync(output)) rmSync(output);
await zxp.sign({
input: STAGE_DIR,
output,
cert: CERT_FILE,
password: passphrase,
});
const bytes = statSync(output).size;
console.log(`Built ${output} (${(bytes / 1024).toFixed(1)} KB)`);
return output;
}
async function main() {
const version = readVersion();
console.log(`Dragonflight Premiere panel — ZXP build v${version}`);
const passphrase = await ensureCert();
stageBundle();
await signZxp(version, passphrase);
rmSync(STAGE_DIR, { recursive: true, force: true });
}
main().catch((err) => {
console.error('ZXP build failed:', err);
process.exit(1);
});

View file

@ -0,0 +1,45 @@
# Self-signed cert for ZXP signing
The `.zxp` package format requires a signature. We use a self-signed cert so
there is no Certificate Authority cost; the trade-off is editors must enable
`PlayerDebugMode` for the panel to load (the Windows `.exe` installer does
this automatically).
## Files
| File | What it is | Commit to git? |
|------|------------|----------------|
| `dragonflight-selfsigned.p12` | PKCS#12 keystore containing the signing cert + private key | **yes** |
| `cert-passphrase.txt` | Passphrase for the `.p12` | **yes** |
Both are auto-generated on the first `node build-zxp.mjs` run. They MUST be
committed and reused across builds: Adobe's ZXP signature continuity rule
means a re-signed package with a different cert fingerprint will not install
over an existing version — editors would have to uninstall the panel first.
## Why is committing a private key OK here?
- The panel is proprietary internal tooling, not a public distribution.
- The cert chains to nothing — a leak lets an attacker sign a fake
`net.wilddragon.dragonflight.panel` bundle, which would still require
`PlayerDebugMode=1` to load and physical access to the editor's machine to
install. Threat model: low.
- The alternative (rotating the cert on every build or keeping it in a
secrets manager) would break upgrade-in-place for every editor on every
build.
If you want a real codesigning cert later, drop a CA-issued `.p12` over the
self-signed one with the same filename and update `cert-passphrase.txt`. The
build script will reuse them.
## Regenerating
Delete both files. Next `node build-zxp.mjs` run will create a fresh
self-signed cert (valid for 25 years). Commit the new pair. **Heads up:**
every editor with the old `.zxp` installed must uninstall first before the
new one will install.
The build script handles regeneration automatically — just delete both
files and re-run `node build-zxp.mjs`. If you need to invoke Adobe's
`ZXPSignCmd` directly (e.g. to inspect the generated cert), it ships inside
`node_modules/zxp-provider/bin/<version>/` after `npm install`.

View file

@ -0,0 +1 @@
k_rdrajiNn_qQcW2Oc9Z2Kc0rG4AP8vA

View file

@ -0,0 +1,79 @@
; Dragonflight Premiere Pro CEP panel — Windows installer
; Build: iscc installer.iss /DMyAppVersion=1.0.0
; (build-installer.ps1 parses CSXS/manifest.xml and passes the version)
#ifndef MyAppVersion
#define MyAppVersion "0.0.0-dev"
#endif
#define MyAppName "Dragonflight Premiere Panel"
#define MyAppPublisher "Wild Dragon LLC"
#define MyAppURL "https://forge.wilddragon.net/zgaetano/dragonflight"
#define BundleId "net.wilddragon.dragonflight.panel"
#define LegacyBundleId "com.wilddragon.mam.panel"
#define PanelSrcDir "..\"
#define OutDir "dist"
[Setup]
AppId={{8E2C1F6D-1B9A-4D7E-9C3F-9F2E5A4C7B11}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}/issues
AppUpdatesURL={#MyAppURL}/releases
DefaultDirName={userappdata}\Adobe\CEP\extensions\{#BundleId}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
DisableDirPage=yes
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=
OutputDir={#OutDir}
OutputBaseFilename=dragonflight-premiere-panel-{#MyAppVersion}-windows-setup
Compression=lzma
SolidCompression=yes
WizardStyle=modern
UninstallDisplayName={#MyAppName} {#MyAppVersion}
UninstallDisplayIcon={app}\index.html
SetupLogging=yes
[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "removelegacy"; Description: "Remove legacy {#LegacyBundleId} install if present"; GroupDescription: "Migration:"; Check: LegacyPanelExists
[Files]
; Copy the entire panel bundle, minus the build/ pipeline and the
; deprecated install-windows.ps1 (this installer supersedes it).
Source: "{#PanelSrcDir}*"; DestDir: "{app}"; Excludes: "build,install-windows.ps1,*.log"; \
Flags: ignoreversion recursesubdirs createallsubdirs
[Registry]
; Enable PlayerDebugMode for every CEP version Premiere Pro might use.
; Adobe stores this as REG_SZ "1" (a STRING, not a DWORD). Intentionally
; no uninsdeletevalue flag — other CEP panels need this key too.
Root: HKCU; Subkey: "Software\Adobe\CSXS.8"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
Root: HKCU; Subkey: "Software\Adobe\CSXS.9"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
Root: HKCU; Subkey: "Software\Adobe\CSXS.10"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
Root: HKCU; Subkey: "Software\Adobe\CSXS.11"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
Root: HKCU; Subkey: "Software\Adobe\CSXS.12"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
Root: HKCU; Subkey: "Software\Adobe\CSXS.13"; ValueType: string; ValueName: "PlayerDebugMode"; ValueData: "1"
[InstallDelete]
; Wipe the legacy folder before installing the new one (only if user opted in).
Type: filesandordirs; Name: "{userappdata}\Adobe\CEP\extensions\{#LegacyBundleId}"; Tasks: removelegacy
[UninstallDelete]
; Strip the install dir clean on uninstall. App lives entirely in {app}.
Type: filesandordirs; Name: "{app}"
[Code]
function LegacyPanelExists: Boolean;
begin
Result := DirExists(ExpandConstant('{userappdata}\Adobe\CEP\extensions\{#LegacyBundleId}'));
end;
[Run]
Filename: "{app}\README.md"; Description: "Open README"; Flags: shellexec postinstall skipifsilent unchecked

View file

@ -0,0 +1,43 @@
{
"name": "dragonflight-premiere-panel-build",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dragonflight-premiere-panel-build",
"version": "0.0.0",
"devDependencies": {
"zxp-sign-cmd": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/zxp-provider": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/zxp-provider/-/zxp-provider-2.0.0.tgz",
"integrity": "sha512-ja2YZwDnDrTdq5Q0EebOaHQK5f4tOf5488mKV4sVC/mKyNiXHyJlyKwLWB4SGIrvqqWWkDk/QCfsWms2jTQ/Tw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/zxp-sign-cmd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/zxp-sign-cmd/-/zxp-sign-cmd-2.0.0.tgz",
"integrity": "sha512-BzWNvp6kSL4RFmxWp8MkVtJ4NIuRq1238W0ojHWLgeAqWMaptFdY8Nh2Uguf7Fka8KyIinrf0+tTgCeGlWPMoA==",
"dev": true,
"license": "MIT",
"dependencies": {
"zxp-provider": "^2.0.0"
},
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0"
}
}
}
}

View file

@ -0,0 +1,18 @@
{
"name": "dragonflight-premiere-panel-build",
"version": "0.0.0",
"private": true,
"description": "Build pipeline for the Dragonflight Premiere Pro CEP panel — produces a signed .zxp and a Windows .exe installer.",
"type": "module",
"scripts": {
"build:zxp": "node build-zxp.mjs",
"build:exe": "powershell -NoProfile -ExecutionPolicy Bypass -File build-installer.ps1",
"build": "powershell -NoProfile -ExecutionPolicy Bypass -File build-all.ps1"
},
"devDependencies": {
"zxp-sign-cmd": "^2.0.0"
},
"engines": {
"node": ">=18"
}
}

View file

@ -1,39 +0,0 @@
# Wild Dragon MAM - Premiere Pro plugin installer (Windows)
# Run from PowerShell as the same user that runs Premiere Pro (NOT as admin)
#
# Usage:
# 1. Open this folder in PowerShell
# 2. Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
# 3. .\install-windows.ps1
$ErrorActionPreference = 'Stop'
$src = $PSScriptRoot
$dest = Join-Path $env:APPDATA 'Adobe\CEP\extensions\com.wilddragon.mam.panel'
Write-Host "Source: $src"
Write-Host "Target: $dest"
if (Test-Path $dest) {
Write-Host "Removing existing extension at $dest"
Remove-Item -Recurse -Force $dest
}
New-Item -ItemType Directory -Force -Path $dest | Out-Null
Copy-Item -Recurse -Force "$src\*" $dest -Exclude 'install-windows.ps1'
Write-Host 'Files copied.'
# Enable CEP debug mode for the supported CEP versions (Premiere Pro uses CSXS.11+).
foreach ($v in 8..13) {
$regPath = "HKCU:\Software\Adobe\CSXS.$v"
if (-not (Test-Path $regPath)) { New-Item -Path $regPath -Force | Out-Null }
Set-ItemProperty -Path $regPath -Name 'PlayerDebugMode' -Value 1 -Type String
Write-Host "Set PlayerDebugMode=1 on $regPath"
}
Write-Host ''
Write-Host 'Done. Restart Premiere Pro, then:'
Write-Host ' Window -> Extensions -> Wild Dragon MAM'
Write-Host ''
Write-Host 'Server URL inside the panel should be the MAM web-UI, e.g.:'
Write-Host ' http://10.0.0.25:47434'

View file

@ -32,7 +32,7 @@ class CSInterface {
constructor() {
this.requestIdCount = 1;
this.requestMap = new Map();
this.extensionId = "com.wilddragon.mam.panel";
this.extensionId = "net.wilddragon.dragonflight.panel";
// Initialize event listener for messages from ExtendScript
if (window.__adobe_cep__ !== undefined) {