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>
This commit is contained in:
Zac Gaetano 2026-05-23 16:13:20 -04:00
parent 674dccca4e
commit f874009329
17 changed files with 565 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
pwsh -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
pwsh -File build-all.ps1
```
See [`build/README.md`](build/README.md).
## Access the Panel
Window > Extensions > Wild Dragon MAM
@ -91,6 +101,7 @@ 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
```

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/
@ -115,6 +142,13 @@ com.wilddragon.mam.panel/
├── index.html # Main panel UI
├── .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
pwsh -File build-all.ps1
```
Artifacts land in `services/premiere-plugin/build/dist/`.
To build just one:
```
node build-zxp.mjs # cross-platform .zxp
pwsh -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,46 @@
# 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"
}
$manifestXml = [xml](Get-Content -Raw -Path $manifestPath)
$version = $manifestXml.ExtensionManifest.ExtensionBundleVersion
if (-not $version) {
throw 'Could not read <ExtensionBundleVersion> from manifest.xml'
}
Write-Host "Dragonflight Premiere panel - Windows installer build v$version"
$iscc = Get-Command 'ISCC.exe' -ErrorAction SilentlyContinue
if (-not $iscc) {
# Common install location if not on PATH.
$fallback = "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe"
if (Test-Path $fallback) {
$iscc = Get-Command $fallback
} else {
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,106 @@
#!/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');
// Files/dirs 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();
}
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 });
return new Promise((res, rej) => {
zxp.selfSignedCert({
country: 'US',
province: 'WA',
org: 'Wild Dragon LLC',
name: 'Wild Dragon LLC',
password: passphrase,
output: CERT_FILE,
validityDays: 365 * 25,
}, (err) => {
if (err) return rej(err);
console.log(` wrote ${CERT_FILE}`);
console.log(` wrote ${PASS_FILE}`);
console.log(' >> COMMIT both files so future builds reuse them. <<');
res(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 });
}
}
function signZxp(version, passphrase) {
mkdirSync(DIST_DIR, { recursive: true });
const output = join(DIST_DIR, `dragonflight-premiere-panel-${version}.zxp`);
if (existsSync(output)) rmSync(output);
return new Promise((res, rej) => {
zxp.sign({
input: STAGE_DIR,
output,
cert: CERT_FILE,
password: passphrase,
}, (err) => {
if (err) return rej(err);
const bytes = statSync(output).size;
console.log(`Built ${output} (${(bytes / 1024).toFixed(1)} KB)`);
res(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,53 @@
# 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.
Manual regeneration with the Adobe-published `ZXPSignCmd` (the
`zxp-sign-cmd` npm package wraps this):
```
npx zxp-sign-cmd selfSignedCert \
--country US \
--province WA \
--org "Wild Dragon LLC" \
--name "Wild Dragon LLC" \
--password "$(cat cert-passphrase.txt)" \
--output dragonflight-selfsigned.p12
```

View file

@ -0,0 +1,95 @@
; 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;
procedure CurStepChanged(CurStep: TSetupStep);
var
PremiereRunning: Boolean;
begin
if CurStep = ssInstall then begin
PremiereRunning := False;
// Heuristic — Premiere's main exe is Adobe Premiere Pro.exe.
// If it is running, files in {app} can still be replaced (CEP loads them
// on panel open, not on Premiere launch), but the user needs a Premiere
// restart before the new bundle is picked up. Just warn, don't block.
if Exec('cmd.exe', '/C tasklist /FI "IMAGENAME eq Adobe Premiere Pro.exe" | find /I "Adobe Premiere Pro.exe" >nul', '', SW_HIDE, ewWaitUntilTerminated, PremiereRunning) and PremiereRunning then begin
// exit code 0 from `find` means the process was found
end;
end;
end;
[Run]
Filename: "{app}\README.md"; Description: "Open README"; Flags: shellexec postinstall skipifsilent unchecked

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": "pwsh -NoProfile -ExecutionPolicy Bypass -File build-installer.ps1",
"build": "pwsh -NoProfile -ExecutionPolicy Bypass -File build-all.ps1"
},
"devDependencies": {
"zxp-sign-cmd": "^0.2.2"
},
"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) {