@metricinsights/pp-dev 1.5.0-beta.24 → 1.5.0-beta.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/README.md DELETED
@@ -1,765 +0,0 @@
1
- # pp-dev
2
-
3
- <p align="center">
4
- <a href="https://www.npmjs.com/package/@metricinsights/pp-dev"><img alt="npm" src="https://img.shields.io/npm/v/%40metricinsights%2Fpp-dev?logo=npm&label=npm%20package"></a>
5
- <a href="https://github.com/mi-examples/pp-dev/releases"><img alt="Release" src="https://img.shields.io/github/v/release/mi-examples/pp-dev?label=release"></a>
6
- <a href="https://github.com/mi-examples/pp-dev/actions/workflows/ci.yml"><img alt="GitHub Workflow CI Status (with event)" src="https://github.com/mi-examples/pp-dev/actions/workflows/ci.yml/badge.svg?branch=develop"></a>
7
- </p>
8
-
9
- The PP Dev Helper is a development framework and build tool for Metric Insights' Portal Pages, designed to make the
10
- lives of PP developers easier:
11
-
12
- - Build and test Portal Pages locally
13
- - Proxy API requests to a Metric Insights server
14
- - Hot module replacement for faster development
15
- - Image optimization and asset management
16
- - Template variable transformation
17
- - Code synchronization with Metric Insights instances
18
-
19
- pp-dev is based on [Vite](https://vitejs.dev/).
20
-
21
- 📸 **[Feature tour](./docs/features.md)** — screenshots of the dev panel, Request Inspector, and Variables Editor.
22
-
23
- ## Installation
24
-
25
- ```bash
26
- npm install @metricinsights/pp-dev
27
- ```
28
-
29
- ### Peer Dependencies
30
-
31
- This package requires Next.js as a peer dependency for certain functionality:
32
-
33
- ```bash
34
- npm install next@^15
35
- ```
36
-
37
- **Note**: pp-dev requires Next.js version 15 or higher (but less than 17) to be installed in your project. This is a peer dependency, meaning it won't be automatically installed with pp-dev.
38
-
39
- ## Package Structure
40
-
41
- The pp-dev package provides multiple entry points for different use cases:
42
-
43
- ```javascript
44
- // Main package (includes everything)
45
- import ppDev from '@metricinsights/pp-dev';
46
-
47
- // Plugin only (for Vite integration)
48
- import { vitePPDev } from '@metricinsights/pp-dev/plugin';
49
-
50
- // Helpers only (defineConfig and utility functions)
51
- import { defineConfig } from '@metricinsights/pp-dev/helpers';
52
-
53
- // Client assets (for development UI)
54
- import '@metricinsights/pp-dev/client/css/client.css';
55
- ```
56
-
57
- ## Configuration
58
-
59
- ### Configuration File
60
-
61
- Create a configuration file named `pp-dev.config` with one of these extensions:
62
-
63
- - `.ts` (recommended)
64
- - `.js` or `.cjs` (for CommonJS)
65
- - `.json`
66
-
67
- Alternatively, you can define configuration in your `package.json` using the `pp-dev` key.
68
-
69
- ### Configuration Examples
70
-
71
- #### TypeScript (recommended)
72
-
73
- ```typescript
74
- // pp-dev.config.ts
75
- import { defineConfig } from '@metricinsights/pp-dev';
76
-
77
- export default defineConfig({
78
- mi: {
79
- url: 'https://mi.company.com',
80
- token: process.env.MI_ACCESS_TOKEN,
81
- mode: 'standalone',
82
- apiVersion: 7,
83
- },
84
- app: {
85
- id: 123,
86
- type: 'template',
87
- },
88
- });
89
- ```
90
-
91
- #### JavaScript (CommonJS)
92
-
93
- ```javascript
94
- // pp-dev.config.js
95
- const { defineConfig } = require('@metricinsights/pp-dev');
96
-
97
- module.exports = defineConfig({
98
- mi: {
99
- url: 'https://mi.company.com',
100
- mode: 'standalone',
101
- apiVersion: 7,
102
- },
103
- app: {
104
- id: 123,
105
- type: 'template',
106
- },
107
- });
108
- ```
109
-
110
- #### JSON
111
-
112
- ```json
113
- {
114
- "mi": {
115
- "url": "https://mi.company.com",
116
- "mode": "standalone",
117
- "apiVersion": 7
118
- },
119
- "app": {
120
- "id": 123,
121
- "type": "template"
122
- }
123
- }
124
- ```
125
-
126
- #### package.json
127
-
128
- ```json
129
- {
130
- "name": "my-portal-page",
131
- "pp-dev": {
132
- "mi": {
133
- "url": "https://mi.company.com",
134
- "mode": "standalone"
135
- },
136
- "app": {
137
- "id": 123
138
- }
139
- }
140
- }
141
- ```
142
-
143
- ## Configuration Options
144
-
145
- ### `mi` — Metric Insights connection
146
-
147
- | Field | Type | Default | Description |
148
- |--------------|-----------------------------------|----------------|-----------------------------------------------------------|
149
- | `url` | `string` | — | URL of the Metric Insights instance |
150
- | `token` | `string` | `MI_ACCESS_TOKEN` env | Personal access token for authentication |
151
- | `mode` | `'standalone' \| 'embedding'` | `'standalone'` | Standalone hides the MI navigation; embedding keeps it |
152
- | `include` | `'top-bar' \| 'shared-components'`| — | Bundle MI top-bar assets into the build (requires `standalone`) |
153
- | `apiVersion` | `6 \| 7` | `7` | MI API version to target |
154
-
155
- ### `app` — Portal Page identity
156
-
157
- | Field | Type | Default | Description |
158
- |--------|----------------------------|--------------------------|-------------------------------------------------------------|
159
- | `id` | `number` | — | Portal Page ID used to fetch template variables |
160
- | `type` | `'template' \| 'page'` | `'template'` | `template` syncs back to MI; `page` is standalone-only |
161
- | `name` | `string` | `package.json#name` | Template name on the MI instance (usually auto-resolved) |
162
-
163
- ### `proxy` — Request proxying
164
-
165
- | Field | Type | Default | Description |
166
- |---------------------|-----------|----------|------------------------------------------------------|
167
- | `cache` | `boolean` | `true` | Enable caching of proxied requests |
168
- | `cacheTtl` | `number` | `600000` | Cache TTL in milliseconds (10 minutes) |
169
- | `tls.allowSelfSigned` | `boolean` | `false` | Allow self-signed SSL certificates on the MI server |
170
-
171
- ### `build` — Build output
172
-
173
- | Field | Type | Default | Description |
174
- |---------------------|-------------------------------------------------------------|----------|--------------------------------------------------------------------------------------|
175
- | `outDir` | `string` | `'dist'` | Output directory |
176
- | `zip` | `boolean \| { fileName?: string; outDir?: string; inDir?: string }` | `true` | Zip build output. Object form customizes filename and directories. |
177
- | `versionFile` | `boolean \| { enabled?: boolean; fileNameTemplate?: string }` | `true` | Write a VERSION file into the build |
178
- | `imageOptimisations`| `boolean \| Record<string, unknown>` | `true` | Image optimization. See [vite-plugin-image-optimizer](https://www.npmjs.com/package/vite-plugin-image-optimizer#plugin-options) for object options |
179
-
180
- ### `inspector` — Request Inspector
181
-
182
- | Field | Type | Default | Description |
183
- |----------------|-----------|-------------|----------------------------------------------------------------|
184
- | `enabled` | `boolean` | `true` | Enable the request inspector |
185
- | `maxMemory` | `number` | `104857600` | Max total body memory (bytes) before oldest entries are evicted (default 100 MB) |
186
- | `captureLimit` | `number` | `10485760` | Max body size captured per request/response (bytes, default 10 MB). Larger bodies are stored truncated. |
187
-
188
- ### `sync` — Template sync
189
-
190
- | Field | Type | Default | Description |
191
- |--------------|-------------------|-------------|-----------------------------------------------------------------------------------------------------|
192
- | `backupsDir` | `string` | `'backups'` | Directory for backups from the MI server |
193
- | `maxBackups` | `number \| false` | `20` | How many of this page's backups to keep; each new backup deletes the oldest beyond that. `false` or `0` keeps them all. |
194
- | `buildTimeoutMs` | `number` | `600000` | How long the build a sync starts (`pp-dev build`, `next build`) may run, in milliseconds, before it is stopped and the sync fails (default 10 minutes). |
195
-
196
- ### `devPanel` — Dev panel appearance
197
-
198
- | Field | Type | Default | Description |
199
- |------------|-----------------------------------------------------------------|------------------|-----------------------------------------------------------------------------|
200
- | `position` | `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` | `'bottom-right'` | Screen corner the dev panel is anchored to |
201
- | `hidden` | `boolean` | `false` | Fully hide the panel. Restore in the browser with `?pp-dev-panel=show` |
202
- | `autoHide` | `boolean` | `false` | Panel slides behind the screen edge leaving a thin strip; hover reveals it |
203
-
204
- These values are **defaults**: the panel itself has a settings popover (gear icon) with a corner
205
- picker, an auto-hide toggle and a hide button, and the panel can be dragged by its grip handle and
206
- snapped to any corner. Runtime choices are persisted in the browser's `localStorage`
207
- (`pp-dev-info-position`, `pp-dev-info-auto-hide`, `pp-dev-info-hidden`) and take precedence over
208
- the config until "Reset to config defaults" is clicked in the popover. The URL params
209
- `?pp-dev-panel=show` / `?pp-dev-panel=hide` set a persistent override too — handy for restoring a
210
- hidden panel or taking clean screenshots. Note that `localStorage` is origin-scoped, so overrides
211
- apply to every pp-dev app served on the same host and port. See the [Dev Panel](#dev-panel)
212
- section for the full feature description.
213
-
214
- ### `users` — Working as other users
215
-
216
- | Field | Type | Default | Description |
217
- |-----------|-----------|---------|--------------------------------------------------------------------------------------------------------------|
218
- | `persist` | `boolean` | `false` | Keep the users added with an API token between dev server runs, in `~/.pp-dev/users/` (plain text, readable by you only; on Windows, by your profile's permissions) |
219
-
220
- See [Working as other users](#working-as-other-users).
221
-
222
- ### `server` — The dev server
223
-
224
- | Field | Type | Default | Description |
225
- |----------------|--------------------|---------|-------------|
226
- | `allowedHosts` | `string[] \| true` | `[]` | Host names the dev server answers besides `localhost`, `*.localhost` and IP addresses, as Vite's [`server.allowedHosts`](https://vite.dev/config/server-options#server-allowedhosts): `'my-app.ngrok.app'`, or `'.ngrok.app'` for the domain and its subdomains. `true` answers any host; avoid it |
227
-
228
- A request whose `Host` is any other name gets 403: that is how DNS rebinding reaches a local server
229
- (a page on `evil.example:3000` whose name is then pointed at `127.0.0.1`). `pp-dev` passes the list
230
- to Vite, which checks `Host` itself; `pp-dev next` checks it for every request and WebSocket. The
231
- `--host <name>` you start the server with is allowed too.
232
-
233
- **Tunnels** (ngrok, cloudflared, an nginx in front): list the tunnel's exact name
234
- (`'my-app.ngrok.app'`). The dev server then answers that `Host`, and the pages served through the
235
- tunnel may use its own API (`/@api/*`), the dev panel's WebSocket and, under `pp-dev next`, Next's
236
- HMR: in development `withPPDev()` adds the exact names to Next's
237
- [`allowedDevOrigins`](https://nextjs.org/docs/app/api-reference/config/next-config-js/allowedDevOrigins),
238
- next to the ones in your Next config. A `.domain` entry (`'.ngrok.app'`) only answers the `Host`:
239
- as a page's origin it would let any page on that domain, someone else's tunnel too, act with your MI
240
- token or read Next's dev resources.
241
-
242
- Use a tunnel that keeps its name in `Host` (ngrok's default). One that rewrites `Host` to
243
- `localhost` (`ngrok --host-header=rewrite`, cloudflared's `httpHostHeader`, nginx
244
- `proxy_set_header Host localhost`) serves the pages, but the dev server then knows itself only as
245
- `localhost`: MI's redirects and the MI links it rewrites in responses point the browser at
246
- `localhost`, out of the tunnel. `X-Forwarded-Host` is not trusted to fix that: a rebinding page
247
- can send it.
248
-
249
- ```ts
250
- export default defineConfig({
251
- // ...
252
- server: { allowedHosts: ['my-app.ngrok.app'] },
253
- });
254
- ```
255
-
256
- ### Validation
257
-
258
- pp-dev validates your config at startup and reports problems clearly:
259
-
260
- | Condition | Behaviour |
261
- |---|---|
262
- | `mi.include` set + `mi.mode !== 'standalone'` | error |
263
- | `mi.url` missing + `mi.mode === 'embedding'` or `app.type === 'template'` | error |
264
- | `mi.url` missing + `mi.mode === 'standalone'` + `app.type === 'page'` | warning |
265
- | `app.type === 'template'` without `app.id` | error |
266
- | `app.type === 'page'` + `mi.mode === 'standalone'` without `app.id` | error |
267
- | `app.name` missing and no `package.json#name` | error |
268
- | `devPanel.position` not one of the four corners | error |
269
- | `server.allowedHosts` neither a list of host names nor `true` | error |
270
-
271
- ### Environment Variables
272
-
273
- | Variable | Description |
274
- |----------------------------------|-------------------------------------------------------------------------------------|
275
- | `MI_ACCESS_TOKEN` | Default value for `mi.token` when not set in config |
276
- | `PP_DEV_DIST_ZIP` | `true`/`false` — override `build.zip` for `pp-dev build` / `pp-dev next-build` |
277
- | `PP_DEV_DIST_ZIP_DIR` | Override the ZIP output directory (`build.zip.outDir`) |
278
- | `PP_DEV_DIST_ZIP_FILENAME` | Override the ZIP file name (`build.zip.fileName`) |
279
- | `PP_DEV_VERSION_MANIFEST` | `true`/`false` — override `build.versionFile` (VERSION/BUILD-MANIFEST generation) |
280
- | `PP_DEV_VERSION_FILE_TEMPLATE` | Override the VERSION file name template |
281
-
282
- The `PP_DEV_DIST_ZIP*`/`PP_DEV_VERSION_*` variables are read by `pp-dev build` and
283
- `pp-dev next-build`; an equivalent CLI flag always takes precedence over its env var. See
284
- [Build](#build) / [Next.js Build](#nextjs-build).
285
-
286
- **Local development and network exposure**: pp-dev is a **development** tool. It assumes a trusted machine. Personal access tokens and session helpers are still sensitive: they can authenticate to your Metric Insights backend as you.
287
-
288
- - Prefer binding the dev server to **`localhost`** when you do not need access from other devices. If you use **`--host`** (or equivalent) so the app listens on **all interfaces** or your LAN, other machines on the same network can reach the dev server and its dev-only routes. Treat that like exposing credentials: use only on networks you trust, or restrict access with your OS firewall.
289
- - Do not commit real tokens; keep them in `.env` (gitignored) or your secret store.
290
-
291
- ## Migrating from 0.x
292
-
293
- Run the built-in codemod to upgrade your config automatically:
294
-
295
- ```bash
296
- npx @metricinsights/pp-dev migrate
297
- ```
298
-
299
- Options:
300
-
301
- | Option | Description |
302
- |---|---|
303
- | `[config]` | Path to config file (auto-detected if omitted) |
304
- | `--dry-run` | Preview the migrated output without writing |
305
- | `--format ts\|js\|json` | Override output format |
306
- | `--output <file>` | Write to a specific file instead of overwriting |
307
- | `--no-backup` | Skip creating a `.bak` backup of the original |
308
-
309
- The command detects flat 0.x configs and legacy `pp-watch.config.*` files, converts them to the new grouped format, and writes a `.bak` backup before overwriting.
310
-
311
- **Field mapping** (0.x → 1.0):
312
-
313
- | 0.x | 1.0 |
314
- |---|---|
315
- | `backendBaseURL` | `mi.url` |
316
- | `personalAccessToken` | `mi.token` |
317
- | `miHudLess: true` | `mi.mode: 'standalone'` |
318
- | `miHudLess: false` | `mi.mode: 'embedding'` |
319
- | `integrateMiTopBar: true` | `mi.mode: 'standalone'`, `mi.include: 'top-bar'` |
320
- | `integrateMiTopBar: { addSharedComponentsScripts: true }` | `mi.include: 'shared-components'` |
321
- | `v7Features: true` | `mi.apiVersion: 7` |
322
- | `v7Features: false` | `mi.apiVersion: 6` |
323
- | `appId` / `portalPageId` | `app.id` |
324
- | `templateName` | `app.name` (usually omit — auto-resolved from `package.json#name`) |
325
- | `templateLess: true` | `app.type: 'page'` |
326
- | `templateLess: false` | `app.type: 'template'` |
327
- | `enableProxyCache` | `proxy.cache` |
328
- | `proxyCacheTTL` | `proxy.cacheTtl` |
329
- | `disableSSLValidation: true` | `proxy.tls.allowSelfSigned: true` |
330
- | `distZip` | `build.zip` |
331
- | `versionPlugin` | `build.versionFile` |
332
- | `imageOptimizer` | `build.imageOptimisations` |
333
- | `outDir` | `build.outDir` |
334
- | `syncBackupsDir` | `sync.backupsDir` |
335
-
336
- ## CLI Commands
337
-
338
- ### Global Options
339
-
340
- | Option | Description |
341
- | ------------------------ | -------------------------------------------------------------------------------- |
342
- | `-c, --config <file>` | Path to configuration file (default: `pp-dev.config.js`) |
343
- | `--base <path>` | Public base path (default: `/`) |
344
- | `-l, --logLevel <level>` | Log level: `trace`, `debug`, `info`, `warn`, `error`, `silent` (default: `info`) |
345
- | `--clearScreen` | Clear screen before logging |
346
- | `--mode <mode>` | Environment mode: `development`, `production`, `test` (default: `development`) |
347
-
348
- ### Development Server
349
-
350
- ```bash
351
- pp-dev [root] [options]
352
- # Aliases: pp-dev dev, pp-dev serve
353
- ```
354
-
355
- | Option | Default | Description |
356
- | --------------- | ----------- | --------------------------------- |
357
- | `[root]` | `.` | Root directory of the application |
358
- | `--host <host>` | `localhost` | Server hostname |
359
- | `--port <port>` | `3000` | Server port |
360
- | `--open [path]` | - | Open browser on server start |
361
- | `--strictPort` | - | Exit if port is already in use |
362
-
363
- **Development Shortcuts**:
364
-
365
- - `l` - Proxy re-login (refresh authentication)
366
- - `r` - Restart dev server
367
- - `u` - Show server URLs
368
- - `q` - Quit dev server
369
-
370
- ### Next.js Development
371
-
372
- ```bash
373
- pp-dev next [options]
374
- # Aliases: pp-dev next-server, pp-dev next-dev
375
- ```
376
-
377
- | Option | Default | Description |
378
- | --------------- | ----------- | -------------------------------------------------------------------- |
379
- | `[root]` | `.` | Root directory of the application |
380
- | `--port <port>` | `3000` | Server port |
381
- | `--host [host]` | `localhost` | Server hostname; `--host` without a value listens on all addresses |
382
- | `--webpack` | - | Use Webpack for Next dev (when Turbopack/native SWC is unavailable) |
383
- | `--turbopack` | - | Use Turbopack for Next dev |
384
-
385
- `--https`, `--open`, `--cors`, `--strictPort` and `--force` are accepted for compatibility but have no effect with `pp-dev next` (a warning says so); they will be removed.
386
-
387
- ### Build
388
-
389
- ```bash
390
- pp-dev build [options]
391
- ```
392
-
393
- | Option | Default | Description |
394
- | ------------------------------- | --------- | ------------------------------------------------------ |
395
- | `[root]` | `.` | Root directory of the application |
396
- | `--target <target>` | `modules` | Transpile target |
397
- | `--outDir <dir>` | `dist` | Output directory |
398
- | `--assetsDir <dir>` | `assets` | Assets directory under outDir |
399
- | `--changelog [file]` | `true` | Create changelog file |
400
- | `--distZip` / `--no-distZip` | see below | Override `build.zip` — pack (or skip) the output ZIP |
401
- | `--distZipDir <dir>` | see below | Override the ZIP output directory (`build.zip.outDir`) |
402
- | `--distZipFilename <file>` | see below | Override the ZIP file name (`build.zip.fileName`) |
403
- | `--versionManifest` / `--no-versionManifest` | see below | Override `build.versionFile` — emit (or skip) VERSION/BUILD-MANIFEST |
404
- | `--versionFileTemplate <tpl>` | see below | Override the VERSION file name template |
405
-
406
- The `--distZip*`/`--versionManifest*` flags (and their `PP_DEV_*` env var equivalents, see
407
- [Environment Variables](#environment-variables)) let CI or ad-hoc builds override the `build.zip`
408
- and `build.versionFile` config without editing `pp-dev.config`. Precedence: CLI flag > env var >
409
- config file > built-in default. The same flags are available on `pp-dev next-build` (below).
410
-
411
- ### Next.js Build
412
-
413
- ```bash
414
- pp-dev next-build [options]
415
- ```
416
-
417
- Plain `next build` only produces the Next.js static export — no VERSION file, BUILD-MANIFEST, or
418
- ZIP archive. `pp-dev next-build` runs `next build` and then applies the same post-build steps as
419
- `pp-dev build`, so Next.js and Vite templates produce build artifacts in the same format:
420
-
421
- 1. Runs `next build` (requires `output: 'export'` in `next.config`)
422
- 2. Writes `VERSION-*.json` + `BUILD-MANIFEST.json` into the export directory (`build.versionFile`)
423
- 3. Zips the export directory into `dist-zip/<name>.zip` (`build.zip`)
424
-
425
- If a project using `withPPDev()` still runs plain `next build` (e.g. directly, or via a `build`
426
- script nobody updated), `withPPDev()` prints a console warning during the production build phase
427
- suggesting `pp-dev next-build` instead. The warning is suppressed automatically when the build was
428
- started by `pp-dev next-build` itself.
429
-
430
- Use it in place of `next build` in your `package.json`:
431
-
432
- ```json
433
- {
434
- "scripts": {
435
- "build": "pp-dev next-build --changelog"
436
- }
437
- }
438
- ```
439
-
440
- | Option | Default | Description |
441
- | ------------------------------- | --------- | ------------------------------------------------------ |
442
- | `[root]` | `.` | Root directory of the application |
443
- | `--changelog [file]` | `true` | Create changelog file |
444
- | `--distZip` / `--no-distZip` | see below | Override `build.zip` — pack (or skip) the output ZIP |
445
- | `--distZipDir <dir>` | see below | Override the ZIP output directory (`build.zip.outDir`) |
446
- | `--distZipFilename <file>` | see below | Override the ZIP file name (`build.zip.fileName`) |
447
- | `--versionManifest` / `--no-versionManifest` | see below | Override `build.versionFile` — emit (or skip) VERSION/BUILD-MANIFEST |
448
- | `--versionFileTemplate <tpl>` | see below | Override the VERSION file name template |
449
-
450
- ### Migration
451
-
452
- ```bash
453
- pp-dev migrate [config] [options]
454
- ```
455
-
456
- | Option | Description |
457
- |---|---|
458
- | `[config]` | Config file to migrate (auto-detected if omitted) |
459
- | `--dry-run` | Preview output without writing |
460
- | `--format ts\|js\|json` | Output format |
461
- | `--output <file>` | Write to a specific path |
462
- | `--no-backup` | Skip `.bak` backup |
463
-
464
- ### Changelog Generation
465
-
466
- ```bash
467
- pp-dev changelog [oldAssetPath] [newAssetPath] [options]
468
- ```
469
-
470
- | Option | Default | Description |
471
- | ------------------------ | ---------------- | -------------------------- |
472
- | `[oldAssetPath]` | - | Path to previous assets |
473
- | `[newAssetPath]` | - | Path to current assets |
474
- | `--oldAssetsPath <path>` | - | Path to previous assets |
475
- | `--newAssetsPath <path>` | - | Path to current assets |
476
- | `--destination <path>` | `.` | Changelog output directory |
477
- | `--filename <name>` | `CHANGELOG.html` | Changelog filename |
478
-
479
- ### Icon Font Generation
480
-
481
- ```bash
482
- pp-dev generate-icon-font [source] [destination] [options]
483
- ```
484
-
485
- | Option | Default | Description |
486
- | ---------------------- | ----------- | ------------------------------- |
487
- | `[source]` | - | Source directory with SVG icons |
488
- | `[destination]` | - | Output directory |
489
- | `--source <path>` | - | Source directory with SVG icons |
490
- | `--destination <path>` | - | Output directory |
491
- | `--fontName <name>` | `icon-font` | Font name |
492
-
493
- ## Next.js Integration
494
-
495
- 1. Add a `pp-dev.config.ts` to your project root
496
- 2. Update `package.json` scripts:
497
- ```json
498
- {
499
- "scripts": {
500
- "dev": "pp-dev next",
501
- "build": "pp-dev next-build"
502
- }
503
- }
504
- ```
505
- `pp-dev next-build` replaces a plain `next build` so the Next.js template produces the same
506
- VERSION/BUILD-MANIFEST/ZIP artifacts as `pp-dev build` — see [Next.js Build](#nextjs-build).
507
- 3. Wrap your Next.js config:
508
-
509
- ```javascript
510
- // next.config.js
511
- const { withPPDev } = require('@metricinsights/pp-dev');
512
-
513
- module.exports = withPPDev({
514
- // your Next.js config
515
- });
516
- ```
517
-
518
- ## Vite Configuration
519
-
520
- For custom build configuration, create a `vite.config` file. See [Vite Configuration](https://vitejs.dev/config/) for details.
521
-
522
- ## Dev Panel
523
-
524
- pp-dev injects a floating dev panel into every served page. It shows the pp-dev version (linked to npm), the backend URL, the template mode and the App ID, and hosts the template **Sync** button and the [Users](#working-as-other-users) button. Since 1.0 the panel is fully repositionable and can be hidden.
525
-
526
- ![Dev panel settings popover](./docs/screenshots/03-panel-settings.png)
527
-
528
- ### Position
529
-
530
- The panel can be anchored to any of the four screen corners (default: bottom-right). Three ways to move it:
531
-
532
- - **Drag & snap** — grab the grip handle (six dots on the panel's left side) and drag; on release the panel snaps to the nearest corner. Dragging works across iframes and is cancelled with <kbd>Escape</kbd>.
533
- - **Settings popover** — click the gear icon and pick a corner in the 2×2 grid.
534
- - **Config default** — set `devPanel.position` in `pp-dev.config` (see below).
535
-
536
- The minimize arrow, the panel's shadow, rounded corner and slide direction all mirror automatically for left/top placements. Sync notification popups stack from the screen edge opposite the panel so they never cover it.
537
-
538
- ### Auto-hide
539
-
540
- Toggle **Auto-hide** in the settings popover (or set `devPanel.autoHide: true`). The panel slides behind the nearest screen edge leaving a 4px accent strip; hovering the strip for ~300 ms slides it out, and it hides again ~500 ms after the pointer leaves. Keyboard focus inside the panel keeps it revealed. While auto-hide is active the minimize arrow acts as a **pin** button that returns the panel to normal mode.
541
-
542
- ### Theme
543
-
544
- The settings popover has an **Auto / Dark / Light** switcher. "Auto" follows the OS/browser preference; the other two force an override. The choice is shared (via the same `localStorage` key) with the standalone [Request Inspector](#request-inspector) and [Variables Editor](#variables-editor) pages, which also each have their own copy of the switcher for when they're opened directly without the panel present.
545
-
546
- ### Hiding and restoring
547
-
548
- **Hide panel** in the settings popover (or `devPanel.hidden: true`) removes the panel from view entirely. To bring it back, open any page with `?pp-dev-panel=show` in the URL — the override persists across reloads. The symmetric `?pp-dev-panel=hide` hides it, which is handy for demos and clean screenshots.
549
-
550
- ### State persistence
551
-
552
- Runtime choices are saved in the browser's `localStorage` (`pp-dev-info-position`, `pp-dev-info-auto-hide`, `pp-dev-info-hidden`, `pp-dev-info-theme`) and take precedence over config values. **Reset to config defaults** in the settings popover clears all overrides. Storage is origin-scoped: overrides apply to every pp-dev app served on the same host and port, and a Metric Insights page that clears origin storage will reset them to config defaults.
553
-
554
- ### Configuration
555
-
556
- ```typescript
557
- // pp-dev.config.ts
558
- export default defineConfig({
559
- devPanel: {
560
- position: 'bottom-right', // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
561
- hidden: false, // hide the panel entirely (restore with ?pp-dev-panel=show)
562
- autoHide: false, // slide behind the screen edge, reveal on hover
563
- },
564
- });
565
- ```
566
-
567
- See the [`devPanel` option reference](#devpanel--dev-panel-appearance) for details.
568
-
569
- ### Page variables
570
-
571
- For pages with a template (`app.type: 'template'`), the settings popover has:
572
-
573
- - **Reload variables** — refetches the page's live variable values from MI right now (bypassing the usual request-level cache) and reloads the page, so `[VarName]` substitution reflects a just-saved value without restarting the dev server.
574
- - **Open variables editor…** — opens the standalone [Variables Editor](#variables-editor) page.
575
-
576
- Pages without a template (`app.type: 'page'`) have no variables, so this group — and the button that opens the editor — is hidden.
577
-
578
- ### Variables Editor
579
-
580
- A standalone page at `/@pp-dev/variables-editor`, alongside the [Request Inspector](#request-inspector), with two tabs:
581
-
582
- - **Schema** — view/edit the template's `__template_variables.json` (add/remove variables, change type, default, `additional_options`, etc.), with a raw-JSON escape hatch.
583
-
584
- ![Variables Editor — Schema tab](./docs/screenshots/06-editor-schema.png)
585
-
586
- - **Values** — edit the page's live variable values in place, with type-aware widgets (searchable select for `static` options, a per-item form for `list`, …). A JSON mode (`View/edit raw JSON`) shows/accepts the same values as plain JSON — list-type values as native arrays, not double-escaped strings — with **Save to JSON file…** / **Import from JSON file…** buttons, and flags values that don't match a declared option, changed since the last load, or aren't in the schema. Each variable's description is shown as markdown, the way MI renders it: **bold**, *italic*, `code` and fenced code blocks, lists, and `<u>` / `<s>` / `<del>` for underline and strikethrough.
587
-
588
- The pages the dev server serves substitute `[VarName]` from its own copy of the values, loaded from MI with the page data. **Save** updates that copy too, so every tab (any user) shows the saved values on its next load. When the values in MI change some other way (edited in MI itself, or the update after a save failed), the Values tab shows **Update local pages · N** in its bottom-right corner; its tooltip lists the values that differ, and a click updates the copy.
589
-
590
- ![Variables Editor — Values tab](./docs/screenshots/09-editor-values.png)
591
-
592
- Both the active tab and Values' JSON mode are reflected in the URL (`?tab=values&mode=json`), so a specific view can be bookmarked or shared.
593
-
594
- See the [feature tour](./docs/features.md#variables-editor) for more screenshots, including the advanced/raw-JSON views and the theme switcher.
595
-
596
- See [`TEMPLATE_VARIABLES.md`](./TEMPLATE_VARIABLES.md) — also shipped inside the published package — for the `__template_variables.json` schema this feature reads.
597
-
598
- ## Working as other users
599
-
600
- Check how a Portal Page looks and behaves for users with other permissions, groups or data access, without restarting pp-dev or logging out. Add users in the dev panel's **Users** popover (the people icon) and open the page as any of them — side by side with your own tab.
601
-
602
- ![Users popover](./docs/screenshots/13-users-popover.png)
603
-
604
- ### How it works
605
-
606
- Every saved user gets its own host: `<name>.localhost:<port>`. The browser sends that host with every request of the tab (fetches, images, links, reloads, tabs opened from it, WebSockets) and keeps cookies and storage per host, so pp-dev knows whom each request is for, and the users' MI sessions never mix. Browsers resolve `*.localhost` to your machine on their own.
607
-
608
- - **`localhost:<port>`** works as the **default user**: you, unless you check another user in the popover.
609
- - **`<name>.localhost:<port>`** works as that user. Its dev panel's Users button is purple, so the tab is never taken for your own.
610
- - **The dev panel itself** (sync, page variables, Variables Editor, Request Inspector) always works as you, on every host.
611
-
612
- ### Requirements
613
-
614
- - **Your own API token** (`mi.token` or `MI_ACCESS_TOKEN`): the dev panel works as you through it. Without it the popover explains why users can't be added.
615
- - **The dev server opened on `localhost`**: hosts like `<name>.localhost` don't exist on an IP address or a custom domain; there pp-dev works as before, without users.
616
-
617
- ### Adding users
618
-
619
- - **API token**: the token is checked with MI before the user is added. SSO users can only be added this way.
620
- - **Username + password** (local MI users): pp-dev adds the user and opens MI's usual login page on the user's own host. You log in there as in MI — 2FA included — and pp-dev never sees the password. Until then the user is *not logged in yet*; once MI ends the session it is *session expired* and **Log in** opens the login page again.
621
-
622
- The name becomes the user's host, so it may contain only lowercase latin letters, digits and `-`, must start with a letter and be at most 32 characters long.
623
-
624
- **Edit** on a user added with an API token renames it or replaces its token (a new token is checked with MI; left empty, the current one stays). While the dev server runs, a page load on its old host (an open tab, a bookmark) moves to the new one, and requests from tabs still open there keep working as the user. A user that logs in with a password can't be edited, since its MI session lives in its host's cookies: remove it and add it again.
625
-
626
- ### Logging out and removing
627
-
628
- Logging out on a user's host ends that user's MI session (or token) as it would in MI, removes the user, and sends the tab back to `localhost`. **×** in the popover removes a user without logging it out of MI. Either way pp-dev drops what it cached for that user.
629
-
630
- ### Keeping users between runs
631
-
632
- Users live as long as the dev server. With `users: { persist: true }` the users added with an API token are kept in `~/.pp-dev/users/<hash>.json` — one file per project and MI instance, outside the project so it never ends up in git or a build. The tokens are stored as plain text: on macOS and Linux the file is readable by you only (mode `0600`); Windows ignores file modes, so there it is as private as your user profile folder (by default readable by you, administrators and the system). Two dev servers on the same project and MI instance share the file: each keeps the users the other added. Passwords and MI sessions are never written. On start, every kept token is checked with MI again; one MI turns down shows as *API token turned down by MI*.
633
-
634
- ```typescript
635
- // pp-dev.config.ts
636
- export default defineConfig({
637
- users: {
638
- persist: true,
639
- },
640
- });
641
- ```
642
-
643
- ### REST API
644
-
645
- The popover uses a small JSON API:
646
-
647
- | Method | Path | Description |
648
- |----------|-------------------------|---------------------------------------------------------------------------------------------------|
649
- | `GET` | `/@api/users` | The users (name, kind, state, MI user, `origin`, `loginUrl`), the default user, and whether users are available |
650
- | `POST` | `/@api/users` | Add a user: `{ "name", "token" }`, or `{ "name", "kind": "session" }` to log in with a password |
651
- | `PUT` | `/@api/users/default` | Make a user the default: `{ "name" }`, or `{ "name": null }` for you |
652
- | `PATCH` | `/@api/users/:name` | Edit a user added with an API token: `{ "name" }` to rename it, `{ "token" }` to replace its token |
653
- | `DELETE` | `/@api/users/:name` | Remove a user |
654
-
655
- Tokens and MI sessions are never sent back.
656
-
657
- ## Request Inspector
658
-
659
- pp-dev includes a built-in request inspector that captures every proxied and locally-served HTTP request made during development. It is enabled by default.
660
-
661
- ### Web UI
662
-
663
- Open `http://localhost:3000/@pp-dev/inspector` (replace port as needed) in any browser tab while the dev server is running. The UI shows:
664
-
665
- - A scrollable list of captured requests with method, status, source badge, and timing
666
- - A tag with the user whose tab made the request, and a user filter, once you [work as other users](#working-as-other-users)
667
- - Full request and response headers, with a **Copy** button per section. Credentials are kept out: an `Authorization` value and the MI session cookie show as `<redacted>`
668
- - Request and response bodies rendered as text for JSON/HTML/CSS/plain-text content types, with **Copy** and **Save** buttons
669
- - Binary bodies (images, fonts, archives) show metadata only and offer a **Save** button
670
-
671
- ![Request Inspector — request list](./docs/screenshots/04-inspector-list.png)
672
-
673
- Selecting a request opens the detail pane with headers and a syntax-highlighted body:
674
-
675
- ![Request Inspector — request detail](./docs/screenshots/05-inspector-detail.png)
676
- - A **Clear** button in the top-right removes all stored entries
677
-
678
- ### Source badges
679
-
680
- Each request in the list displays a colored letter badge to the left of the HTTP status:
681
-
682
- | Badge | Color | Meaning |
683
- |-------|--------|----------------------------------------------|
684
- | `P` | Purple | Forwarded to the upstream Metric Insights server (proxy) |
685
- | `C` | Amber | Served from the local proxy cache |
686
- | `L` | Grey | Served locally (static file, dev route, etc.) |
687
-
688
- ### Console banner
689
-
690
- The dev panel script prints a one-line banner to the browser DevTools console when the page loads:
691
-
692
- ```
693
- pp-dev 🔍 Request Inspector → http://localhost:3000/@pp-dev/inspector
694
- ```
695
-
696
- The message persists in DevTools history so it is visible even when you open the console after the page has loaded.
697
-
698
- ### REST API
699
-
700
- The inspector also exposes a lightweight JSON API, useful for tooling and AI agents:
701
-
702
- | Method | Path | Description |
703
- |----------|-------------------------|---------------------------------------------|
704
- | `GET` | `/@api/requests` | Paginated list of captured requests (metadata only, no bodies) |
705
- | `GET` | `/@api/requests/:id` | Full entry including captured request/response bodies (base64-encoded) |
706
- | `GET` | `/@api/requests/stats` | Store stats: entry count, memory usage, limits |
707
- | `DELETE` | `/@api/requests` | Clear all stored entries |
708
-
709
- `GET /@api/requests` accepts `?limit=` (default 50) and `?offset=` query parameters for pagination.
710
-
711
- Bodies in `GET /@api/requests/:id` are returned as base64 strings in `requestBody` / `responseBody` fields alongside `requestContentType` / `responseContentType`. A `*Truncated: true` flag indicates the body exceeded `captureLimit` and was cut off.
712
-
713
- ### Configuration
714
-
715
- ```typescript
716
- // pp-dev.config.ts
717
- export default defineConfig({
718
- inspector: {
719
- enabled: true, // set to false to disable entirely
720
- maxMemory: 100 * 1024 * 1024, // evict oldest entries above 100 MB
721
- captureLimit: 10 * 1024 * 1024, // capture at most 10 MB per body
722
- },
723
- });
724
- ```
725
-
726
- ## Troubleshooting
727
-
728
- ### Common Issues
729
-
730
- #### Next.js Peer Dependency Error
731
-
732
- If you encounter an error like "Next.js is required but not available":
733
-
734
- 1. **Install Next.js in your project:**
735
-
736
- ```bash
737
- npm install next@^15
738
- ```
739
-
740
- 2. **Verify the installation:**
741
-
742
- ```bash
743
- npm list next
744
- ```
745
-
746
- 3. **Check your package.json:**
747
- ```json
748
- {
749
- "dependencies": {
750
- "next": "^15.0.0"
751
- }
752
- }
753
- ```
754
-
755
- #### Version Compatibility
756
-
757
- - **pp-dev** requires Next.js version 15 or higher (but less than 17)
758
- - **Node.js** version 24 or higher is required
759
- - **TypeScript** version 5 or higher is recommended
760
-
761
- ### Getting Help
762
-
763
- - Check the [GitHub Issues](https://github.com/mi-examples/pp-dev-js/issues) for known problems
764
- - Review the [CHANGELOG.md](./CHANGELOG.md) for recent changes
765
- - Ensure all peer dependencies are properly installed