@metricinsights/pp-dev is a Vite/Next.js-based local development framework and build tool for Metric Insights' Portal Pages. It:
- Proxies API requests to a live MI instance
- Injects a dev panel (minimize, template sync) into the served page
- Synchronizes the built template back to MI via WebSocket-triggered
next build/ Vite build
npm run build # Build node + client bundles; also packs a .tgz
npm run test # Unit + integration (vitest)
npm run test:unit # Unit tests only
npm run test:integration # Integration tests (forked processes)
npm run audit:all # npm audit in root AND every tests/* package — always use this, never bare npm auditAlways verify with the repo-wide audit, not just root:
npm run audit:allThis runs npm audit in root + tests/test-commonjs, tests/test-nextjs, tests/test-nextjs-cjs. All must exit 0.
If test-fixture lockfiles need patching, add/update overrides in their package.json and run npm install there.
If an advisory has no upstream fix at all (fixAvailable: false and no newer version exists), don't
try to force an override that doesn't exist. Mitigate it in application code instead, then add the
GHSA id to the ALLOWLIST map in scripts/audit-all.mjs with a comment explaining the mitigation —
that's the only thing that lets audit:all pass without silently hiding real, fixable vulnerabilities.
Remove the entry as soon as a real fix ships upstream.
npm run reinstall:all # builds dist/ + .tgz, then reinstalls in all test fixturessrc/cli.ts — 8 CLI commands: serve (default), next, build, changelog, …
src/index.ts — withPPDev() Vite config builder; loads pp-dev.config.*
src/plugin.ts — Vite plugin interface (re-exported)
src/lib/
client.service.ts — WebSocket event handler (info-data, template:sync, …)
dist.service.ts — Build artifact manager: backups, VERSION, BUILD-MANIFEST, zip
dev-panel.ts — EJS panel injection + static asset middleware
pp-ws-server.ts — Raw ws server for Next.js (Vite-WS-compatible facade)
version-manifest.ts — VERSION file + BUILD-MANIFEST generation (shared)
middleware/ — Request pipeline: redirect → proxy cache → load-pp-data → proxy-pass → rewrite-response
src/plugins/
client-injection-plugin.ts — Vite transformIndexHtml: injects panel markup
version-plugin.ts — Vite build hook: writes VERSION into dist
src/client/
index.ts — Browser-side dev panel (sync button, minimize)
hot-context.ts — import.meta.hot shim for Next.js WS transport
WebSocket transport: Vite dev server uses Vite HMR WS. Next.js uses PPDevHotServer (raw ws, path /@pp-dev-hmr). The client picks whichever is available: import.meta.hot ?? createPPDevHotContext().
| Suite | Config | Pool | Timeout | Location |
|---|---|---|---|---|
| Unit | vitest.config.ts |
threads | 10 s | tests/unit/**/*.spec.ts |
| Integration | vitest.integration.config.ts |
forks | 30 s | tests/integration/**/*.spec.ts |
| E2E | playwright.config.ts |
browser | — | e2e/ |
Test fixtures (real apps installed with the local .tgz):
tests/test-nextjs/— ESM Next.js apptests/test-nextjs-cjs/— CJS Next.js apptests/test-commonjs/— CommonJS Vite app
- Dual ESM/CJS output — Rollup builds
dist/esm/,dist/cjs/,dist/types/from 4 entry points. - Config caching —
src/config.tscaches loaded config (30 s) andpackage.json(60 s). - Lazy heavy imports —
esbuild,jsdom,sharpare imported lazily to keep startup fast. - Axios instance cache — one Axios instance per base URL;
keepAlive: falseavoids max-listeners warnings. - No bare
npm audit— alwaysnpm run audit:allso test fixtures are included.
See .cursor/rules/pr-message-format.mdc. Use emojis: 🚀 features, 🔧 fixes, 🔐 security, 🧪 tests, 🧹 chore.
develop drives semantic-release's beta channel (.releaserc.json + the release-beta job in
ci.yml). main is sometimes tagged for a release directly (bypassing semantic-release) and never
merged back into develop — when that happens, develop's history has no idea the newer release
exists, and semantic-release keeps computing the next beta version against the old, stale baseline
(e.g. still proposing 1.3.0-beta.x after v1.4.0 already shipped from main).
So before creating a PR into develop, check whether main has moved ahead of it:
git fetch origin
git log origin/develop..origin/main --onelineIf it has, merge origin/main into the PR branch first (git merge origin/main --no-ff) so
develop stays a superset of main's history. This is normally a no-op content-wise — it only
fixes the ancestry graph so semantic-release resolves the real last release. Sanity-check with a
local semantic-release --dry-run (on a branch literally named develop, since branch matching is
by exact name) if you want to confirm the computed next version before pushing.