@metricinsights/pp-dev 1.5.0-beta.3 → 1.5.0-beta.30

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.
Files changed (72) hide show
  1. package/README.md +198 -145
  2. package/dist/cjs/auth.provider-BT1sgf1x.js +2 -0
  3. package/dist/cjs/auth.provider-BT1sgf1x.js.map +1 -0
  4. package/dist/cjs/cli.js +1 -1
  5. package/dist/cjs/cli.js.map +1 -1
  6. package/dist/cjs/index-D9zJqX2X.js +2 -0
  7. package/dist/cjs/index-D9zJqX2X.js.map +1 -0
  8. package/dist/cjs/index.js +1 -1
  9. package/dist/cjs/migrate-CuzJuHC1.js +2 -0
  10. package/dist/cjs/migrate-CuzJuHC1.js.map +1 -0
  11. package/dist/cjs/package.json +2 -135
  12. package/dist/cjs/plugin.js +1 -1
  13. package/dist/cjs/plugin.js.map +1 -1
  14. package/dist/cjs/request-capture.middleware-Bihrs8O-.js +2 -0
  15. package/dist/cjs/request-capture.middleware-Bihrs8O-.js.map +1 -0
  16. package/dist/cjs/version-manifest-5tqQXsyA.js +2 -0
  17. package/dist/cjs/version-manifest-5tqQXsyA.js.map +1 -0
  18. package/dist/cjs/version-plugin-JOQRBtAn.js +2 -0
  19. package/dist/cjs/version-plugin-JOQRBtAn.js.map +1 -0
  20. package/dist/client/client.js +269 -125
  21. package/dist/client/client.js.map +1 -1
  22. package/dist/client/request-inspector.css +3 -0
  23. package/dist/client/request-inspector.css.map +1 -0
  24. package/dist/client/request-inspector.html +87 -0
  25. package/dist/client/request-inspector.js +527 -0
  26. package/dist/client/request-inspector.js.map +1 -0
  27. package/dist/client/variables-editor.css +3 -0
  28. package/dist/client/variables-editor.css.map +1 -0
  29. package/dist/client/variables-editor.html +44 -0
  30. package/dist/client/variables-editor.js +3474 -0
  31. package/dist/client/variables-editor.js.map +1 -0
  32. package/dist/esm/auth.provider-CMlTFLKr.js +2 -0
  33. package/dist/esm/auth.provider-CMlTFLKr.js.map +1 -0
  34. package/dist/esm/cli.js +1 -1
  35. package/dist/esm/cli.js.map +1 -1
  36. package/dist/esm/index-B4F5_U6S.js +2 -0
  37. package/dist/esm/index-B4F5_U6S.js.map +1 -0
  38. package/dist/esm/index.js +1 -1
  39. package/dist/esm/migrate-r4PvE5UL.js +2 -0
  40. package/dist/esm/{migrate-B2gJ62fm.js.map → migrate-r4PvE5UL.js.map} +1 -1
  41. package/dist/esm/package.json +2 -135
  42. package/dist/esm/plugin.js +1 -1
  43. package/dist/esm/plugin.js.map +1 -1
  44. package/dist/esm/request-capture.middleware-CYtDXIxP.js +2 -0
  45. package/dist/esm/request-capture.middleware-CYtDXIxP.js.map +1 -0
  46. package/dist/esm/version-manifest-BG-RUMD6.js +2 -0
  47. package/dist/esm/version-manifest-BG-RUMD6.js.map +1 -0
  48. package/dist/esm/version-plugin-BtTT_xRU.js +2 -0
  49. package/dist/esm/version-plugin-BtTT_xRU.js.map +1 -0
  50. package/dist/types/helpers.d.ts +29 -0
  51. package/dist/types/index.d.ts +15 -155
  52. package/dist/types/plugin.d.ts +8 -0
  53. package/dist/types/pp-dev-config-D889A-PO.d.ts +189 -0
  54. package/docs/features.md +2 -1
  55. package/package.json +26 -35
  56. package/dist/CHANGELOG.md +0 -442
  57. package/dist/README.md +0 -724
  58. package/dist/cjs/index-CCUrjlJE.js +0 -2
  59. package/dist/cjs/index-CCUrjlJE.js.map +0 -1
  60. package/dist/cjs/migrate-BYno__sx.js +0 -2
  61. package/dist/cjs/migrate-BYno__sx.js.map +0 -1
  62. package/dist/cjs/plugin-D_RXI7ru.js +0 -2
  63. package/dist/cjs/plugin-D_RXI7ru.js.map +0 -1
  64. package/dist/cjs/version-plugin-Bf4jLh17.js +0 -2
  65. package/dist/cjs/version-plugin-Bf4jLh17.js.map +0 -1
  66. package/dist/esm/index-BazQY12s.js +0 -2
  67. package/dist/esm/index-BazQY12s.js.map +0 -1
  68. package/dist/esm/migrate-B2gJ62fm.js +0 -2
  69. package/dist/esm/plugin-NIWxLreC.js +0 -2
  70. package/dist/esm/plugin-NIWxLreC.js.map +0 -1
  71. package/dist/esm/version-plugin-DwuZCHob.js +0 -2
  72. package/dist/esm/version-plugin-DwuZCHob.js.map +0 -1
package/README.md CHANGED
@@ -31,18 +31,18 @@ npm install @metricinsights/pp-dev
31
31
  This package requires Next.js as a peer dependency for certain functionality:
