pcf-dev-proxy
v3.2.0
Published
HTTPS MITM proxy that intercepts deployed PCF bundle requests and serves local files with hot module reload.
Maintainers
Readme
pcf-dev-proxy
HTTPS MITM proxy for PCF development against live Dataverse pages.
By default it intercepts control assets and serves local build output.
With --hot, it also enables deterministic in-place PCF control hot-reload (no full page refresh).
Quick start
npx pcf-dev-proxyThis auto-detects ControlManifest.Input.xml, resolves cc_<namespace>.<constructor>, and serves files from out/controls/<constructor>.
Hot mode (Chrome, no full page reload)
npx pcf-dev-proxy --hot --yesHot mode adds:
- local HMR control plane on
127.0.0.1(default port8643) - direct WebSocket from page to control plane
- in-page runtime instrumentation for PCF instance swap
- CSP header stripping on passthrough responses (hot mode only)
Trigger reload from your build pipeline
Primary workflow is explicit trigger from build completion:
npx pcf-dev-proxy reload \
--control cc_Contoso.MyControl \
--trigger pcf-start \
--build-id "$(date -u +%Y-%m-%dT%H:%M:%SZ)"Optional fallback watcher:
npx pcf-dev-proxy --hot --watch-bundleControl plane API
When hot mode is enabled (--hot):
GET /healthPOST /reloadPOST /ackGET /last-ack
Example reload payload:
{ "controlName": "cc_Contoso.MyControl", "buildId": "2026-02-27T12:34:56.789Z", "trigger": "pcf-start" }Example ACK payload from runtime:
{ "id": "r-123", "controlName": "cc_Contoso.MyControl", "buildId": "2026-02-27T12:34:56.789Z", "status": "success", "instancesTotal": 2, "instancesReloaded": 2, "durationMs": 184 }CLI
# start proxy
npx pcf-dev-proxy [options]
# enqueue a reload (no proxy startup)
npx pcf-dev-proxy reload --control <name> [options]Options:
--port <number>Proxy port (default8642)--ws-port <number>HMR control plane port (default8643)--dir <path>Directory to serve files from--control <name>Override control name--browser <name>chromeoredge(auto-detected)--hotEnable hot mode (Chrome only)--watch-bundleWatchbundle.jsand enqueue reload (hot mode only)-y, --yesSkip launch prompt
Reload subcommand options:
--ws-port <number>Control plane port--control <name>Required control name--build-id <id>Build identifier--trigger <source>Trigger label--changed-files <csv>Optional changed files metadata
Browser profile
The proxy launches Chrome with a dedicated profile at ~/.pcf-dev-proxy/chrome-profile. This profile is persistent — your Dataverse login, cookies, and session survive across proxy restarts. You only need to authenticate once.
The profile is separate from your normal Chrome profile, so proxy settings (certificate trust, --proxy-server flag) don't affect your daily browsing.
Typical PCF workflow
# terminal 1 — build watcher
pcf-start
# terminal 2 — proxy
npx pcf-dev-proxy --hot
# terminal 3 (or post-build hook) — trigger reload after build completes
npx pcf-dev-proxy reload --control cc_Contoso.MyControl --trigger pcf-startOn first run, Chrome opens and you log into Dataverse. On subsequent runs, the session is already there.
Troubleshooting
- No reload applied: check
GET /last-ackfor latest runtime status. - ACK timeout: ensure Dataverse tab is open in the Chrome instance launched by the proxy.
- Chrome won't launch: if Chrome is already running with the proxy profile, the proxy skips launch. Close the existing proxy Chrome window first, or just reload the page.
- Browser mismatch: hot mode currently supports Chrome only (Edge works for non-hot proxy usage).
- Multiple rapid builds: queue is latest-wins per control; only newest pending reload is applied.
pcf-scripts buildfails with Chrome profile errors: this can happen if.cache/contains a Chrome profile. The proxy stores its Chrome profile at~/.pcf-dev-proxy/chrome-profile(outside the project) to avoid this.
Requirements
- Node.js >= 18
- Chrome for hot mode (Edge remains supported for non-hot proxy usage)
- A PCF project with
ControlManifest.Input.xml
License
MIT