32
32
 
33
33
  ```bash
34
- npm install next@^15
34
+ npm install next@^16
35
35
  ```
36
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.
37
+ **Note**: pp-dev accepts Next.js 13 to 16 (`peerDependencies`: `>= 13 < 17`); the test apps run on Next.js 16. It is a peer dependency, so it isn't installed with pp-dev.
38
38
 
39
39
  ## Package Structure
40
40
 
41
41
  The pp-dev package provides multiple entry points for different use cases:
42
42
 
43
43
  ```javascript
44
- // Main package (includes everything)
45
- import ppDev from '@metricinsights/pp-dev';
44
+ // Main package (includes everything, defineConfig too)
45
+ import { withPPDev } from '@metricinsights/pp-dev';
46
46
 
47
47
  // Plugin only (for Vite integration)
48
48
  import { vitePPDev } from '@metricinsights/pp-dev/plugin';
@@ -51,7 +51,7 @@ import { vitePPDev } from '@metricinsights/pp-dev/plugin';
51
51
  import { defineConfig } from '@metricinsights/pp-dev/helpers';
52
52
 
53
53
  // Client assets (for development UI)
54
- import '@metricinsights/pp-dev/client/css/client.css';
54
+ import '@metricinsights/pp-dev/client/client.css';
55
55
  ```
56
56
 
57
57
  ## Configuration
@@ -144,60 +144,62 @@ module.exports = defineConfig({
144
144
 
145
145
  ### `mi` — Metric Insights connection
146
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 |
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
154
 
155
155
  ### `app` — Portal Page identity
156
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) |
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
162
 
163
163
  ### `proxy` — Request proxying
164
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 |
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
170
 
171
171
  ### `build` — Build output
172
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 |
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
179
 
180
180
  ### `inspector` — Request Inspector
181
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) |
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
186
  | `captureLimit` | `number` | `10485760` | Max body size captured per request/response (bytes, default 10 MB). Larger bodies are stored truncated. |
187
187
 
188
188
  ### `sync` — Template sync
189
189
 
190
- | Field | Type | Default | Description |
191
- |--------------|----------|-------------|-----------------------------------------|
192
- | `backupsDir` | `string` | `'backups'` | Directory for backups from the MI server |
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). |
193
195
 
194
196
  ### `devPanel` — Dev panel appearance
195
197
 
196
- | Field | Type | Default | Description |
197
- |------------|-----------------------------------------------------------------|------------------|-----------------------------------------------------------------------------|
198
- | `position` | `'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right'` | `'bottom-right'` | Screen corner the dev panel is anchored to |
199
- | `hidden` | `boolean` | `false` | Fully hide the panel. Restore in the browser with `?pp-dev-panel=show` |
200
- | `autoHide` | `boolean` | `false` | Panel slides behind the screen edge leaving a thin strip; hover reveals it |
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 |
201
203
 
202
204
  These values are **defaults**: the panel itself has a settings popover (gear icon) with a corner
203
205
  picker, an auto-hide toggle and a hide button, and the panel can be dragged by its grip handle and
@@ -211,36 +213,71 @@ section for the full feature description.
211
213
 
212
214
  ### `users` — Working as other users
213
215
 
214
- | Field | Type | Default | Description |
215
- |-----------|-----------|---------|--------------------------------------------------------------------------------------------------------------|
216
- | `persist` | `boolean` | `false` | Keep the users added with an API token between dev server runs, in `~/.pp-dev/users/` (readable by you only) |
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) |
217
219
 
218
220
  See [Working as other users](#working-as-other-users).
219
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
+
220
256
  ### Validation
221
257
 
222
258
  pp-dev validates your config at startup and reports problems clearly:
223
259
 
224
- | Condition | Behaviour |
225
- |---|---|
226
- | `mi.include` set + `mi.mode !== 'standalone'` | error |
227
- | `mi.url` missing + `mi.mode === 'embedding'` or `app.type === 'template'` | error |
228
- | `mi.url` missing + `mi.mode === 'standalone'` + `app.type === 'page'` | warning |
229
- | `app.type === 'template'` without `app.id` | error |
230
- | `app.type === 'page'` + `mi.mode === 'standalone'` without `app.id` | error |
231
- | `app.name` missing and no `package.json#name` | error |
232
- | `devPanel.position` not one of the four corners | error |
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 |
233
270
 
234
271
  ### Environment Variables
235
272
 
236
- | Variable | Description |
237
- |----------------------------------|-------------------------------------------------------------------------------------|
238
- | `MI_ACCESS_TOKEN` | Default value for `mi.token` when not set in config |
239
- | `PP_DEV_DIST_ZIP` | `true`/`false` — override `build.zip` for `pp-dev build` / `pp-dev next-build` |
240
- | `PP_DEV_DIST_ZIP_DIR` | Override the ZIP output directory (`build.zip.outDir`) |
241
- | `PP_DEV_DIST_ZIP_FILENAME` | Override the ZIP file name (`build.zip.fileName`) |
242
- | `PP_DEV_VERSION_MANIFEST` | `true`/`false` — override `build.versionFile` (VERSION/BUILD-MANIFEST generation) |
243
- | `PP_DEV_VERSION_FILE_TEMPLATE` | Override the VERSION file name template |
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 |
244
281
 
245
282
  The `PP_DEV_DIST_ZIP*`/`PP_DEV_VERSION_*` variables are read by `pp-dev build` and
246
283
  `pp-dev next-build`; an equivalent CLI flag always takes precedence over its env var. See
@@ -261,40 +298,40 @@ npx @metricinsights/pp-dev migrate
261
298
 
262
299
  Options:
263
300
 
264
- | Option | Description |
265
- |---|---|
266
- | `[config]` | Path to config file (auto-detected if omitted) |
267
- | `--dry-run` | Preview the migrated output without writing |
268
- | `--format ts\|js\|json` | Override output format |
269
- | `--output <file>` | Write to a specific file instead of overwriting |
270
- | `--no-backup` | Skip creating a `.bak` backup of the original |
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 |
271
308
 
272
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.
273
310
 
274
311
  **Field mapping** (0.x → 1.0):
275
312
 
276
- | 0.x | 1.0 |
277
- |---|---|
278
- | `backendBaseURL` | `mi.url` |
279
- | `personalAccessToken` | `mi.token` |
280
- | `miHudLess: true` | `mi.mode: 'standalone'` |
281
- | `miHudLess: false` | `mi.mode: 'embedding'` |
282
- | `integrateMiTopBar: true` | `mi.mode: 'standalone'`, `mi.include: 'top-bar'` |
283
- | `integrateMiTopBar: { addSharedComponentsScripts: true }` | `mi.include: 'shared-components'` |
284
- | `v7Features: true` | `mi.apiVersion: 7` |
285
- | `v7Features: false` | `mi.apiVersion: 6` |
286
- | `appId` / `portalPageId` | `app.id` |
287
- | `templateName` | `app.name` (usually omit — auto-resolved from `package.json#name`) |
288
- | `templateLess: true` | `app.type: 'page'` |
289
- | `templateLess: false` | `app.type: 'template'` |
290
- | `enableProxyCache` | `proxy.cache` |
291
- | `proxyCacheTTL` | `proxy.cacheTtl` |
292
- | `disableSSLValidation: true` | `proxy.tls.allowSelfSigned: true` |
293
- | `distZip` | `build.zip` |
294
- | `versionPlugin` | `build.versionFile` |
295
- | `imageOptimizer` | `build.imageOptimisations` |
296
- | `outDir` | `build.outDir` |
297
- | `syncBackupsDir` | `sync.backupsDir` |
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` |
298
335
 
299
336
  ## CLI Commands
300
337
 
@@ -337,11 +374,26 @@ pp-dev next [options]
337
374
  # Aliases: pp-dev next-server, pp-dev next-dev
338
375
  ```
339
376
 
340
- | Option | Default | Description |
341
- | --------------- | ----------- | --------------------------------- |
342
- | `[root]` | `.` | Root directory of the application |
343
- | `--port <port>` | `3000` | Server port |
344
- | `--host <host>` | `localhost` | Server hostname |
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
+ **Template sync.** The panel's Sync builds the app with `next build` next to the running dev
388
+ server. That build is given Next's default `distDir`, so it goes to `.next` and its static export to
389
+ `out`, and the dev server's `<distDir>/dev` (its manifests and cache) is left alone. Before the build,
390
+ the dev server's generated route types (`<distDir>/dev/types`) are removed, as `pp-dev next-build`
391
+ does, since `next build` would type-check them next to its own; the dev server writes them again on
392
+ its next start. This needs `next.config` wrapped with `withPPDev()`, which applies the build's
393
+ `distDir`; without it the build exports into the app's own `distDir`, as a plain `next build` would,
394
+ and the dev server has to be restarted after the sync.
395
+
396
+ **Config changes.** Both commands watch `pp-dev.config.*`, `next.config.*` / `vite.config.*`, `package.json` and the `.env*` files of the project root and restart the dev server when one changes, appears or is removed. A `pp-dev.config.*` that can't be loaded (half-written, a syntax error) is reported and the running server is kept; the next save tries again. `pp-dev next` runs its server in a process of its own and starts that process again on a change, as `next dev` does: Next.js caches its config for the life of a process, so a restart in place could not pick up a changed `withPPDev()` config or `next.config.*`.
345
397
 
346
398
  ### Build
347
399
 
@@ -349,18 +401,18 @@ pp-dev next [options]
349
401
  pp-dev build [options]
350
402
  ```
351
403
 
352
- | Option | Default | Description |
353
- | ------------------------------- | --------- | ------------------------------------------------------ |
354
- | `[root]` | `.` | Root directory of the application |
355
- | `--target <target>` | `modules` | Transpile target |
356
- | `--outDir <dir>` | `dist` | Output directory |
357
- | `--assetsDir <dir>` | `assets` | Assets directory under outDir |
358
- | `--changelog [file]` | `true` | Create changelog file |
359
- | `--distZip` / `--no-distZip` | see below | Override `build.zip` — pack (or skip) the output ZIP |
360
- | `--distZipDir <dir>` | see below | Override the ZIP output directory (`build.zip.outDir`) |
361
- | `--distZipFilename <file>` | see below | Override the ZIP file name (`build.zip.fileName`) |
404
+ | Option | Default | Description |
405
+ | -------------------------------------------- | --------- | -------------------------------------------------------------------- |
406
+ | `[root]` | `.` | Root directory of the application |
407
+ | `--target <target>` | `modules` | Transpile target |
408
+ | `--outDir <dir>` | `dist` | Output directory |
409
+ | `--assetsDir <dir>` | `assets` | Assets directory under outDir |
410
+ | `--changelog [file]` | `true` | Create changelog file |
411
+ | `--distZip` / `--no-distZip` | see below | Override `build.zip` — pack (or skip) the output ZIP |
412
+ | `--distZipDir <dir>` | see below | Override the ZIP output directory (`build.zip.outDir`) |
413
+ | `--distZipFilename <file>` | see below | Override the ZIP file name (`build.zip.fileName`) |
362
414
  | `--versionManifest` / `--no-versionManifest` | see below | Override `build.versionFile` — emit (or skip) VERSION/BUILD-MANIFEST |
363
- | `--versionFileTemplate <tpl>` | see below | Override the VERSION file name template |
415
+ | `--versionFileTemplate <tpl>` | see below | Override the VERSION file name template |
364
416
 
365
417
  The `--distZip*`/`--versionManifest*` flags (and their `PP_DEV_*` env var equivalents, see
366
418
  [Environment Variables](#environment-variables)) let CI or ad-hoc builds override the `build.zip`
@@ -396,15 +448,15 @@ Use it in place of `next build` in your `package.json`:
396
448
  }
397
449
  ```
398
450
 
399
- | Option | Default | Description |
400
- | ------------------------------- | --------- | ------------------------------------------------------ |
401
- | `[root]` | `.` | Root directory of the application |
402
- | `--changelog [file]` | `true` | Create changelog file |
403
- | `--distZip` / `--no-distZip` | see below | Override `build.zip` — pack (or skip) the output ZIP |
404
- | `--distZipDir <dir>` | see below | Override the ZIP output directory (`build.zip.outDir`) |
405
- | `--distZipFilename <file>` | see below | Override the ZIP file name (`build.zip.fileName`) |
451
+ | Option | Default | Description |
452
+ | -------------------------------------------- | --------- | -------------------------------------------------------------------- |
453
+ | `[root]` | `.` | Root directory of the application |
454
+ | `--changelog [file]` | `true` | Create changelog file |
455
+ | `--distZip` / `--no-distZip` | see below | Override `build.zip` — pack (or skip) the output ZIP |
456
+ | `--distZipDir <dir>` | see below | Override the ZIP output directory (`build.zip.outDir`) |
457
+ | `--distZipFilename <file>` | see below | Override the ZIP file name (`build.zip.fileName`) |
406
458
  | `--versionManifest` / `--no-versionManifest` | see below | Override `build.versionFile` — emit (or skip) VERSION/BUILD-MANIFEST |
407
- | `--versionFileTemplate <tpl>` | see below | Override the VERSION file name template |
459
+ | `--versionFileTemplate <tpl>` | see below | Override the VERSION file name template |
408
460
 
409
461
  ### Migration
410
462
 
@@ -412,13 +464,13 @@ Use it in place of `next build` in your `package.json`:
412
464
  pp-dev migrate [config] [options]
413
465
  ```
414
466
 
415
- | Option | Description |
416
- |---|---|
417
- | `[config]` | Config file to migrate (auto-detected if omitted) |
418
- | `--dry-run` | Preview output without writing |
419
- | `--format ts\|js\|json` | Output format |
420
- | `--output <file>` | Write to a specific path |
421
- | `--no-backup` | Skip `.bak` backup |
467
+ | Option | Description |
468
+ | ----------------------- | ------------------------------------------------- |
469
+ | `[config]` | Config file to migrate (auto-detected if omitted) |
470
+ | `--dry-run` | Preview output without writing |
471
+ | `--format ts\|js\|json` | Output format |
472
+ | `--output <file>` | Write to a specific path |
473
+ | `--no-backup` | Skip `.bak` backup |
422
474
 
423
475
  ### Changelog Generation
424
476
 
@@ -517,8 +569,8 @@ Runtime choices are saved in the browser's `localStorage` (`pp-dev-info-position
517
569
  export default defineConfig({
518
570
  devPanel: {
519
571
  position: 'bottom-right', // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
520
- hidden: false, // hide the panel entirely (restore with ?pp-dev-panel=show)
521
- autoHide: false, // slide behind the screen edge, reveal on hover
572
+ hidden: false, // hide the panel entirely (restore with ?pp-dev-panel=show)
573
+ autoHide: false, // slide behind the screen edge, reveal on hover
522
574
  },
523
575
  });
524
576
  ```
@@ -542,7 +594,7 @@ A standalone page at `/@pp-dev/variables-editor`, alongside the [Request Inspect
542
594
 
543
595
  ![Variables Editor — Schema tab](./docs/screenshots/06-editor-schema.png)
544
596
 
545
- - **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.
597
+ - **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.
546
598
 
547
599
  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.
548
600
 
@@ -576,7 +628,7 @@ Every saved user gets its own host: `<name>.localhost:<port>`. The browser sends
576
628
  ### Adding users
577
629
 
578
630
  - **API token**: the token is checked with MI before the user is added. SSO users can only be added this way.
579
- - **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.
631
+ - **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.
580
632
 
581
633
  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.
582
634
 
@@ -588,7 +640,7 @@ Logging out on a user's host ends that user's MI session (or token) as it would
588
640
 
589
641
  ### Keeping users between runs
590
642
 
591
- 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, readable by you only, outside the project so it never ends up in git or a build. 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*.
643
+ 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_.
592
644
 
593
645
  ```typescript
594
646
  // pp-dev.config.ts
@@ -603,13 +655,13 @@ export default defineConfig({
603
655
 
604
656
  The popover uses a small JSON API:
605
657
 
606
- | Method | Path | Description |
607
- |----------|-------------------------|---------------------------------------------------------------------------------------------------|
608
- | `GET` | `/@api/users` | The users (name, kind, state, MI user, `origin`, `loginUrl`), the default user, and whether users are available |
609
- | `POST` | `/@api/users` | Add a user: `{ "name", "token" }`, or `{ "name", "kind": "session" }` to log in with a password |
610
- | `PUT` | `/@api/users/default` | Make a user the default: `{ "name" }`, or `{ "name": null }` for you |
611
- | `PATCH` | `/@api/users/:name` | Edit a user added with an API token: `{ "name" }` to rename it, `{ "token" }` to replace its token |
612
- | `DELETE` | `/@api/users/:name` | Remove a user |
658
+ | Method | Path | Description |
659
+ | -------- | --------------------- | --------------------------------------------------------------------------------------------------------------- |
660
+ | `GET` | `/@api/users` | The users (name, kind, state, MI user, `origin`, `loginUrl`), the default user, and whether users are available |
661
+ | `POST` | `/@api/users` | Add a user: `{ "name", "token" }`, or `{ "name", "kind": "session" }` to log in with a password |
662
+ | `PUT` | `/@api/users/default` | Make a user the default: `{ "name" }`, or `{ "name": null }` for you |
663
+ | `PATCH` | `/@api/users/:name` | Edit a user added with an API token: `{ "name" }` to rename it, `{ "token" }` to replace its token |
664
+ | `DELETE` | `/@api/users/:name` | Remove a user |
613
665
 
614
666
  Tokens and MI sessions are never sent back.
615
667
 
@@ -632,17 +684,18 @@ Open `http://localhost:3000/@pp-dev/inspector` (replace port as needed) in any b
632
684
  Selecting a request opens the detail pane with headers and a syntax-highlighted body:
633
685
 
634
686
  ![Request Inspector — request detail](./docs/screenshots/05-inspector-detail.png)
687
+
635
688
  - A **Clear** button in the top-right removes all stored entries
636
689
 
637
690
  ### Source badges
638
691
 
639
692
  Each request in the list displays a colored letter badge to the left of the HTTP status:
640
693
 
641
- | Badge | Color | Meaning |
642
- |-------|--------|----------------------------------------------|
694
+ | Badge | Color | Meaning |
695
+ | ----- | ------ | -------------------------------------------------------- |
643
696
  | `P` | Purple | Forwarded to the upstream Metric Insights server (proxy) |
644
- | `C` | Amber | Served from the local proxy cache |
645
- | `L` | Grey | Served locally (static file, dev route, etc.) |
697
+ | `C` | Amber | Served from the local proxy cache |
698
+ | `L` | Grey | Served locally (static file, dev route, etc.) |
646
699
 
647
700
  ### Console banner
648
701
 
@@ -658,12 +711,12 @@ The message persists in DevTools history so it is visible even when you open the
658
711
 
659
712
  The inspector also exposes a lightweight JSON API, useful for tooling and AI agents:
660
713
 
661
- | Method | Path | Description |
662
- |----------|-------------------------|---------------------------------------------|
663
- | `GET` | `/@api/requests` | Paginated list of captured requests (metadata only, no bodies) |
664
- | `GET` | `/@api/requests/:id` | Full entry including captured request/response bodies (base64-encoded) |
665
- | `GET` | `/@api/requests/stats` | Store stats: entry count, memory usage, limits |
666
- | `DELETE` | `/@api/requests` | Clear all stored entries |
714
+ | Method | Path | Description |
715
+ | -------- | ---------------------- | ---------------------------------------------------------------------- |
716
+ | `GET` | `/@api/requests` | Paginated list of captured requests (metadata only, no bodies) |
717
+ | `GET` | `/@api/requests/:id` | Full entry including captured request/response bodies (base64-encoded) |
718
+ | `GET` | `/@api/requests/stats` | Store stats: entry count, memory usage, limits |
719
+ | `DELETE` | `/@api/requests` | Clear all stored entries |
667
720
 
668
721
  `GET /@api/requests` accepts `?limit=` (default 50) and `?offset=` query parameters for pagination.
669
722
 
@@ -675,8 +728,8 @@ Bodies in `GET /@api/requests/:id` are returned as base64 strings in `requestBod
675
728
  // pp-dev.config.ts
676
729
  export default defineConfig({
677
730
  inspector: {
678
- enabled: true, // set to false to disable entirely
679
- maxMemory: 100 * 1024 * 1024, // evict oldest entries above 100 MB
731
+ enabled: true, // set to false to disable entirely
732
+ maxMemory: 100 * 1024 * 1024, // evict oldest entries above 100 MB
680
733
  captureLimit: 10 * 1024 * 1024, // capture at most 10 MB per body
681
734
  },
682
735
  });
@@ -713,7 +766,7 @@ If you encounter an error like "Next.js is required but not available":
713
766
 
714
767
  #### Version Compatibility
715
768
 
716
- - **pp-dev** requires Next.js version 15 or higher (but less than 17)
769
+ - **pp-dev** accepts Next.js 13 to 16 (`>= 13 < 17`); the test apps run on Next.js 16
717
770
  - **Node.js** version 24 or higher is required
718
771
  - **TypeScript** version 5 or higher is recommended
719
772
 
@@ -0,0 +1,2 @@
1
+ "use strict";const e=require("fs"),t=require("path"),i=require("url"),r=require("picocolors"),s=require("node:path"),o=require("node:net"),n=require("vite");var a="undefined"!=typeof document?document.currentScript:null;const p=(e=>e&&"object"==typeof e&&"default"in e?e.default:e)(s),d=t.resolve("undefined"!=typeof __filename&&__filename||i.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:a&&"SCRIPT"===a.tagName.toUpperCase()&&a.src||new URL("auth.provider-BT1sgf1x.js",document.baseURI).href),"../../.."),l=t.resolve("undefined"!=typeof __filename&&__filename||i.fileURLToPath("undefined"==typeof document?require("url").pathToFileURL(__filename).href:a&&"SCRIPT"===a.tagName.toUpperCase()&&a.src||new URL("auth.provider-BT1sgf1x.js",document.baseURI).href),"../.."),c=e.existsSync(t.resolve(d,"package.json"))?d:l,u=t.resolve(c,"dist/client/client.js"),{version:h,name:f}=JSON.parse(e.readFileSync(t.resolve(c,"package.json")).toString()),m=h,v=f,g="info";let w,_;function E(){return w??={level:g,logger:n.createLogger(g)},w.logger}function P(e){return void 0!==e&&e!==w?.level&&(w={level:e,logger:n.createLogger(e)}),_??={info:(e,t)=>E().info(e,t),warn:(e,t)=>E().warn(e,t),warnOnce:(e,t)=>E().warnOnce(e,t),error:(e,t)=>E().error(e,t),clearScreen:e=>E().clearScreen(e),hasErrorLogged:e=>E().hasErrorLogged(e),get hasWarned(){return E().hasWarned},set hasWarned(e){E().hasWarned=e}},_}const y=r.createColors();function b(e,t){if(!e||e.includes("\0")||p.posix.isAbsolute(e)||p.win32.isAbsolute(e)||p.win32.parse(e).root)throw new Error(`[pp-dev] ${t} must be a relative path inside its output directory.`);const i=p.posix.normalize(e.replace(/\\/g,"/"));if("."===i||".."===i||i.startsWith("../"))throw new Error(`[pp-dev] ${t} must stay inside its output directory.`);return i}function x(e){return b(`${e.replace(/^@/,"").replace(/[\\/]+/g,"-")}.zip`,"default ZIP output file name")}const A=["top-left","top-right","bottom-left","bottom-right"],D=2147483647;function T(e,t){const i=e.mi?.mode??"standalone",r=e.app?.type??"template",s=e.mi?.apiVersion??7,o=e.mi?.url??process.env.MI_BACKEND_URL;if(!(e.app?.name??t))throw new Error("[pp-dev] app.name is required (or set package.json#name)");const n=e.sync?.maxBackups;if(void 0!==n&&!1!==n&&!(Number.isInteger(n)&&n>=0))throw new Error(`[pp-dev] sync.maxBackups must be a whole number ≥ 0 or false (0 and false keep every backup), got ${JSON.stringify(n)}`);const a=e.sync?.buildTimeoutMs;if(void 0!==a&&!(Number.isInteger(a)&&a>0&&a<=D))throw new Error(`[pp-dev] sync.buildTimeoutMs must be a whole number of milliseconds between 1 and 2147483647, got ${JSON.stringify(a)}`);if(e.mi?.include&&"standalone"!==i)throw console.warn('[pp-dev] mi.include is only valid when mi.mode is "standalone"'),new Error('[pp-dev] mi.include requires mi.mode to be "standalone"');if(!o){if("embedding"===i||"template"===r)throw new Error('[pp-dev] mi.url is required when mi.mode is "embedding" or app.type is "template"');"standalone"===i&&"page"===r&&console.warn("[pp-dev] mi.url is not set — dev server will run without a backend proxy")}if("template"===r&&!e.app?.id)throw new Error('[pp-dev] app.id is required when app.type is "template"');if("page"===r&&o&&("standalone"===i||s>=7)&&!e.app?.id)throw new Error('[pp-dev] app.id is required when backend page data is loaded for app.type "page"');if(void 0!==e.devPanel?.position&&!A.includes(e.devPanel.position))throw new Error(`[pp-dev] devPanel.position must be one of: ${A.join(", ")}`);const p=e.server?.allowedHosts;if(!(void 0===p||!0===p||Array.isArray(p)&&p.every(e=>"string"==typeof e&&""!==e.trim())))throw new Error(`[pp-dev] server.allowedHosts must be a list of host names or true, got ${JSON.stringify(p)}`)}function L(e,t){const{mi:i={},app:r={},proxy:s={},build:o={},sync:n={},inspector:a={},devPanel:p={},users:d={},server:l={}}=e,c=i.mode??"standalone",u=r.type??"template",h=i.apiVersion??7,f="standalone"===c;let m=!1;"top-bar"===i.include?m=!0:"shared-components"===i.include&&(m={addSharedComponentsScripts:!0,addRootElement:!1});const v="page"===u,g=r.name??t;if(!g)throw new Error("[pp-dev] app.name is required (or set package.json#name)");const w="VERSION-v{packageversion}-{currentDate}.json";let _;const E=o.zip;let P;_=!1!==E&&(!0===E||void 0===E?{outFileName:x(g),outDir:"dist-zip"}:{outFileName:b(E.fileName??x(g),"build.zip.fileName"),outDir:E.outDir??"dist-zip",...E.inDir?{inDir:E.inDir}:{}});const y=o.versionFile;let A;P=!1!==y&&(!0===y||void 0===y?{versionFileTemplate:w,enabled:!0}:{versionFileTemplate:b(y.fileNameTemplate??w,"build.versionFile.fileNameTemplate"),enabled:y.enabled??!0});const D=o.imageOptimisations;return A=!1!==D&&(!0===D||void 0===D?{}:D),{templateName:g,backendBaseURL:i.url??process.env.MI_BACKEND_URL,appId:r.id,templateLess:v,miHudLess:f,integrateMiTopBar:m,enableProxyCache:s.cache??!0,proxyCacheTTL:s.cacheTtl??6e5,disableSSLValidation:s.tls?.allowSelfSigned??!1,imageOptimizer:A,outDir:o.outDir??"dist",distZip:_,versionPlugin:P,syncBackupsDir:n.backupsDir??"backups",syncMaxBackups:n.maxBackups,syncBuildTimeoutMs:n.buildTimeoutMs,v7Features:h>=7,personalAccessToken:i.token??process.env.MI_ACCESS_TOKEN,inspectorEnabled:a.enabled??!0,inspectorMaxMemory:a.maxMemory??1073741824,inspectorCaptureLimit:a.captureLimit??10485760,devPanelPosition:p.position??"bottom-right",devPanelHidden:p.hidden??!1,devPanelAutoHide:p.autoHide??!1,persistUsers:d.persist??!1,allowedHosts:!0===l.allowedHosts||(l.allowedHosts??[]).map(e=>e.trim().toLowerCase())}}const R=Object.freeze({__proto__:null,normalizePPDevConfig:L,validatePPDevConfig:T}),N=new Set(["GET","HEAD","OPTIONS"]);function S(e){return!0===e?[]:e.filter(e=>!e.startsWith("."))}function C(e,t=[]){const i=e.headers.origin,r=e.headers.host;if("string"==typeof i){if("null"===i)return'Origin "null" (a sandboxed or file:// page)';let e;try{e=new URL(i)}catch{return`unreadable Origin "${i}"`}if("localhost"===(s=e.hostname)||s.endsWith(".localhost")||"[::1]"===s||/^127(?:\.\d{1,3}){3}$/.test(s)||S(t).includes(e.hostname))return null;const o=r?function(e,t){try{return new URL(`${e}//${t}`).host}catch{return}}(e.protocol,r):void 0;return o&&e.host===o?null:`Origin ${e.origin} is neither this dev server (${r??"no Host"}) nor this machine`}var s;const o=e.headers["sec-fetch-site"];return N.has((e.method??"GET").toUpperCase())||"cross-site"!==o?null:"sent from a cross-site page"}class I{state={isAuthenticated:!1,isRedirected:!1,lastChecked:0};listeners=new Set;getState(){return{...this.state}}isAuthenticated(){return this.state.isAuthenticated}isRedirected(){return this.state.isRedirected}setAuthenticated(e){this.state.isAuthenticated=e,this.state.lastChecked=Date.now(),this.notifyListeners()}setRedirected(e){this.state.isRedirected=e,this.notifyListeners()}updateState(e){void 0!==e.isAuthenticated&&(this.state.isAuthenticated=e.isAuthenticated),void 0!==e.isRedirected&&(this.state.isRedirected=e.isRedirected),this.state.lastChecked=Date.now(),this.notifyListeners()}reset(){this.state={isAuthenticated:!1,isRedirected:!1,lastChecked:0},this.notifyListeners()}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}notifyListeners(){this.listeners.forEach(e=>{try{e(this.getState())}catch(e){P().error(`Error in auth state listener: ${e instanceof Error?e.stack??e.message:String(e)}`)}})}}const k=new I;exports.AuthProvider=I,exports.PACKAGE_NAME=v,exports.PATH_PAGE_PREFIX="/p",exports.PATH_TEMPLATE_LOCAL_PREFIX="/pl",exports.PATH_TEMPLATE_PREFIX="/pt",exports.PP_DEV_CLIENT_ENTRY=u,exports.PP_DEV_CONFIG_NAMES=[".pp-dev.config.js",".pp-dev.config.cjs",".pp-dev.config.mjs",".pp-dev.config.ts",".pp-dev.config.cts",".pp-dev.config.mts",".pp-dev.config.json","pp-dev.config.js","pp-dev.config.cjs","pp-dev.config.mjs","pp-dev.config.ts","pp-dev.config.cts","pp-dev.config.mts","pp-dev.config.json"],exports.PP_DEV_NEXT_BUILD_DIST_DIR_ENV_VAR="PP_DEV_NEXT_BUILD_DIST_DIR",exports.PP_DEV_NEXT_BUILD_ENV_VAR="PP_DEV_NEXT_BUILD",exports.PP_DEV_PACKAGE_DIR=c,exports.VERSION=m,exports.authProvider=k,exports.colors=y,exports.createDefaultZipFileName=x,exports.createLogger=P,exports.createOriginGuard=function(e=[]){return(t,i,r)=>{const s=C(t,e);s?i.status(403).json({error:`Blocked by pp-dev: ${s}.`}):r()}},exports.crossOriginReason=C,exports.exactAllowedHosts=S,exports.hostNotAllowedMessage=function(e){const t=JSON.stringify((e??"").replace(/:\d*$/,""));return`Blocked by pp-dev: this host (${t}) is not allowed. To allow it, add ${t} to server.allowedHosts in the pp-dev config.`},exports.isHostAllowed=function(e,t){if(void 0===e||!0===t)return!0;const i=function(e){const t=e.trim().toLowerCase();if(t.startsWith("[")){const e=t.indexOf("]");return e>0&&6===o.isIP(t.slice(1,e))?{ip:!0}:void 0}const i=t.replace(/:\d*$/,"");if(i&&!i.includes(":"))return 4===o.isIP(i)?{ip:!0}:{hostname:i}}(e);if(void 0===i)return!1;if("ip"in i)return!0;const{hostname:r}=i;return"localhost"===r||r.endsWith(".localhost")||function(e,t){return t.some(t=>t===e||t.startsWith(".")&&(t.slice(1)===e||e.endsWith(t)))}(r,t)},exports.normalizePPDevConfig=L,exports.normalizeRelativeOutputPath=b,exports.ppDevConfig=R,exports.resolveOutputFilePath=function(e,t,i){const r=b(t,i),s=p.resolve(e),o=p.resolve(s,...r.split("/")),n=p.relative(s,o);if(".."===n||n.startsWith(`..${p.sep}`)||p.isAbsolute(n))throw new Error(`[pp-dev] ${i} must resolve inside its output directory.`);return o},exports.resolveZipSourceDir=function(e,t,i){return p.resolve(e,i||t)},exports.validatePPDevConfig=T;
2
+ //# sourceMappingURL=auth.provider-BT1sgf1x.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.provider-BT1sgf1x.js","sources":["../../../src/constants.ts","../../../src/lib/logger.ts","../../../src/lib/helpers/color.helper.ts","../../../src/lib/output-path.ts","../../../src/lib/pp-dev-config.ts","../../../src/lib/helpers/origin-guard.ts","../../../src/lib/auth.provider.ts"],"sourcesContent":[null,null,null,null,null,null,null],"names":["afterBundlePath","resolve","__filename","fileURLToPath","document","require","pathToFileURL","href","_documentCurrentScript","tagName","toUpperCase","src","URL","baseURI","beforeBundlePath","PP_DEV_PACKAGE_DIR","existsSync","PP_DEV_CLIENT_ENTRY","version","name","JSON","parse","readFileSync","toString","VERSION","PACKAGE_NAME","DEFAULT_LEVEL","current","shared","active","level","logger","createViteLogger","createLogger","undefined","info","msg","options","warn","warnOnce","error","clearScreen","type","hasErrorLogged","hasWarned","value","colors","createColors","normalizeRelativeOutputPath","relativePath","optionName","includes","path","posix","isAbsolute","win32","root","Error","normalized","normalize","replace","startsWith","createDefaultZipFileName","appName","DEV_PANEL_POSITIONS","MAX_TIMER_DELAY_MS","validatePPDevConfig","config","templateName","miMode","mi","mode","appType","app","apiVersion","miUrl","url","process","env","MI_BACKEND_URL","maxBackups","sync","Number","isInteger","stringify","buildTimeoutMs","include","console","id","devPanel","position","join","allowedHosts","server","Array","isArray","every","host","trim","normalizePPDevConfig","proxy","build","inspector","users","miHudLess","integrateMiTopBar","addSharedComponentsScripts","addRootElement","templateLess","resolvedName","defaultVersionFileTemplate","distZip","zipCfg","zip","versionPlugin","outFileName","outDir","fileName","inDir","vfCfg","versionFile","imageOptimizer","versionFileTemplate","enabled","fileNameTemplate","imgCfg","imageOptimisations","backendBaseURL","appId","enableProxyCache","cache","proxyCacheTTL","cacheTtl","disableSSLValidation","tls","allowSelfSigned","syncBackupsDir","backupsDir","syncMaxBackups","syncBuildTimeoutMs","v7Features","personalAccessToken","token","MI_ACCESS_TOKEN","inspectorEnabled","inspectorMaxMemory","maxMemory","inspectorCaptureLimit","captureLimit","devPanelPosition","devPanelHidden","hidden","devPanelAutoHide","autoHide","persistUsers","persist","map","toLowerCase","SAFE_METHODS","Set","exactAllowedHosts","filter","crossOriginReason","req","origin","headers","originUrl","hostname","endsWith","test","requestHost","scheme","normalizeHost","protocol","fetchSite","has","method","AuthProvider","state","isAuthenticated","isRedirected","lastChecked","listeners","getState","this","setAuthenticated","authenticated","Date","now","notifyListeners","setRedirected","redirected","updateState","updates","reset","subscribe","listener","add","delete","forEach","stack","message","String","authProvider","res","next","reason","status","json","named","trimmed","end","indexOf","isIP","slice","ip","readHostHeader","some","allowed","matchesAllowedHost","directory","safeRelativePath","resolvedDirectory","resolvedFile","split","relativeToDirectory","relative","sep","projectRoot"],"mappings":"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"}