@metricinsights/pp-dev 1.4.7 → 1.5.0-beta.10
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/README.md +77 -6
- package/dist/README.md +77 -6
- package/dist/cjs/cli.js +1 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/index-BcARY73n.js +2 -0
- package/dist/cjs/index-BcARY73n.js.map +1 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/migrate-CTAwfgnJ.js +2 -0
- package/dist/cjs/{migrate-G-xh-wpc.js.map → migrate-CTAwfgnJ.js.map} +1 -1
- package/dist/cjs/package.json +8 -8
- package/dist/cjs/plugin-Cx8D7mM_.js +106 -0
- package/dist/cjs/plugin-Cx8D7mM_.js.map +1 -0
- package/dist/cjs/plugin.js +1 -1
- package/dist/cjs/version-plugin-C_tAfa8C.js +2 -0
- package/dist/cjs/version-plugin-C_tAfa8C.js.map +1 -0
- package/dist/client/client.css +1 -1
- package/dist/client/client.css.map +1 -1
- package/dist/client/client.js +555 -74
- package/dist/client/client.js.map +1 -1
- package/dist/client/index.html +24 -2
- package/dist/esm/cli.js +1 -1
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/index-DYif-i3c.js +2 -0
- package/dist/esm/index-DYif-i3c.js.map +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/migrate-3G0bzseG.js +2 -0
- package/dist/esm/{migrate-BBCvcE_8.js.map → migrate-3G0bzseG.js.map} +1 -1
- package/dist/esm/package.json +8 -8
- package/dist/esm/plugin-GOAsE6Xr.js +106 -0
- package/dist/esm/plugin-GOAsE6Xr.js.map +1 -0
- package/dist/esm/plugin.js +1 -1
- package/dist/esm/version-plugin-RuvytTeG.js +2 -0
- package/dist/esm/{version-plugin-BqEwLs0b.js.map → version-plugin-RuvytTeG.js.map} +1 -1
- package/dist/types/index.d.ts +18 -0
- package/docs/features.md +25 -2
- package/docs/screenshots/13-users-popover.png +0 -0
- package/docs/screenshots/14-users-user-tab.png +0 -0
- package/package.json +17 -17
- package/dist/cjs/index-DlBoHBGI.js +0 -2
- package/dist/cjs/index-DlBoHBGI.js.map +0 -1
- package/dist/cjs/migrate-G-xh-wpc.js +0 -2
- package/dist/cjs/plugin-Bfd0zHTR.js +0 -2
- package/dist/cjs/plugin-Bfd0zHTR.js.map +0 -1
- package/dist/cjs/version-plugin-DmJ0luHT.js +0 -2
- package/dist/cjs/version-plugin-DmJ0luHT.js.map +0 -1
- package/dist/esm/index-Dv-Y3cH6.js +0 -2
- package/dist/esm/index-Dv-Y3cH6.js.map +0 -1
- package/dist/esm/migrate-BBCvcE_8.js +0 -2
- package/dist/esm/plugin-B0dsWaBT.js +0 -2
- package/dist/esm/plugin-B0dsWaBT.js.map +0 -1
- package/dist/esm/version-plugin-BqEwLs0b.js +0 -2
package/README.md
CHANGED
|
@@ -187,9 +187,10 @@ module.exports = defineConfig({
|
|
|
187
187
|
|
|
188
188
|
### `sync` — Template sync
|
|
189
189
|
|
|
190
|
-
| Field | Type
|
|
191
|
-
|
|
192
|
-
| `backupsDir` | `string`
|
|
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. |
|
|
193
194
|
|
|
194
195
|
### `devPanel` — Dev panel appearance
|
|
195
196
|
|
|
@@ -209,6 +210,14 @@ hidden panel or taking clean screenshots. Note that `localStorage` is origin-sco
|
|
|
209
210
|
apply to every pp-dev app served on the same host and port. See the [Dev Panel](#dev-panel)
|
|
210
211
|
section for the full feature description.
|
|
211
212
|
|
|
213
|
+
### `users` — Working as other users
|
|
214
|
+
|
|
215
|
+
| Field | Type | Default | Description |
|
|
216
|
+
|-----------|-----------|---------|--------------------------------------------------------------------------------------------------------------|
|
|
217
|
+
| `persist` | `boolean` | `false` | Keep the users added with an API token between dev server runs, in `~/.pp-dev/users/` (readable by you only) |
|
|
218
|
+
|
|
219
|
+
See [Working as other users](#working-as-other-users).
|
|
220
|
+
|
|
212
221
|
### Validation
|
|
213
222
|
|
|
214
223
|
pp-dev validates your config at startup and reports problems clearly:
|
|
@@ -472,7 +481,7 @@ For custom build configuration, create a `vite.config` file. See [Vite Configura
|
|
|
472
481
|
|
|
473
482
|
## Dev Panel
|
|
474
483
|
|
|
475
|
-
pp-dev injects a floating dev panel into every served page. It shows the
|
|
484
|
+
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.
|
|
476
485
|
|
|
477
486
|

|
|
478
487
|
|
|
@@ -534,7 +543,9 @@ A standalone page at `/@pp-dev/variables-editor`, alongside the [Request Inspect
|
|
|
534
543
|
|
|
535
544
|

|
|
536
545
|
|
|
537
|
-
- **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.
|
|
546
|
+
- **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.
|
|
547
|
+
|
|
548
|
+
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.
|
|
538
549
|
|
|
539
550
|

|
|
540
551
|
|
|
@@ -544,6 +555,65 @@ See the [feature tour](./docs/features.md#variables-editor) for more screenshots
|
|
|
544
555
|
|
|
545
556
|
See [`TEMPLATE_VARIABLES.md`](./TEMPLATE_VARIABLES.md) — also shipped inside the published package — for the `__template_variables.json` schema this feature reads.
|
|
546
557
|
|
|
558
|
+
## Working as other users
|
|
559
|
+
|
|
560
|
+
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.
|
|
561
|
+
|
|
562
|
+

|
|
563
|
+
|
|
564
|
+
### How it works
|
|
565
|
+
|
|
566
|
+
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.
|
|
567
|
+
|
|
568
|
+
- **`localhost:<port>`** works as the **default user**: you, unless you check another user in the popover.
|
|
569
|
+
- **`<name>.localhost:<port>`** works as that user. Its dev panel's Users button is purple, so the tab is never taken for your own.
|
|
570
|
+
- **The dev panel itself** (sync, page variables, Variables Editor, Request Inspector) always works as you, on every host.
|
|
571
|
+
|
|
572
|
+
### Requirements
|
|
573
|
+
|
|
574
|
+
- **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.
|
|
575
|
+
- **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.
|
|
576
|
+
|
|
577
|
+
### Adding users
|
|
578
|
+
|
|
579
|
+
- **API token**: the token is checked with MI before the user is added. SSO users can only be added this way.
|
|
580
|
+
- **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.
|
|
581
|
+
|
|
582
|
+
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.
|
|
583
|
+
|
|
584
|
+
**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.
|
|
585
|
+
|
|
586
|
+
### Logging out and removing
|
|
587
|
+
|
|
588
|
+
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.
|
|
589
|
+
|
|
590
|
+
### Keeping users between runs
|
|
591
|
+
|
|
592
|
+
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*.
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
// pp-dev.config.ts
|
|
596
|
+
export default defineConfig({
|
|
597
|
+
users: {
|
|
598
|
+
persist: true,
|
|
599
|
+
},
|
|
600
|
+
});
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### REST API
|
|
604
|
+
|
|
605
|
+
The popover uses a small JSON API:
|
|
606
|
+
|
|
607
|
+
| Method | Path | Description |
|
|
608
|
+
|----------|-------------------------|---------------------------------------------------------------------------------------------------|
|
|
609
|
+
| `GET` | `/@api/users` | The users (name, kind, state, MI user, `origin`, `loginUrl`), the default user, and whether users are available |
|
|
610
|
+
| `POST` | `/@api/users` | Add a user: `{ "name", "token" }`, or `{ "name", "kind": "session" }` to log in with a password |
|
|
611
|
+
| `PUT` | `/@api/users/default` | Make a user the default: `{ "name" }`, or `{ "name": null }` for you |
|
|
612
|
+
| `PATCH` | `/@api/users/:name` | Edit a user added with an API token: `{ "name" }` to rename it, `{ "token" }` to replace its token |
|
|
613
|
+
| `DELETE` | `/@api/users/:name` | Remove a user |
|
|
614
|
+
|
|
615
|
+
Tokens and MI sessions are never sent back.
|
|
616
|
+
|
|
547
617
|
## Request Inspector
|
|
548
618
|
|
|
549
619
|
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.
|
|
@@ -553,7 +623,8 @@ pp-dev includes a built-in request inspector that captures every proxied and loc
|
|
|
553
623
|
Open `http://localhost:3000/@pp-dev/inspector` (replace port as needed) in any browser tab while the dev server is running. The UI shows:
|
|
554
624
|
|
|
555
625
|
- A scrollable list of captured requests with method, status, source badge, and timing
|
|
556
|
-
-
|
|
626
|
+
- A tag with the user whose tab made the request, and a user filter, once you [work as other users](#working-as-other-users)
|
|
627
|
+
- 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>`
|
|
557
628
|
- Request and response bodies rendered as text for JSON/HTML/CSS/plain-text content types, with **Copy** and **Save** buttons
|
|
558
629
|
- Binary bodies (images, fonts, archives) show metadata only and offer a **Save** button
|
|
559
630
|
|
package/dist/README.md
CHANGED
|
@@ -187,9 +187,10 @@ module.exports = defineConfig({
|
|
|
187
187
|
|
|
188
188
|
### `sync` — Template sync
|
|
189
189
|
|
|
190
|
-
| Field | Type
|
|
191
|
-
|
|
192
|
-
| `backupsDir` | `string`
|
|
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. |
|
|
193
194
|
|
|
194
195
|
### `devPanel` — Dev panel appearance
|
|
195
196
|
|
|
@@ -209,6 +210,14 @@ hidden panel or taking clean screenshots. Note that `localStorage` is origin-sco
|
|
|
209
210
|
apply to every pp-dev app served on the same host and port. See the [Dev Panel](#dev-panel)
|
|
210
211
|
section for the full feature description.
|
|
211
212
|
|
|
213
|
+
### `users` — Working as other users
|
|
214
|
+
|
|
215
|
+
| Field | Type | Default | Description |
|
|
216
|
+
|-----------|-----------|---------|--------------------------------------------------------------------------------------------------------------|
|
|
217
|
+
| `persist` | `boolean` | `false` | Keep the users added with an API token between dev server runs, in `~/.pp-dev/users/` (readable by you only) |
|
|
218
|
+
|
|
219
|
+
See [Working as other users](#working-as-other-users).
|
|
220
|
+
|
|
212
221
|
### Validation
|
|
213
222
|
|
|
214
223
|
pp-dev validates your config at startup and reports problems clearly:
|
|
@@ -472,7 +481,7 @@ For custom build configuration, create a `vite.config` file. See [Vite Configura
|
|
|
472
481
|
|
|
473
482
|
## Dev Panel
|
|
474
483
|
|
|
475
|
-
pp-dev injects a floating dev panel into every served page. It shows the
|
|
484
|
+
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.
|
|
476
485
|
|
|
477
486
|

|
|
478
487
|
|
|
@@ -534,7 +543,9 @@ A standalone page at `/@pp-dev/variables-editor`, alongside the [Request Inspect
|
|
|
534
543
|
|
|
535
544
|

|
|
536
545
|
|
|
537
|
-
- **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.
|
|
546
|
+
- **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.
|
|
547
|
+
|
|
548
|
+
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.
|
|
538
549
|
|
|
539
550
|

|
|
540
551
|
|
|
@@ -544,6 +555,65 @@ See the [feature tour](./docs/features.md#variables-editor) for more screenshots
|
|
|
544
555
|
|
|
545
556
|
See [`TEMPLATE_VARIABLES.md`](./TEMPLATE_VARIABLES.md) — also shipped inside the published package — for the `__template_variables.json` schema this feature reads.
|
|
546
557
|
|
|
558
|
+
## Working as other users
|
|
559
|
+
|
|
560
|
+
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.
|
|
561
|
+
|
|
562
|
+

|
|
563
|
+
|
|
564
|
+
### How it works
|
|
565
|
+
|
|
566
|
+
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.
|
|
567
|
+
|
|
568
|
+
- **`localhost:<port>`** works as the **default user**: you, unless you check another user in the popover.
|
|
569
|
+
- **`<name>.localhost:<port>`** works as that user. Its dev panel's Users button is purple, so the tab is never taken for your own.
|
|
570
|
+
- **The dev panel itself** (sync, page variables, Variables Editor, Request Inspector) always works as you, on every host.
|
|
571
|
+
|
|
572
|
+
### Requirements
|
|
573
|
+
|
|
574
|
+
- **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.
|
|
575
|
+
- **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.
|
|
576
|
+
|
|
577
|
+
### Adding users
|
|
578
|
+
|
|
579
|
+
- **API token**: the token is checked with MI before the user is added. SSO users can only be added this way.
|
|
580
|
+
- **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.
|
|
581
|
+
|
|
582
|
+
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.
|
|
583
|
+
|
|
584
|
+
**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.
|
|
585
|
+
|
|
586
|
+
### Logging out and removing
|
|
587
|
+
|
|
588
|
+
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.
|
|
589
|
+
|
|
590
|
+
### Keeping users between runs
|
|
591
|
+
|
|
592
|
+
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*.
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
// pp-dev.config.ts
|
|
596
|
+
export default defineConfig({
|
|
597
|
+
users: {
|
|
598
|
+
persist: true,
|
|
599
|
+
},
|
|
600
|
+
});
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### REST API
|
|
604
|
+
|
|
605
|
+
The popover uses a small JSON API:
|
|
606
|
+
|
|
607
|
+
| Method | Path | Description |
|
|
608
|
+
|----------|-------------------------|---------------------------------------------------------------------------------------------------|
|
|
609
|
+
| `GET` | `/@api/users` | The users (name, kind, state, MI user, `origin`, `loginUrl`), the default user, and whether users are available |
|
|
610
|
+
| `POST` | `/@api/users` | Add a user: `{ "name", "token" }`, or `{ "name", "kind": "session" }` to log in with a password |
|
|
611
|
+
| `PUT` | `/@api/users/default` | Make a user the default: `{ "name" }`, or `{ "name": null }` for you |
|
|
612
|
+
| `PATCH` | `/@api/users/:name` | Edit a user added with an API token: `{ "name" }` to rename it, `{ "token" }` to replace its token |
|
|
613
|
+
| `DELETE` | `/@api/users/:name` | Remove a user |
|
|
614
|
+
|
|
615
|
+
Tokens and MI sessions are never sent back.
|
|
616
|
+
|
|
547
617
|
## Request Inspector
|
|
548
618
|
|
|
549
619
|
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.
|
|
@@ -553,7 +623,8 @@ pp-dev includes a built-in request inspector that captures every proxied and loc
|
|
|
553
623
|
Open `http://localhost:3000/@pp-dev/inspector` (replace port as needed) in any browser tab while the dev server is running. The UI shows:
|
|
554
624
|
|
|
555
625
|
- A scrollable list of captured requests with method, status, source badge, and timing
|
|
556
|
-
-
|
|
626
|
+
- A tag with the user whose tab made the request, and a user filter, once you [work as other users](#working-as-other-users)
|
|
627
|
+
- 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>`
|
|
557
628
|
- Request and response bodies rendered as text for JSON/HTML/CSS/plain-text content types, with **Copy** and **Save** buttons
|
|
558
629
|
- Binary bodies (images, fonts, archives) show metadata only and offer a **Save** button
|
|
559
630
|
|
package/dist/cjs/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const e=require("path"),t=require("fs"),o=require("node:events"),n=require("node:perf_hooks"),i=require("chokidar"),r=require("cac"),s=require("./plugin-Bfd0zHTR.js"),a=require("./index-DlBoHBGI.js"),l=require("vite"),c=require("url"),d=require("dir-compare"),p=require("diff-match-patch"),f=require("isbinaryfile"),u=require("os"),g=require("crypto"),h=require("svgtofont"),m=require("ws");require("http-proxy-middleware"),require("picocolors"),require("node:string_decoder"),require("axios"),require("node:http"),require("node:https"),require("jsdom"),require("process"),require("child_process"),require("node:path"),require("jszip"),require("module"),require("zlib"),require("express"),require("node:crypto"),require("./helpers.js"),require("ejs");const v=e=>e&&"object"==typeof e&&"default"in e?e.default:e;function b(e){if(e&&"object"==typeof e&&"default"in e)return e;const t=Object.create(null);if(e)for(const o in e)t[o]=e[o];return t.default=e,Object.freeze(t)}const w=b(e),y=b(t),P=b(d),x=v(p),S=b(u),E=b(g),T=v(h);function L(e){return null!=e&&!1!==e}let k=null;const D=[{key:"r",description:"restart the server",async action(e){await e.restart()}},{key:"u",description:"show server url",action(e){e.config.logger.info(""),e.printUrls()}},{key:"o",description:"open in browser",action(e){e.openBrowser()}},{key:"c",description:"clear console",action(e){e.config.logger.clearScreen("error")}},{key:"q",description:"quit",async action(e){await e.close().finally(()=>process.exit())}},{key:"C",description:"clear proxy cache",action(e){e.cache&&(e.cache.clear(),e.config.logger.info("Proxy cache cleared"))}}];const F=/(.+)(-[a-f0-9]{6,20})(\.[a-z0-9]+)$/i;class I{oldAssetsPath;newAssetsPath;destinationPath;changelogFilename;changelogTemplate='<!DOCTYPE html>\n <html lang="en">\n <head>\n <meta charset="UTF-8" />\n <title>Changelog Diff</title>\n <style>\n tr,\n td {\n padding: 0;\n }\n .diff-file {\n margin-top: 20px;\n border: 1px solid #e1e4e8;\n border-radius: 6px;\n }\n .diff-file-title {\n padding: 10px 20px;\n background-color: #f6f8fa;\n border-bottom: 1px solid #e1e4e8;\n border-radius: 6px 6px 0 0;\n font-weight: bold;\n }\n .diff-file-title .renamed {\n font-weight: normal;\n }\n .diff-file-title .renamed .from {\n color: #cb2431;\n }\n .diff-file-title .renamed .to {\n color: #22863a;\n }\n .diff-file-title .added {\n color: #22863a;\n }\n .diff-file-title .deleted {\n color: #cb2431;\n }\n .diff-file-content {\n }\n .diff-table {\n tab-size: 8;\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n }\n .blob-num {\n position: relative;\n color: #1f2328;\n width: 1%;\n min-width: 50px;\n padding: 0 10px;\n font-family:\n ui-monospace,\n SFMono-Regular,\n SF Mono,\n Menlo,\n Consolas,\n Liberation Mono,\n monospace;\n font-size: 12px;\n line-height: 20px;\n text-align: right;\n white-space: nowrap;\n vertical-align: top;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n }\n .blob-num.addition {\n background-color: #ccffd8;\n border-color: #1f883e;\n }\n .blob-num.deletion {\n background-color: #ffd7d5;\n border-color: #cf222e;\n }\n .blob-num::before {\n content: attr(data-line-number);\n }\n .blob-code {\n position: relative;\n padding: 0 10px 0 22px;\n vertical-align: top;\n color: #1f2329;\n }\n .blob-code.code-addition {\n background-color: #e6ffec;\n }\n .blob-code.code-deletion {\n background-color: #ffebe9;\n }\n .blob-code.skip,\n .blob-code.message {\n text-align: center;\n }\n .blob-code.skip .blob-code-inner,\n .blob-code.message .blob-code-inner {\n font-weight: bold;\n color: #6a737d;\n padding: 10px 0;\n }\n .blob-code-inner {\n display: table-cell;\n overflow: visible;\n font-family:\n ui-monospace,\n SFMono-Regular,\n SF Mono,\n Menlo,\n Consolas,\n Liberation Mono,\n monospace;\n font-size: 12px;\n word-wrap: anywhere;\n white-space: pre-wrap;\n }\n .blob-code-inner::before {\n content: attr(data-code-prefix);\n position: absolute;\n top: 1px;\n left: 8px;\n padding-right: 8px;\n }\n </style>\n </head>\n <body>\n <h1>Changelog Diff</h1>\n\n %FILES%\n </body>\n </html>';diffFileTemplateHandler;diffLineTemplateHandler;contextLines=3;logger;constructor(e){const{oldAssetsPath:t,newAssetsPath:o,destinationPath:n,changelogTemplate:i,diffFileTemplateHandler:r,diffLineTemplateHandler:a,changelogFilename:l,contextLines:c}=e;if(this.logger=s.createLogger(),!t||!o||!n)throw new Error("Previous assets path, current assets path and destination path are required");if(t===o)throw new Error("Previous and current assets paths must be different");if(!this.isExists(t))throw new Error(`Previous assets path ${t} does not exist`);if(!this.isExists(o))throw new Error(`Current assets path ${o} does not exist`);if(this.isZipFile(t)){const e=w.resolve(S.tmpdir(),E.createHash("md5").update(t).digest("hex"));this.oldAssetsPath=this.unzipFile(t,e).then(()=>this.normalizeAssetFolderPath(e)).then(e=>{if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);return e})}else{if(!this.isFolder(t))throw new Error(`Invalid previous assets path ${t}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(t);if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);this.oldAssetsPath=Promise.resolve(e)}}if(this.isZipFile(o)){const e=w.resolve(S.tmpdir(),E.createHash("md5").update(o).digest("hex"));this.newAssetsPath=this.unzipFile(o,e).then(()=>this.normalizeAssetFolderPath(e)).then(e=>{if(this.isEmptyFolder(e))throw new Error(`Current assets path ${e} is empty`);return e})}else{if(!this.isFolder(o))throw new Error(`Invalid current assets path ${o}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(o);if(this.isEmptyFolder(e))throw new Error(`Current assets path ${o} is empty`);this.newAssetsPath=Promise.resolve(e)}}this.destinationPath=n,this.mkdirpSync(this.destinationPath),this.changelogFilename=l||"CHANGELOG.html",i&&(this.templateIsValid(i)?this.changelogTemplate=i:this.logger.warn(s.colors.yellow("Invalid changelog template, using default"))),"function"==typeof r&&(this.diffFileTemplateHandler=r),"function"==typeof a&&(this.diffLineTemplateHandler=a),c&&(this.contextLines=c)}templateIsValid(e){return e.includes("%FILES%")}isExists(e){return y.existsSync(e)}isZipFile(e){return e.endsWith(".zip")}isFolder(e){return y.lstatSync(e).isDirectory()}isEmptyFolder(e){return 0===y.readdirSync(e,{withFileTypes:!0}).length}mkdirpSync(e){y.existsSync(e)||y.mkdirSync(e,{recursive:!0})}async unzipFile(e,t){y.rmSync(t,{force:!0,recursive:!0}),await s.extractZipSafe(e,t)}normalizeAssetFolderPath(e){const t=y.readdirSync(e);return 1===t.length&&y.lstatSync(w.join(e,t[0])).isDirectory()?this.normalizeAssetFolderPath(w.join(e,t[0])):e}pathToPosix(e){return e.replace(/\\/g,"/")}diffTableTemplate(e){return`<table class="diff-table">\n <tbody>\n ${e}\n </tbody>\n </table>`}getDiffTableHTML(e){const t=e.filter((e,t,o)=>0!==e.lineType||(t>=0&&t<this.contextLines||t>o.length-(this.contextLines+1)&&t<=o.length-1||o.slice(t-this.contextLines,t+this.contextLines+1).some(e=>0!==e.lineType))).map((e,t,o)=>{if(t>0){const n=o[t-1];if(e.lineNumber-n.lineNumber>1)return[{lineNumber:-1,lineContent:"",lineType:0},e]}return[e]}).flat().map(e=>this.diffLineHTML(e)).join("");return this.diffTableTemplate(t)}diffLineMessageTemplate(e){return`<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code message">\n <span class="blob-code-inner">${e}</span>\n </td>\n </tr>`}diffLineSkipTemplate(){return'<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code skip">\n <span class="blob-code-inner">Skip</span>\n </td>\n </tr>'}diffLineTemplate(e){const{lineNumber:t,lineContent:o,lineType:n}=e,i=1===n?"addition":-1===n?"deletion":"";return`<tr>\n <td\n class="blob-num ${i}${"addition"===i?" empty":""}"\n ${"addition"!==i?` data-line-number="${t}"`:""}\n ></td>\n <td\n class="blob-num ${i}${"deletion"===i?" empty":""}"\n ${"deletion"!==i?` data-line-number="${t}"`:""}\n ></td>\n <td class="blob-code ${1===n?"code-addition":-1===n?"code-deletion":""}">\n <span class="blob-code-inner" data-code-prefix="${1===n?"+":-1===n?"-":" "}">${r=o??"",r.replace(/[\u00A0-\u9999<>&]/g,e=>"&#"+e.charCodeAt(0)+";")}</span>\n </td>\n </tr>`;var r}diffLineHTML(e){if(this.diffLineTemplateHandler)return this.diffLineTemplateHandler(e);const{lineNumber:t}=e;return-1===t?this.diffLineSkipTemplate():this.diffLineTemplate(e)}diffFileTemplate(e,t){return this.diffFileTemplateHandler?this.diffFileTemplateHandler(e,t):`<div class="diff-file">\n <div class="diff-file-title">${e}</div>\n <div class="diff-file-content">${t}</div>\n </div>`}async generateAssetFoldersDiff(){this.logger.info(s.colors.blue(`Comparing asset folders ${await this.oldAssetsPath} and ${await this.newAssetsPath}`));const e=await P.compare(await this.oldAssetsPath,await this.newAssetsPath,{compareContent:!0,skipSymlinks:!0,compareSize:!0,compareDate:!1,compareNameHandler:(e,t)=>(F.test(e)&&(e=e.replace(F,"$1$3")),F.test(t)&&(t=t.replace(F,"$1$3")),0===e.localeCompare(t)?0:e.localeCompare(t)>0?1:-1)});return e.diffSet?.filter(e=>"equal"!==e.state||e.name1!==e.name2)||[]}async generateAssetFilesDiff(e,t){const o=new x,n=o.diff_linesToChars_(e,t),i=o.diff_main(n.chars1,n.chars2,!1);o.diff_charsToLines_(i,n.lineArray);let r=0;return i.map(e=>{const[t,o]=e,n=o.endsWith("\n")?o.split("\n").length-1:o.split("\n").length,i=o.split("\n").map((e,o)=>({lineContent:e,lineNumber:r+o+1,lineType:t})).slice(0,n);return-1!==t&&(r+=n),i}).flat()}async generateFilesDiff(e){if("equal"===e.state){const t=this.pathToPosix(w.join(".",e.relativePath,e.name1??"")),o=this.pathToPosix(w.join(".",e.relativePath,e.name2??""));return this.diffFileTemplate(`<span class="renamed"\n >Renamed <span class="from">${t}</span> -> <span class="to">${o}</span></span\n >`,this.diffTableTemplate(this.diffLineMessageTemplate("No changes")))}const t=e.path1&&e.name1?w.join(e.path1,e.name1):null,o=e.path2&&e.name2?w.join(e.path2,e.name2):null,n=this.pathToPosix(w.join(".",e.relativePath,(e.name1||e.name2)??""));if("left"===e.state&&t)return this.diffFileTemplate(`<span class="removed">Removed ${n}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File removed")));if("right"===e.state&&o)return this.diffFileTemplate(`<span class="added">Added ${n}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File added")));if("distinct"===e.state&&t&&o){const i=this.pathToPosix(w.join(".",e.relativePath,e.name1??"")),r=this.pathToPosix(w.join(".",e.relativePath,e.name2??"")),s=e.name1!==e.name2?`<span class="renamed"\n >Renamed <span class="from">${i}</span> -> <span class="to">${r}</span></span\n >`:n;return this.diffFileTemplate(s,await f.isBinaryFile(t)||await f.isBinaryFile(o)?this.diffTableTemplate(this.diffLineMessageTemplate("Binary file")):this.getDiffTableHTML(await this.generateAssetFilesDiff(y.readFileSync(t,"utf-8"),y.readFileSync(o,"utf-8"))))}return""}async generateChangelog(){this.logger.info(s.colors.green("Generating changelog"));const e=await this.generateAssetFoldersDiff(),t=(await Promise.all(e.map(e=>this.generateFilesDiff(e)))).join("");this.logger.info(s.colors.green("Writing changelog file"));const o=this.changelogTemplate.split("%FILES%");o.splice(1,0,t);const n=o.join("");y.writeFileSync(w.join(this.destinationPath,this.changelogFilename),n),this.logger.info(s.colors.green(`Changelog file written to ${w.join(this.destinationPath,this.changelogFilename)}`))}}class _{sourceDir;outputDir;fontName;constructor(e){this.sourceDir=e.sourceDir,this.outputDir=e.outputDir,this.fontName=e.fontName}async generate(){await T({src:this.sourceDir,dist:this.outputDir,fontName:this.fontName,css:!0,typescript:!0,startUnicode:59905,svgicons2svgfont:{fontHeight:1024}})}}class ${wss;eventListeners=new Map;lifecycleListeners=new Map;clients=new Map;ws;constructor(){this.wss=new m.WebSocketServer({noServer:!0}),this.wss.on("connection",e=>this.onConnection(e)),this.wss.on("error",e=>this.fireLifecycle("error",e)),this.ws={on:(e,t)=>{"close"!==e&&"error"!==e?this.getEventSet(e).add(t):this.getLifecycleSet(e).add(t)},off:(e,t)=>{this.eventListeners.get(e)?.delete(t),"close"!==e&&"error"!==e||this.lifecycleListeners.get(e)?.delete(t)},send:(e,t)=>{if("string"==typeof e)for(const o of this.clients.keys())this.sendToSocket(o,e,t);else{const t=JSON.stringify(e);for(const e of this.clients.keys())e.readyState===m.WebSocket.OPEN&&e.send(t)}}}}handleUpgrade(e,t,o){return(e.url??"").split("?")[0]===s.PP_DEV_HMR_WS_PATH&&(this.wss.handleUpgrade(e,t,o,t=>{this.wss.emit("connection",t,e)}),!0)}async close(){this.fireLifecycle("close");for(const e of this.clients.keys())e.terminate();this.clients.clear(),await new Promise(e=>this.wss.close(()=>e()))}onConnection(e){const t={send:(t,o)=>this.sendToSocket(e,t,o)};this.clients.set(e,t),e.on("message",e=>this.onMessage(t,e)),e.on("close",()=>this.clients.delete(e)),e.on("error",()=>{})}onMessage(e,t){let o;try{o=JSON.parse(t.toString())}catch{return}if(!o||"custom"!==o.type||"string"!=typeof o.event)return;const n=this.eventListeners.get(o.event);if(n)for(const t of n)try{t(o.data,e)}catch(e){s.createLogger().error(`ws handler for "${o.event}" failed`,{error:e instanceof Error?e:new Error(String(e))})}}sendToSocket(e,t,o){e.readyState===m.WebSocket.OPEN&&e.send(JSON.stringify({type:"custom",event:t,data:o}))}fireLifecycle(e,t){for(const o of this.lifecycleListeners.get(e)??[])try{o(t)}catch{}}getEventSet(e){let t=this.eventListeners.get(e);return t||(t=new Set,this.eventListeners.set(e,t)),t}getLifecycleSet(e){let t=this.lifecycleListeners.get(e);return t||(t=new Set,this.lifecycleListeners.set(e,t)),t}}const j=r.cac("pp-dev");function C(e,t,o){const n=[...s.PP_DEV_CONFIG_NAMES,"package.json","next.config.js","next.config.mjs","next.config.ts","vite.config.js","vite.config.mjs","vite.config.ts",".env",".env.local",".env.development",".env.development.local"].map(t=>w.join(e,t)),r=i.watch(n,{ignored:e=>{const t=w.basename(e);return/(^|[\/\\])\../.test(e)&&!t.startsWith(".env")&&!t.startsWith(".pp-dev")&&!t.startsWith(".pp-watch")},persistent:!0,ignoreInitial:!0,followSymlinks:!1});let a=null;return r.on("change",n=>{o(s.colors.blue(`🔧 Config file changed: ${w.relative(e,n)}`)),a&&clearTimeout(a),a=setTimeout(async()=>{try{o(s.colors.yellow("🔄 Restarting dev server due to config change...")),await t()}catch(e){o(s.colors.red(`❌ Failed to restart dev server: ${e?.message}. Stack: ${e?.stack}`))}},500)}),r.on("error",e=>{o(s.colors.red(`❌ Config watcher error: ${e}`))}),{watcher:r,restartCallback:t,logger:o}}function A(e){e.watcher&&e.watcher.close()}function N(e){if(!e||"object"!=typeof e||!("message"in e))return!1;const t=String(e.message);return/Turbopack is not supported/i.test(t)||/native bindings are not available/i.test(t)||/Only WebAssembly \(WASM\) bindings were loaded/i.test(t)}async function R(e){const{changelog:t,executionRoot:o,newAssetsPath:n,backupsDirPath:i,changelogDestinationPath:r,logLevel:a}=e;let l;if("string"==typeof t)l=w.resolve(o,t);else{if(!y.existsSync(i))return void s.createLogger(a).warn(s.colors.yellow("backups directory not found, skipping changelog generation"));const e=y.readdirSync(i,{withFileTypes:!0});if(!e.length)return void s.createLogger(a).warn(s.colors.yellow("no backups found, skipping changelog generation"));const t=e.filter(e=>e.isFile()&&e.name.endsWith(".zip"));if(!t.length)return void s.createLogger(a).warn(s.colors.yellow("no ZIP backups found, skipping changelog generation"));const o=t.reduce((e,t)=>y.statSync(w.resolve(i,e.name)).mtimeMs>y.statSync(w.resolve(i,t.name)).mtimeMs?e:t).name;l=w.resolve(i,o)}const c=new I({oldAssetsPath:l,newAssetsPath:n,destinationPath:r});await c.generateChangelog()}let M=global.__pp_dev_profile_session,O=0;const q=e=>{if(M)return new Promise((t,o)=>{M.post("Profiler.stop",(n,{profile:i})=>{if(n)o(n);else{const o=w.resolve(`./pp-dev-profile-${O++}.cpuprofile`);y.writeFileSync(o,JSON.stringify(i)),e(s.colors.yellow(`CPU profile written to ${s.colors.white(s.colors.dim(o))}`)),M=void 0,t()}})})},V=e=>{for(const[t,o]of Object.entries(e))Array.isArray(o)&&(e[t]=o[o.length-1])};function H(e){const t={...e};return delete t["--"],delete t.c,delete t.config,delete t.base,delete t.l,delete t.logLevel,delete t.clearScreen,delete t.d,delete t.debug,delete t.f,delete t.filter,delete t.m,delete t.mode,t}j.option("-c, --config <file>","[string] use specified config file").option("--base <path>","[string] public base path (default: /)").option("-l, --logLevel <level>","[string] info | warn | error | silent").option("--clearScreen","[boolean] allow/disable clear screen when logging").option("-d, --debug [feat]","[string | boolean] show debug logs").option("-f, --filter <filter>","[string] filter debug logs").option("-m, --mode <mode>","[string] set env mode"),j.command("[root]","start dev server").alias("serve").alias("dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action(async(e,t)=>{V(t);let o=null,i=null,r=!1;const c=e?w.resolve(process.cwd(),e):process.cwd(),d=s.createLogger(t.logLevel),p=async()=>{if(!r){r=!0;try{o&&(d.info(s.colors.yellow("🛑 Stopping existing dev server...")),await o.close(),o=null);const{clearConfigCache:f,getConfig:u}=await Promise.resolve().then(()=>require("./index-DlBoHBGI.js")).then(e=>e.config);f();const{createServer:g}=await(import("vite")),h=t.mode||"development",m=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(h,m);const v=await l.loadConfigFromFile({mode:h,command:"serve"},t.config,e,t.logLevel);let b=await a.getViteConfig(void 0,{mode:h,root:m});if(v){const{plugins:e,...t}=v.config;b=l.mergeConfig(b,t)}if(o=await g(l.mergeConfig(b,{root:e,base:t.base,mode:t.mode,configFile:t.config,logLevel:t.logLevel,clearScreen:t.clearScreen,optimizeDeps:{force:t.force},server:H(t),customLogger:d},!0)),!o.config.base||"/"===o.config.base)throw new Error('base cannot be equal to "/" or empty string');if(!o.httpServer)throw new Error("HTTP server not available");await o.listen();const y=global.__pp_dev_start_time??!1,P=y?s.colors.dim(`ready in ${s.colors.reset(s.colors.bold(Math.ceil(n.performance.now()-y)))} ms`):"";d.info(`\n ${s.colors.green(`${s.colors.bold("PP-DEV")} v${s.VERSION}`)} ${P}\n`),o.printUrls();const x=await u(m);if(!1!==x.inspector?.enabled){const e=o.resolvedUrls?.local[0],t=e?new URL(e).origin:`http://localhost:${o.config.server.port??5173}`;d.info(`\n ${s.colors.cyan("🔍 Request Inspector")} ${s.colors.dim(t+s.INSPECTOR_PATH)}\n`)}!function(e,t){if(!e.httpServer||!process.stdin.isTTY||process.env.CI)return;e._shortcutsOptions=t;const o=s.createLogger();t.print&&o.info(s.colors.dim(s.colors.green(" ➜"))+s.colors.dim(" press ")+s.colors.bold("h")+s.colors.dim(" to show help"));const n=(t.customShortcuts??[]).filter(L).concat(D);k?.(),k=null;let i=!1;const r=process.stdin.isPaused(),a=process.stdin,l=Boolean(a.isRaw),c=async t=>{if(""===t)return void process.kill(process.pid,"SIGINT");if(""===t)return void await e.close().finally(()=>process.exit(0));if(i)return;"h"===t&&o.info(["",s.colors.bold(" Shortcuts"),...n.map(e=>s.colors.dim(" press ")+s.colors.bold(e.key)+s.colors.dim(` to ${e.description}`))].join("\n"));const r=n.find(e=>e.key===t);r&&(i=!0,await r.action(e),i=!1)};process.stdin.setRawMode(!0),process.stdin.on("data",c).setEncoding("utf8").resume();const d=e.httpServer,p=()=>{k===p&&(d.removeListener("close",p),process.stdin.off("data",c),l||process.stdin.setRawMode(!1),r&&process.stdin.pause(),k=null)};k=p,d.on("close",p)}(o,{print:!0,customShortcuts:[...M?[{key:"p",description:"start/stop the profiler",async action(e){if(M)await q(d.info);else{const e=await import("node:inspector").then(e=>e.default);await new Promise(t=>{M=new e.Session,M.connect(),M.post("Profiler.enable",()=>{M?.post("Profiler.start",()=>{d.info("Profiler started"),t()})})})}}}]:[],{key:"l",description:"proxy re-login",action(e){e.ws.send({type:"custom",event:"redirect",data:{url:`/auth/index/logout?proxyRedirect=${encodeURIComponent("/")}`}})}}]}),i||(i=C(c,p,d.info),d.info(s.colors.blue("🔧 Config file watcher started"))),r=!1}catch(e){r=!1,d.error(s.colors.red(`error when starting dev server:\n${e.stack}`),{error:e}),q(d.info),process.exit(1)}}},f=async e=>{d.info(s.colors.yellow(`\n🛑 Received ${e}, shutting down gracefully...`));try{i&&(A(i),i=null),o&&(await o.close(),o=null),q(d.info),d.info(s.colors.green("✅ Graceful shutdown completed")),process.exit(0)}catch(e){d.error(s.colors.red(`❌ Error during graceful shutdown: ${e}`)),process.exit(1)}};process.on("SIGINT",()=>f("SIGINT")),process.on("SIGTERM",()=>f("SIGTERM")),process.on("uncaughtException",e=>{d.error(s.colors.red(`❌ Uncaught Exception: ${e}`)),f("uncaughtException")}),process.on("unhandledRejection",(e,t)=>{d.error(s.colors.red(`❌ Unhandled Rejection at: ${t}, reason: ${e}`)),f("unhandledRejection")}),await p()}),j.command("next [root]","start Next.js development server with pp-dev integration").alias("next-serve").alias("next-dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port",{default:3e3}).option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").option("--webpack","[boolean] use Webpack for Next dev (use when Turbopack/native SWC is unavailable)").option("--turbopack","[boolean] use Turbopack for Next dev when native bindings work").action(async(e,t)=>{V(t);let n=null,i=null,r=null,l=null,d=!1;const p=s.createLogger(),f=async()=>{if(!d){d=!0;try{const{next:g,constants:h}=await a.safeNextImport(),{PHASE_DEVELOPMENT_SERVER:m}=h;r&&(await r.close(),r=null),i&&(p.info(s.colors.yellow("🛑 Stopping existing Next.js server...")),await new Promise(e=>{i.close(()=>{i=null,e()})})),n&&"function"==typeof n.close&&(await n.close(),n=null);const{clearConfigCache:v}=await Promise.resolve().then(()=>require("./index-DlBoHBGI.js")).then(e=>e.config);v();const{join:b,basename:P}=await(import("path")),{createServer:x}=await(import("http")),S=await(import("next/dist/server/config.js")),E=S.default.default||S["module.exports"].default||S.default,T=H(t),L=e?b(process.cwd(),e):process.cwd();a.loadPPDevEnv(t.mode||"development",L),p.info(L);const k=await E(m,L);let D=k?.ppDev||{};if(0===Object.keys(D).length)try{const{getConfig:e}=await Promise.resolve().then(()=>require("./index-DlBoHBGI.js")).then(e=>e.config),t=await e(L);Object.keys(t).length>0?(D=t,p.info(s.colors.blue("🔧 Loaded pp-dev config from standalone config file"))):p.info(s.colors.yellow("⚠️ No pp-dev config found in Next.js config or standalone file, using defaults"))}catch(e){p.info(s.colors.yellow("⚠️ Failed to load standalone pp-dev config, using defaults")),console.debug("Error loading standalone config:",e)}else p.info(s.colors.blue("🔧 Loaded pp-dev config from Next.js config"));let F=null;try{const{getPkg:e}=await Promise.resolve().then(()=>require("./index-DlBoHBGI.js")).then(e=>e.config);F=e(L).name}catch{F=P(L)}s.validatePPDevConfig(D,F??"");const I=s.normalizePPDevConfig(D,F??""),_=I.backendBaseURL??"http://localhost:8080",j=I.templateLess,R=I.v7Features,M=I.disableSSLValidation,O=I.enableProxyCache,q=I.proxyCacheTTL,V=I.personalAccessToken,z=I.miHudLess,U=I.inspectorEnabled,W=I.inspectorMaxMemory,B=I.inspectorCaptureLimit,Z=I.appId??(process.env.MI_APP_ID&&parseInt(process.env.MI_APP_ID,10)||void 0)??(process.env.MI_PORTAL_PAGE_ID&&parseInt(process.env.MI_PORTAL_PAGE_ID,10)||void 0)??1,G=k?.basePath;let J="";G?J=G:(J=j?s.PATH_PAGE_PREFIX:R?s.PATH_TEMPLATE_LOCAL_PREFIX:s.PATH_TEMPLATE_PREFIX,J+=`/${F}`);const X=function(e){const t="1"===process.env.PP_DEV_NEXT_WEBPACK||"true"===process.env.PP_DEV_NEXT_WEBPACK;if(t&&(e.webpack||e.turbopack))throw new Error("Do not combine PP_DEV_NEXT_WEBPACK with --webpack or --turbopack");if(t)return{webpack:!0};if(e.webpack&&e.turbopack)throw new Error("Use only one of --webpack or --turbopack");return e.webpack?{webpack:!0}:e.turbopack?{turbopack:!0}:{}}(t),K=async e=>{delete process.env.TURBOPACK,n&&"function"==typeof n.close&&(await n.close(),n=null);const t={dev:!0,customServer:!0,hostname:T.host||"localhost",port:T.port,dir:L,conf:{...k,basePath:J,assetPrefix:J}};e.webpack?t.webpack=!0:e.turbopack&&(t.turbopack=!0),n=g(t),await n.prepare()};if(X.webpack)await K({webpack:!0});else if(X.turbopack)try{await K({turbopack:!0})}catch(e){if(!N(e))throw e;p.warn(s.colors.yellow("⚠ Turbopack is unavailable (native bindings). Falling back to Webpack.")),await K({webpack:!0})}else try{await K({})}catch(e){if(!N(e))throw e;p.warn(s.colors.yellow("⚠ Turbopack cannot run (native Next.js bindings unavailable). Falling back to Webpack.")),await K({webpack:!0})}if(!n)throw new Error("Next.js app failed to initialize");if(J.endsWith("/")||(J+="/"),"/"===J)throw new Error('basePath cannot be equal to "/" or equal to empty string');p.info(s.colors.green("✅ Next.js app prepared successfully")),p.info(s.colors.blue(`🔧 pp-dev plugin configured for template: ${F}`)),p.info(s.colors.blue(`🔧 Base path configured: ${J}`)),_&&(p.info(s.colors.blue(`🌐 Backend URL: ${_}`)),p.info(s.colors.blue(`🆔 Custom App ID: ${Z}`)));const Y=n.getRequestHandler(),Q="number"==typeof T.port?T.port:3e3,ee="string"==typeof T.host?T.host||"0.0.0.0":"localhost",te=new Set;i=x(async(e,t)=>{try{const o=e.url||"/",n=o.split("?")[0];let i=c.parse(o,!0);if(ne.length>0){if(n.startsWith("/_next/")||"/favicon.ico"===n||n.startsWith("/__nextjs_")){if(ie.length>0){let l=0;const d=()=>{if(l>=ie.length)return void r();const o=ie[l];l++,o(e,t,d)};return void d()}return void r()}let s=0;const a=()=>{if(s>=ne.length)return void r();const o=ne[s];s++,o(e,t,a)};return void a()}async function r(){if(n.startsWith(J))i=c.parse(o,!0);else{if(n===J.replace(/\/$/,"")){const e=o.replace(n,J);return t.writeHead(302,{Location:e}),void t.end()}if(n.startsWith("/_next/")||"/favicon.ico"===n||n.startsWith("/__nextjs_"));else if("/"===n)return t.writeHead(302,{Location:J}),void t.end()}await Y(e,t,i)}r()}catch(f){p.error(`Error handling request: ${f instanceof Error?f.message:String(f)}`,{error:f instanceof Error?f:void 0}),t.statusCode=500,t.end("Internal Server Error")}});let oe=null,ne=[],ie=[];if(!1!==U){const e=new s.RequestStore(W);s.registerInspectorRoutes(s.internalServer,e,B);const t=s.createRequestCaptureMiddleware(e,B);ne.push(t)}if(_){const e=new URL(_).host;_.startsWith("https://")&&(o.EventEmitter.defaultMaxListeners=Math.max(o.EventEmitter.defaultMaxListeners,20));const t={headers:{host:e,referer:_,origin:_.replace(/^(https?:\/\/)([^/]+)(\/.*)?$/i,"$1$2")},appId:Z,templateLess:j,disableSSLValidation:M,v7Features:R,personalAccessToken:V??process.env.MI_ACCESS_TOKEN};oe=new s.MiAPI(_,t);const l=s.initPPRedirect(J,F??void 0),c=(e,t,o)=>{l(e,t,o)};ie.push(c),ne.push(c);const d=a.createDevPanelAssetMiddleware(J);if(ie.push(d),ne.push(d),O){let e=+q;(!e||Number.isNaN(e)||e<0)&&(e=6e5);const t={devServer:{middlewares:{use:e=>e},config:{logger:console}},ttl:e},o=s.initProxyCache(t),n=(e,t,n)=>{o(e,t,n)};ne.push(n),p.info(s.colors.blue(`🔧 Proxy cache middleware added with TTL: ${e}ms`))}const f=new RegExp(`^((${u=J,u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})|/)$`),g=s.initLoadPPData(f,oe,Object.assign({base:J},t,{miHudLess:z})),m=(e,t,o)=>{g(e,t,o)};ne.push(m);const v=J.endsWith("/")?J.substring(0,J.length-1):J,b={middlewares:{use:e=>e},config:{logger:console}},x=s.initProxy({devServer:b,baseURL:_,proxyIgnore:["/@vite","/@metricinsights","/@",v,"/_next","/favicon.ico","/__nextjs_","/installHook.js.map"],disableSSLValidation:M,miAPI:oe,templateName:F??void 0}),S=(e,t,o)=>{x(e,t,o)};ne.push(S);const T=s.internalServer,D=(e,t,o)=>{if(e.url?.startsWith("/@api/")||e.url?.startsWith(s.INSPECTOR_PATH)||e.url?.startsWith(s.VARIABLES_EDITOR_PATH)){return void T(e,t,()=>{})}o()};ie.push(D),ne.push(D);const C=s.initRewriteResponse(e=>{const t=e.split("?")[0];return t.startsWith(J)&&!t.includes("/_next/")},(t,o)=>{const n=oe.buildPage(t,z),i=a.injectDevPanel(n,J,{backendBaseURL:_,templateLess:j,appId:Z,devPanelPosition:I.devPanelPosition,devPanelHidden:I.devPanelHidden,devPanelAutoHide:I.devPanelAutoHide});return Buffer.from(s.urlReplacer(e,o.headers.host??"",i))}),A=(e,t,o)=>{C(e,t,o)};ne.push(A),r=new $;let N=k?.distDir;try{process.env[s.PP_DEV_NEXT_BUILD_ENV_VAR]="1";const e=await E(h.PHASE_PRODUCTION_BUILD,L);N=e?.distDir??N}catch{}const H=(N??"").replace(/\\/g,"/").replace(/\/+$/,"").replace(/\/dev$/,""),U=H&&".next"!==H?H:"out";let W,B="0.0.0";try{const e=JSON.parse(y.readFileSync(w.join(L,"package.json"),"utf-8"));B="string"==typeof e.version?e.version:B,W="string"==typeof e.repository?e.repository:e.repository?.url}catch{}const G=new s.DistService(F??P(L),{root:L,backupFolder:w.resolve(L,I.syncBackupsDir),nextBuild:{projectRoot:L,distDir:U,packageVersion:B,packageRepositoryUrl:W}}),X={ws:r.ws,config:{clientInjectionPlugin:{v7Features:R}}};new s.ClientService(X,{distService:G,miAPI:oe}),s.registerVariablesEditorRoutes(s.internalServer,{distService:G,miAPI:oe});const K="function"==typeof n?.getUpgradeHandler?n.getUpgradeHandler():null;i.on("upgrade",(e,t,o)=>{r?.handleUpgrade(e,t,o)||(K?K(e,t,o):t.destroy())}),p.info(s.colors.blue(`🔧 ${ne.length} pp-dev middlewares initialized`)),p.info(s.colors.blue(`🔧 ${ie.length} essential middlewares for internal routes`)),p.info(s.colors.blue(`🔧 MiAPI initialized for backend: ${_}`)),p.info(s.colors.blue(`🔧 Custom App ID: ${Z}`))}i.listen(Q,ee,()=>{p.info(s.colors.green(`✅ pp-dev Next.js server running at http://${ee}:${Q}`)),p.info(s.colors.blue(`📱 Next.js app accessible at http://${ee}:${Q}${J}`)),!1!==U&&p.info(s.colors.cyan(`🔍 Request Inspector: http://${ee}:${Q}${s.INSPECTOR_PATH}`)),p.info(s.colors.blue("🔧 Base path handling active")),l||(l=C(L,f,p.info),p.info(s.colors.blue("🔧 Config file watcher started"))),i.on("connection",e=>{te.add(e),e.on("close",()=>te.delete(e))});const e=async e=>{p.info(s.colors.yellow(`\n🛑 Received ${e}, shutting down gracefully...`));const t=setTimeout(()=>{p.info(s.colors.yellow("⏰ Shutdown timeout reached, forcing exit")),process.exit(0)},5e3);try{l&&(A(l),l=null);for(const e of Array.from(te))e.destroy();te.clear(),r&&(await r.close(),r=null),await new Promise(e=>{i.close(()=>{p.info(s.colors.yellow("🛑 HTTP server closed")),e()})}),n&&"function"==typeof n.close&&(await n.close(),p.info(s.colors.yellow("🛑 Next.js app closed"))),clearTimeout(t),p.info(s.colors.green("✅ Graceful shutdown completed")),process.exit(0)}catch(e){clearTimeout(t),p.error(s.colors.red(`❌ Error during graceful shutdown: ${e}`)),process.exit(1)}};let t=process;if("function"!=typeof process.on){const e=globalThis.process||global.process;e&&"function"==typeof e.on&&(t=e,p.info(s.colors.green("✅ Using global process object for event handlers")))}if("function"==typeof t.on)try{t.on("SIGINT",()=>e("SIGINT")),t.on("SIGTERM",()=>e("SIGTERM")),t.on("uncaughtException",t=>{p.error(s.colors.red(`❌ Uncaught Exception: ${t}`)),e("uncaughtException")}),t.on("unhandledRejection",(t,o)=>{p.error(s.colors.red(`❌ Unhandled Rejection at: ${o}, reason: ${t}`)),e("unhandledRejection")}),p.info(s.colors.green("✅ Process event handlers registered successfully"))}catch(e){p.warn(s.colors.yellow(`⚠️ Failed to register process event handlers: ${e}`))}else p.warn(s.colors.yellow("⚠️ process.on is not available, graceful shutdown handlers will not be registered")),p.info(s.colors.blue("💡 This might be due to bundling or environment constraints"))}),d=!1}catch(e){d=!1,p.error(s.colors.red(`❌ Failed to start Next.js server: ${e?.message}. Stack: ${e?.stack}`)),e instanceof Error&&e.message.includes("Next.js is required")&&(p.error(s.colors.red("❌ Next.js Peer Dependency Error:")),p.error(s.colors.red(e.message)),p.error(s.colors.yellow("\n💡 To fix this issue:")),p.error(s.colors.blue(" 1. Install Next.js in your project:")),p.error(s.colors.white(" npm install next@^16")),p.error(s.colors.blue(" 2. Or use yarn:")),p.error(s.colors.white(" yarn add next@^16")),p.error(s.colors.blue(" 3. Or use pnpm:")),p.error(s.colors.white(" pnpm add next@^16")),p.error(s.colors.yellow("\n📖 For more information, see:")),p.error(s.colors.blue(" https://nextjs.org/docs/getting-started"))),process.exit(1)}var u}},u=async e=>{p.info(s.colors.yellow(`\n🛑 Received ${e}, shutting down gracefully...`));try{l&&(A(l),l=null),r&&(await r.close(),r=null),i&&await new Promise(e=>{i.close(()=>{i=null,e()})}),n&&"function"==typeof n.close&&(await n.close(),n=null),p.info(s.colors.green("✅ Graceful shutdown completed")),process.exit(0)}catch(e){p.error(s.colors.red(`❌ Error during graceful shutdown: ${e}`)),process.exit(1)}};process.on("SIGINT",()=>u("SIGINT")),process.on("SIGTERM",()=>u("SIGTERM")),process.on("uncaughtException",e=>{p.error(s.colors.red(`❌ Uncaught Exception: ${e}`)),u("uncaughtException")}),process.on("unhandledRejection",(e,t)=>{p.error(s.colors.red(`❌ Unhandled Rejection at: ${t}, reason: ${e}`)),u("unhandledRejection")}),await f()}),j.command("build [root]","build for production").option("--target <target>","[string] transpile target (default: 'modules')").option("--outDir <dir>","[string] output directory (default: dist)").option("--assetsDir <dir>","[string] directory under outDir to place assets in (default: assets)").option("--assetsInlineLimit <number>","[number] static asset base64 inline threshold in bytes (default: 4096)").option("--ssr [entry]","[string] build specified entry for server-side rendering").option("--sourcemap [output]",'[boolean | "inline" | "hidden"] output source maps for build (default: false)').option("--minify [minifier]",'[boolean | "terser" | "esbuild"] enable/disable minification, or specify minifier to use (default: esbuild)').option("--manifest [name]","[boolean | string] emit build manifest json").option("--ssrManifest [name]","[boolean | string] emit ssr manifest json").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle (experimental)").option("--emptyOutDir","[boolean] force empty outDir when it's outside of root").option("-w, --watch","[boolean] rebuilds when modules have changed on disk").option("--changelog [assetsFile]","[boolean | string] generate changelog between assetsFile and current build (default: false)").option("--distZip","[boolean] pack build output into a ZIP archive; use --no-distZip to disable (default: pp-dev config build.zip, or true). Env: PP_DEV_DIST_ZIP").option("--distZipDir <dir>","[string] override the ZIP output directory (default: 'dist-zip'). Env: PP_DEV_DIST_ZIP_DIR").option("--distZipFilename <filename>","[string] override the ZIP output file name (default: '<app-name>.zip'). Env: PP_DEV_DIST_ZIP_FILENAME").option("--versionManifest","[boolean] emit VERSION-*.json + BUILD-MANIFEST.json; use --no-versionManifest to disable (default: pp-dev config build.versionFile, or true). Env: PP_DEV_VERSION_MANIFEST").option("--versionFileTemplate <template>","[string] override the VERSION file name template (default: 'VERSION-v{packageversion}-{currentDate}.json'). Env: PP_DEV_VERSION_FILE_TEMPLATE").action(async(e,t)=>{V(t);const o=H(t),n=a.resolveBuildCliOverrides(t);try{const i=t.mode||"production",r=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(i,r);const s=await l.loadConfigFromFile({mode:i,command:"build"},t.config,e,t.logLevel);let c=await a.getViteConfig(n,{mode:i,root:r});if(s){const{plugins:e,...t}=s.config;c=l.mergeConfig(c,t)}const d=l.mergeConfig(c,{root:e,base:t.base,mode:t.mode,configFile:t.config,logLevel:t.logLevel,clearScreen:t.clearScreen,optimizeDeps:{force:t.force},build:o},!0);if(await l.build(d),o.changelog){const n=e||process.cwd(),i=d.build?.outDir||"dist";let r="dist-zip";d.ppDevConfig&&(!1===d.ppDevConfig.distZip?r=i:"object"==typeof d.ppDevConfig.distZip&&"string"==typeof d.ppDevConfig.distZip.outDir&&(r=d.ppDevConfig.distZip.outDir)),await R({changelog:o.changelog,executionRoot:n,newAssetsPath:w.resolve(n,i),backupsDirPath:w.resolve(n,d.ppDevConfig?.syncBackupsDir||"backups"),changelogDestinationPath:w.resolve(n,r),logLevel:t.logLevel})}}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error during build:\n${e.stack}`),{error:e}),process.exit(1)}finally{q(e=>s.createLogger(t.logLevel).info(e))}}),j.command("next-build [root]","build a Next.js app for production (`next build`) and emit VERSION/BUILD-MANIFEST/zip in the same format as `pp-dev build`").option("--changelog [assetsFile]","[boolean | string] generate changelog between assetsFile and current build (default: false)").option("--distZip","[boolean] pack build output into a ZIP archive; use --no-distZip to disable (default: pp-dev config build.zip, or true). Env: PP_DEV_DIST_ZIP").option("--distZipDir <dir>","[string] override the ZIP output directory (default: 'dist-zip'). Env: PP_DEV_DIST_ZIP_DIR").option("--distZipFilename <filename>","[string] override the ZIP output file name (default: '<app-name>.zip'). Env: PP_DEV_DIST_ZIP_FILENAME").option("--versionManifest","[boolean] emit VERSION-*.json + BUILD-MANIFEST.json; use --no-versionManifest to disable (default: pp-dev config build.versionFile, or true). Env: PP_DEV_VERSION_MANIFEST").option("--versionFileTemplate <template>","[string] override the VERSION file name template (default: 'VERSION-v{packageversion}-{currentDate}.json'). Env: PP_DEV_VERSION_FILE_TEMPLATE").action(async(e,t)=>{V(t);const o=s.createLogger(t.logLevel),n=e?w.resolve(process.cwd(),e):process.cwd(),i=a.resolveBuildCliOverrides(t);process.env[s.PP_DEV_NEXT_BUILD_ENV_VAR]="1";try{a.loadPPDevEnv(t.mode||"production",n);const{constants:e}=await a.safeNextImport(),r=await(import("next/dist/server/config.js")),l=r.default.default||r["module.exports"].default||r.default,c=await l(e.PHASE_PRODUCTION_BUILD,n);let d,p=c?.ppDev||{};if(0===Object.keys(p).length){const{getConfig:e}=await Promise.resolve().then(()=>require("./index-DlBoHBGI.js")).then(e=>e.config);p=await e(n)}try{const{getPkg:e}=await Promise.resolve().then(()=>require("./index-DlBoHBGI.js")).then(e=>e.config);d=e(n).name}catch{d=w.basename(n)}const f=s.normalizePPDevConfig(p,d),u=a.applyDistZipOverride(f.distZip,i,s.createDefaultZipFileName(d)),g=a.applyVersionManifestOverride(f.versionPlugin,i),h=s.removeStaleDevTypes(n,c);h&&o.info(s.colors.dim(`[pp-dev] Removed stale dev route types: ${w.relative(n,h)}`)),o.info(s.colors.cyan("[pp-dev] Running `next build`...")),await s.runNextBuildProcess(n);const m="string"==typeof c?.distDir&&c.distDir?c.distDir:".next",v=".next"===m?"out":m,b=w.resolve(n,v);if(!y.existsSync(b)||!y.statSync(b).isDirectory())throw new Error(`Next.js build output directory not found: ${b}. "next-build" requires "output: 'export'" in next.config (static export).`);const P=JSON.parse(y.readFileSync(w.join(n,"package.json"),"utf-8"));if(!1!==g&&!1!==g.enabled&&(s.writeBuildVersionManifest({outDir:b,packageVersion:"string"==typeof P.version?P.version:"0.0.0",versionFileTemplate:g.versionFileTemplate,packageRepositoryUrl:"string"==typeof P.repository?P.repository:P.repository?.url,enabled:g.enabled}),o.info(s.colors.green(`✅ VERSION / BUILD-MANIFEST written to ${w.relative(n,b)}`))),!1!==u){const e=w.resolve(n,u.outDir),t=u.inDir?w.resolve(b,u.inDir):b,i=s.resolveOutputFilePath(e,u.outFileName,"ZIP output file name");y.mkdirSync(w.dirname(i),{recursive:!0});const r=await s.zipDirectoryToBuffer(t);y.writeFileSync(i,r),o.info(s.colors.green(`✅ Zip archive written to ${w.relative(n,i)}`))}if(t.changelog){const e=!1!==u?u.outDir:v;await R({changelog:t.changelog,executionRoot:n,newAssetsPath:b,backupsDirPath:w.resolve(n,f.syncBackupsDir),changelogDestinationPath:w.resolve(n,e),logLevel:t.logLevel})}}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error during next-build:\n${e.stack}`),{error:e}),process.exit(1)}finally{q(e=>s.createLogger(t.logLevel).info(e))}}),j.command("changelog [oldAssetPath] [newAssetPath]","generate changelog between two assets files/folders").option("--oldAssetsPath <oldAssetsPath>","[string] path to the old assets zip file or folder").option("--newAssetsPath <newAssetsPath>","[string] path to the new assets zip file or folder").option("--destination <destination>","[string] destination folder for the changelog (default: .)").option("--filename <filename>","[string] filename for the changelog (default: CHANGELOG.html)").action(async(e,t,o)=>{V(o);const{oldAssetsPath:n=e,newAssetsPath:i=t,destination:r=".",filename:a="CHANGELOG.html",logLevel:l}=o,c=process.cwd();n&&i||(s.createLogger(l).error(s.colors.red("error during changelog generation: oldAssetPath and newAssetPath are required")),process.exit(1));const d=w.resolve(c,n),p=w.resolve(c,i),f=w.resolve(c,r),u=new I({oldAssetsPath:d,newAssetsPath:p,destinationPath:f,changelogFilename:a});await u.generateChangelog()}),j.command("generate-icon-font [source] [destination]","generate icon font from SVG files").option("--source <source>","[string] path to the source directory with SVG files").option("--destination <destination>","[string] path to the destination directory to save the generated font files").option("--font-name, -n <fontName>","[string] name of the font to generate (default: 'icon-font')").action(async(e,t,o)=>{V(o);const{source:n=e,destination:i=t,fontName:r="icon-font"}=o,a=process.cwd(),l=w.resolve(a,n),c=w.resolve(a,i),d=new _({sourceDir:l,outputDir:c,fontName:r}),p=s.createLogger(o.logLevel);p.info(`Generating icon font from SVG files in ${s.colors.dim(l)}`),await d.generate(),p.info(`Icon font generated and saved to ${s.colors.dim(c)}`)}),j.command("optimize [root]","pre-bundle dependencies").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action(async(e,t)=>{V(t);try{const o=t.mode||"production",n=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(o,n);const i=await l.loadConfigFromFile({mode:o,command:"build"},t.config,e,t.logLevel);let r=await a.getViteConfig(void 0,{mode:o,root:n});if(i){const{plugins:e,...t}=i.config;r=l.mergeConfig(r,t)}const s=await l.resolveConfig(l.mergeConfig(r,{root:e,base:t.base,configFile:t.config,logLevel:t.logLevel,mode:t.mode}),"serve");await l.optimizeDeps(s,t.force,!0)}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error when optimizing deps:\n${e.stack}`),{error:e}),process.exit(1)}}),j.command("preview [root]","locally preview production build").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--strictPort","[boolean] exit if specified port is already in use").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--outDir <dir>","[string] output directory (default: dist)").action(async(e,t)=>{V(t);try{const o=t.mode||"production",n=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(o,n);const i=await l.loadConfigFromFile({mode:o,command:"build"},t.config,e,t.logLevel);let r=await a.getViteConfig(void 0,{mode:o,root:n});if(i){const{plugins:e,...t}=i.config;r=l.mergeConfig(r,t)}(await l.preview(l.mergeConfig(r,{root:e,base:t.base,configFile:t.config,logLevel:t.logLevel,mode:t.mode,build:{outDir:t.outDir},preview:{port:t.port,strictPort:t.strictPort,host:t.host,https:t.https,open:t.open}}))).printUrls()}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error when starting preview server:\n${e.stack}`),{error:e}),process.exit(1)}finally{q(e=>s.createLogger(t.logLevel).info(e))}}),j.command("migrate [config]","migrate pp-dev config from 0.x flat format to 1.0 grouped format").option("--dry-run","[boolean] print migrated config without writing any files").option("--format <format>","[string] output format: ts (default), js, json").option("--output <file>","[string] output file path (default: pp-dev.config.ts)").option("--no-backup","[boolean] skip backup of original config file").action(async(e,t)=>{const o=s.createLogger(t.logLevel),{isLegacyFlatConfig:n,isLegacyPPWatchConfig:i,isAlreadyMigrated:r,migrateLegacyFlatConfig:a,migratePPWatchConfig:l,generateConfigFileContent:c,discoverMigrateSource:d,loadPackageJsonMigrateConfig:p}=await Promise.resolve().then(()=>require("./migrate-G-xh-wpc.js")),f=t.format??"ts",u=!1!==t.backup,g=process.cwd(),h=d(g,e);h||(o.warn(s.colors.yellow("No pp-dev or pp-watch config file found in the current directory.")),o.info(s.colors.blue('Supported files: pp-dev.config.{ts,js,cjs,mjs,json}, .pp-watch.config.{ts,js,json}, or a "pp-dev" field in package.json')),process.exit(1));const{sourceFile:m,isWatchConfig:v,isPackageJsonConfig:b}=h;o.info(s.colors.blue(`Found config: ${w.relative(g,m)}`));const{getPkg:P}=await Promise.resolve().then(()=>require("./index-DlBoHBGI.js")).then(e=>e.config),x=P();let S,E={};try{if(/\.[cm]?ts$/i.test(m)){const e=await(import("esbuild")),{pathToFileURL:t}=await(import("url")),o=(await e.build({absWorkingDir:g,entryPoints:[m],outfile:"out.js",write:!1,target:"node24",platform:"node",bundle:!0,packages:"external",format:"esm",mainFields:["main"]})).outputFiles[0].text,n=`pp-migrate-tmp-${Date.now()}.mjs`;y.writeFileSync(n,o);try{const e=await(import(t(w.resolve(g,n)).toString()));E=e.default?.default??e.default??e}finally{y.existsSync(n)&&y.unlinkSync(n)}}else if(/\.[cm]?js$/i.test(m)){const{pathToFileURL:e}=await(import("url")),t=await(import(e(w.resolve(g,m)).toString()));E=t.default?.default??t.default??t}else b?E=p(m):m.endsWith(".json")&&(E=JSON.parse(y.readFileSync(m,"utf-8")))}catch(e){o.error(s.colors.red(`Failed to load config file: ${e.message}`)),process.exit(1)}E&&"object"==typeof E||(o.error(s.colors.red("Config file did not export a valid object.")),process.exit(1)),r(E)?(o.info(s.colors.green("Config is already in 1.0 format — nothing to migrate.")),process.exit(0)):v||i(E)?(o.info(s.colors.blue("Detected pp-watch config format → migrating to 1.0")),S=l(E)):n(E)?(o.info(s.colors.blue("Detected 0.x flat config format → migrating to 1.0")),S=a(E,x.name)):(o.warn(s.colors.yellow("Could not detect config format. No known keys found.")),process.exit(1));const T=c(S,f),L=t.output??w.join(g,`pp-dev.config.${f}`);if(t.dryRun&&(o.info(s.colors.green(`\n--- Migrated config (dry-run) → ${w.relative(g,L)} ---\n`)),process.exit(0)),u&&!b&&y.existsSync(m)){const e=`${m}.bak`;y.copyFileSync(m,e),o.info(s.colors.blue(`Backed up original to: ${w.relative(g,e)}`))}y.writeFileSync(L,T,"utf-8"),o.info(s.colors.green(`✅ Migration complete → ${w.relative(g,L)}`)),b?o.info(s.colors.yellow('You can now remove the "pp-dev" field from package.json.')):m!==L&&y.existsSync(m)&&o.info(s.colors.yellow(`You can now delete the old config: ${w.relative(g,m)}`))}),j.help(),j.version(s.VERSION),j.parse(),exports.stopProfiler=q;
|
|
1
|
+
"use strict";const e=require("path"),t=require("fs"),o=require("node:events"),n=require("node:perf_hooks"),i=require("chokidar"),r=require("cac"),s=require("./plugin-Cx8D7mM_.js"),a=require("./index-BcARY73n.js"),l=require("vite"),c=require("url"),d=require("dir-compare"),p=require("diff-match-patch"),f=require("isbinaryfile"),u=require("os"),g=require("crypto"),h=require("svgtofont"),m=require("ws");require("http-proxy-middleware"),require("picocolors"),require("node:string_decoder"),require("axios"),require("node:http"),require("node:https"),require("jsdom"),require("process"),require("child_process"),require("node:path"),require("jszip"),require("module"),require("zlib"),require("express"),require("node:crypto"),require("node:fs"),require("node:os"),require("./helpers.js"),require("ejs");const v=e=>e&&"object"==typeof e&&"default"in e?e.default:e;function b(e){if(e&&"object"==typeof e&&"default"in e)return e;const t=Object.create(null);if(e)for(const o in e)t[o]=e[o];return t.default=e,Object.freeze(t)}const w=b(e),y=b(t),P=b(d),S=v(p),x=b(u),E=b(g),T=v(h);function L(e){return null!=e&&!1!==e}let k=null;const D=[{key:"r",description:"restart the server",async action(e){await e.restart()}},{key:"u",description:"show server url",action(e){e.config.logger.info(""),e.printUrls()}},{key:"o",description:"open in browser",action(e){e.openBrowser()}},{key:"c",description:"clear console",action(e){e.config.logger.clearScreen("error")}},{key:"q",description:"quit",async action(e){await e.close().finally(()=>process.exit())}},{key:"C",description:"clear proxy cache",action(e){e.cache&&(e.cache.clear(),e.config.logger.info("Proxy cache cleared"))}}];const F=/(.+)(-[a-f0-9]{6,20})(\.[a-z0-9]+)$/i;class I{oldAssetsPath;newAssetsPath;destinationPath;changelogFilename;changelogTemplate='<!DOCTYPE html>\n <html lang="en">\n <head>\n <meta charset="UTF-8" />\n <title>Changelog Diff</title>\n <style>\n tr,\n td {\n padding: 0;\n }\n .diff-file {\n margin-top: 20px;\n border: 1px solid #e1e4e8;\n border-radius: 6px;\n }\n .diff-file-title {\n padding: 10px 20px;\n background-color: #f6f8fa;\n border-bottom: 1px solid #e1e4e8;\n border-radius: 6px 6px 0 0;\n font-weight: bold;\n }\n .diff-file-title .renamed {\n font-weight: normal;\n }\n .diff-file-title .renamed .from {\n color: #cb2431;\n }\n .diff-file-title .renamed .to {\n color: #22863a;\n }\n .diff-file-title .added {\n color: #22863a;\n }\n .diff-file-title .deleted {\n color: #cb2431;\n }\n .diff-file-content {\n }\n .diff-table {\n tab-size: 8;\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n }\n .blob-num {\n position: relative;\n color: #1f2328;\n width: 1%;\n min-width: 50px;\n padding: 0 10px;\n font-family:\n ui-monospace,\n SFMono-Regular,\n SF Mono,\n Menlo,\n Consolas,\n Liberation Mono,\n monospace;\n font-size: 12px;\n line-height: 20px;\n text-align: right;\n white-space: nowrap;\n vertical-align: top;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n }\n .blob-num.addition {\n background-color: #ccffd8;\n border-color: #1f883e;\n }\n .blob-num.deletion {\n background-color: #ffd7d5;\n border-color: #cf222e;\n }\n .blob-num::before {\n content: attr(data-line-number);\n }\n .blob-code {\n position: relative;\n padding: 0 10px 0 22px;\n vertical-align: top;\n color: #1f2329;\n }\n .blob-code.code-addition {\n background-color: #e6ffec;\n }\n .blob-code.code-deletion {\n background-color: #ffebe9;\n }\n .blob-code.skip,\n .blob-code.message {\n text-align: center;\n }\n .blob-code.skip .blob-code-inner,\n .blob-code.message .blob-code-inner {\n font-weight: bold;\n color: #6a737d;\n padding: 10px 0;\n }\n .blob-code-inner {\n display: table-cell;\n overflow: visible;\n font-family:\n ui-monospace,\n SFMono-Regular,\n SF Mono,\n Menlo,\n Consolas,\n Liberation Mono,\n monospace;\n font-size: 12px;\n word-wrap: anywhere;\n white-space: pre-wrap;\n }\n .blob-code-inner::before {\n content: attr(data-code-prefix);\n position: absolute;\n top: 1px;\n left: 8px;\n padding-right: 8px;\n }\n </style>\n </head>\n <body>\n <h1>Changelog Diff</h1>\n\n %FILES%\n </body>\n </html>';diffFileTemplateHandler;diffLineTemplateHandler;contextLines=3;logger;constructor(e){const{oldAssetsPath:t,newAssetsPath:o,destinationPath:n,changelogTemplate:i,diffFileTemplateHandler:r,diffLineTemplateHandler:a,changelogFilename:l,contextLines:c}=e;if(this.logger=s.createLogger(),!t||!o||!n)throw new Error("Previous assets path, current assets path and destination path are required");if(t===o)throw new Error("Previous and current assets paths must be different");if(!this.isExists(t))throw new Error(`Previous assets path ${t} does not exist`);if(!this.isExists(o))throw new Error(`Current assets path ${o} does not exist`);if(this.isZipFile(t)){const e=w.resolve(x.tmpdir(),E.createHash("md5").update(t).digest("hex"));this.oldAssetsPath=this.unzipFile(t,e).then(()=>this.normalizeAssetFolderPath(e)).then(e=>{if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);return e})}else{if(!this.isFolder(t))throw new Error(`Invalid previous assets path ${t}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(t);if(this.isEmptyFolder(e))throw new Error(`Previous assets path ${e} is empty`);this.oldAssetsPath=Promise.resolve(e)}}if(this.isZipFile(o)){const e=w.resolve(x.tmpdir(),E.createHash("md5").update(o).digest("hex"));this.newAssetsPath=this.unzipFile(o,e).then(()=>this.normalizeAssetFolderPath(e)).then(e=>{if(this.isEmptyFolder(e))throw new Error(`Current assets path ${e} is empty`);return e})}else{if(!this.isFolder(o))throw new Error(`Invalid current assets path ${o}. It must be a folder or a zip file`);{const e=this.normalizeAssetFolderPath(o);if(this.isEmptyFolder(e))throw new Error(`Current assets path ${o} is empty`);this.newAssetsPath=Promise.resolve(e)}}this.destinationPath=n,this.mkdirpSync(this.destinationPath),this.changelogFilename=l||"CHANGELOG.html",i&&(this.templateIsValid(i)?this.changelogTemplate=i:this.logger.warn(s.colors.yellow("Invalid changelog template, using default"))),"function"==typeof r&&(this.diffFileTemplateHandler=r),"function"==typeof a&&(this.diffLineTemplateHandler=a),c&&(this.contextLines=c)}templateIsValid(e){return e.includes("%FILES%")}isExists(e){return y.existsSync(e)}isZipFile(e){return e.endsWith(".zip")}isFolder(e){return y.lstatSync(e).isDirectory()}isEmptyFolder(e){return 0===y.readdirSync(e,{withFileTypes:!0}).length}mkdirpSync(e){y.existsSync(e)||y.mkdirSync(e,{recursive:!0})}async unzipFile(e,t){y.rmSync(t,{force:!0,recursive:!0}),await s.extractZipSafe(e,t)}normalizeAssetFolderPath(e){const t=y.readdirSync(e);return 1===t.length&&y.lstatSync(w.join(e,t[0])).isDirectory()?this.normalizeAssetFolderPath(w.join(e,t[0])):e}pathToPosix(e){return e.replace(/\\/g,"/")}diffTableTemplate(e){return`<table class="diff-table">\n <tbody>\n ${e}\n </tbody>\n </table>`}getDiffTableHTML(e){const t=e.filter((e,t,o)=>0!==e.lineType||(t>=0&&t<this.contextLines||t>o.length-(this.contextLines+1)&&t<=o.length-1||o.slice(t-this.contextLines,t+this.contextLines+1).some(e=>0!==e.lineType))).map((e,t,o)=>{if(t>0){const n=o[t-1];if(e.lineNumber-n.lineNumber>1)return[{lineNumber:-1,lineContent:"",lineType:0},e]}return[e]}).flat().map(e=>this.diffLineHTML(e)).join("");return this.diffTableTemplate(t)}diffLineMessageTemplate(e){return`<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code message">\n <span class="blob-code-inner">${e}</span>\n </td>\n </tr>`}diffLineSkipTemplate(){return'<tr>\n <td class="blob-num"></td>\n <td class="blob-num"></td>\n <td class="blob-code skip">\n <span class="blob-code-inner">Skip</span>\n </td>\n </tr>'}diffLineTemplate(e){const{lineNumber:t,lineContent:o,lineType:n}=e,i=1===n?"addition":-1===n?"deletion":"";return`<tr>\n <td\n class="blob-num ${i}${"addition"===i?" empty":""}"\n ${"addition"!==i?` data-line-number="${t}"`:""}\n ></td>\n <td\n class="blob-num ${i}${"deletion"===i?" empty":""}"\n ${"deletion"!==i?` data-line-number="${t}"`:""}\n ></td>\n <td class="blob-code ${1===n?"code-addition":-1===n?"code-deletion":""}">\n <span class="blob-code-inner" data-code-prefix="${1===n?"+":-1===n?"-":" "}">${r=o??"",r.replace(/[\u00A0-\u9999<>&]/g,e=>"&#"+e.charCodeAt(0)+";")}</span>\n </td>\n </tr>`;var r}diffLineHTML(e){if(this.diffLineTemplateHandler)return this.diffLineTemplateHandler(e);const{lineNumber:t}=e;return-1===t?this.diffLineSkipTemplate():this.diffLineTemplate(e)}diffFileTemplate(e,t){return this.diffFileTemplateHandler?this.diffFileTemplateHandler(e,t):`<div class="diff-file">\n <div class="diff-file-title">${e}</div>\n <div class="diff-file-content">${t}</div>\n </div>`}async generateAssetFoldersDiff(){this.logger.info(s.colors.blue(`Comparing asset folders ${await this.oldAssetsPath} and ${await this.newAssetsPath}`));const e=await P.compare(await this.oldAssetsPath,await this.newAssetsPath,{compareContent:!0,skipSymlinks:!0,compareSize:!0,compareDate:!1,compareNameHandler:(e,t)=>(F.test(e)&&(e=e.replace(F,"$1$3")),F.test(t)&&(t=t.replace(F,"$1$3")),0===e.localeCompare(t)?0:e.localeCompare(t)>0?1:-1)});return e.diffSet?.filter(e=>"equal"!==e.state||e.name1!==e.name2)||[]}async generateAssetFilesDiff(e,t){const o=new S,n=o.diff_linesToChars_(e,t),i=o.diff_main(n.chars1,n.chars2,!1);o.diff_charsToLines_(i,n.lineArray);let r=0;return i.map(e=>{const[t,o]=e,n=o.endsWith("\n")?o.split("\n").length-1:o.split("\n").length,i=o.split("\n").map((e,o)=>({lineContent:e,lineNumber:r+o+1,lineType:t})).slice(0,n);return-1!==t&&(r+=n),i}).flat()}async generateFilesDiff(e){if("equal"===e.state){const t=this.pathToPosix(w.join(".",e.relativePath,e.name1??"")),o=this.pathToPosix(w.join(".",e.relativePath,e.name2??""));return this.diffFileTemplate(`<span class="renamed"\n >Renamed <span class="from">${t}</span> -> <span class="to">${o}</span></span\n >`,this.diffTableTemplate(this.diffLineMessageTemplate("No changes")))}const t=e.path1&&e.name1?w.join(e.path1,e.name1):null,o=e.path2&&e.name2?w.join(e.path2,e.name2):null,n=this.pathToPosix(w.join(".",e.relativePath,(e.name1||e.name2)??""));if("left"===e.state&&t)return this.diffFileTemplate(`<span class="removed">Removed ${n}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File removed")));if("right"===e.state&&o)return this.diffFileTemplate(`<span class="added">Added ${n}</span>`,this.diffTableTemplate(this.diffLineMessageTemplate("File added")));if("distinct"===e.state&&t&&o){const i=this.pathToPosix(w.join(".",e.relativePath,e.name1??"")),r=this.pathToPosix(w.join(".",e.relativePath,e.name2??"")),s=e.name1!==e.name2?`<span class="renamed"\n >Renamed <span class="from">${i}</span> -> <span class="to">${r}</span></span\n >`:n;return this.diffFileTemplate(s,await f.isBinaryFile(t)||await f.isBinaryFile(o)?this.diffTableTemplate(this.diffLineMessageTemplate("Binary file")):this.getDiffTableHTML(await this.generateAssetFilesDiff(y.readFileSync(t,"utf-8"),y.readFileSync(o,"utf-8"))))}return""}async generateChangelog(){this.logger.info(s.colors.green("Generating changelog"));const e=await this.generateAssetFoldersDiff(),t=(await Promise.all(e.map(e=>this.generateFilesDiff(e)))).join("");this.logger.info(s.colors.green("Writing changelog file"));const o=this.changelogTemplate.split("%FILES%");o.splice(1,0,t);const n=o.join("");y.writeFileSync(w.join(this.destinationPath,this.changelogFilename),n),this.logger.info(s.colors.green(`Changelog file written to ${w.join(this.destinationPath,this.changelogFilename)}`))}}class _{sourceDir;outputDir;fontName;constructor(e){this.sourceDir=e.sourceDir,this.outputDir=e.outputDir,this.fontName=e.fontName}async generate(){await T({src:this.sourceDir,dist:this.outputDir,fontName:this.fontName,css:!0,typescript:!0,startUnicode:59905,svgicons2svgfont:{fontHeight:1024}})}}class ${wss;eventListeners=new Map;lifecycleListeners=new Map;clients=new Map;ws;constructor(){this.wss=new m.WebSocketServer({noServer:!0}),this.wss.on("connection",e=>this.onConnection(e)),this.wss.on("error",e=>this.fireLifecycle("error",e)),this.ws={on:(e,t)=>{"close"!==e&&"error"!==e?this.getEventSet(e).add(t):this.getLifecycleSet(e).add(t)},off:(e,t)=>{this.eventListeners.get(e)?.delete(t),"close"!==e&&"error"!==e||this.lifecycleListeners.get(e)?.delete(t)},send:(e,t)=>{if("string"==typeof e)for(const o of this.clients.keys())this.sendToSocket(o,e,t);else{const t=JSON.stringify(e);for(const e of this.clients.keys())e.readyState===m.WebSocket.OPEN&&e.send(t)}}}}handleUpgrade(e,t,o){return(e.url??"").split("?")[0]===s.PP_DEV_HMR_WS_PATH&&(this.wss.handleUpgrade(e,t,o,t=>{this.wss.emit("connection",t,e)}),!0)}async close(){this.fireLifecycle("close");for(const e of this.clients.keys())e.terminate();this.clients.clear(),await new Promise(e=>this.wss.close(()=>e()))}onConnection(e){const t={send:(t,o)=>this.sendToSocket(e,t,o)};this.clients.set(e,t),e.on("message",e=>this.onMessage(t,e)),e.on("close",()=>this.clients.delete(e)),e.on("error",()=>{})}onMessage(e,t){let o;try{o=JSON.parse(t.toString())}catch{return}if(!o||"custom"!==o.type||"string"!=typeof o.event)return;const n=this.eventListeners.get(o.event);if(n)for(const t of n)try{t(o.data,e)}catch(e){s.createLogger().error(`ws handler for "${o.event}" failed`,{error:e instanceof Error?e:new Error(String(e))})}}sendToSocket(e,t,o){e.readyState===m.WebSocket.OPEN&&e.send(JSON.stringify({type:"custom",event:t,data:o}))}fireLifecycle(e,t){for(const o of this.lifecycleListeners.get(e)??[])try{o(t)}catch{}}getEventSet(e){let t=this.eventListeners.get(e);return t||(t=new Set,this.eventListeners.set(e,t)),t}getLifecycleSet(e){let t=this.lifecycleListeners.get(e);return t||(t=new Set,this.lifecycleListeners.set(e,t)),t}}function C(e){return e instanceof Error?e.stack??e.message:String(e)}function j({logger:e,knownRejections:t=[],shutdown:o,shutdownTimeoutMs:n=5e3,processRef:i=process}){let r=!1,a=0;const l=async(t,l)=>{if((e=>{a=Math.max(a,e)})(l),r)return void("SIGINT"!==t&&"SIGTERM"!==t||(e.warn(s.colors.yellow(`\n⚠️ Received ${t} again, exiting without waiting for the shutdown`)),i.exit(a)));r=!0,e.info(s.colors.yellow(`\n🛑 Received ${t}, shutting down gracefully...`));const c=setTimeout(()=>{e.error(s.colors.red(`⏰ Shutdown did not finish within ${n} ms, forcing exit`)),i.exit(1)},n);try{await o(),clearTimeout(c),e.info(s.colors.green("✅ Graceful shutdown completed")),i.exit(a)}catch(t){clearTimeout(c),e.error(s.colors.red(`❌ Error during graceful shutdown: ${C(t)}`)),i.exit(1)}},c=()=>{l("SIGINT",0)},d=()=>{l("SIGTERM",0)},p=t=>{e.error(s.colors.red(`❌ Uncaught exception: ${C(t)}`)),l("uncaughtException",1)},f=o=>{const n=t.find(e=>e.matches(o));n?e.info(s.colors.dim(n.message)):e.error(s.colors.red(`❌ Unhandled promise rejection (the server keeps running): ${C(o)}`))};return i.on("SIGINT",c),i.on("SIGTERM",d),i.on("uncaughtException",p),i.on("unhandledRejection",f),()=>{i.off("SIGINT",c),i.off("SIGTERM",d),i.off("uncaughtException",p),i.off("unhandledRejection",f)}}const A={matches:e=>e instanceof Error&&"Worker creator already registered"===e.message,message:"Next.js kept its Turbopack worker pool from before the restart ('Worker creator already registered')"};const N=r.cac("pp-dev");function R(e,t,o){const n=[...s.PP_DEV_CONFIG_NAMES,"package.json","next.config.js","next.config.mjs","next.config.ts","vite.config.js","vite.config.mjs","vite.config.ts",".env",".env.local",".env.development",".env.development.local"].map(t=>w.join(e,t)),r=i.watch(n,{ignored:e=>{const t=w.basename(e);return/(^|[\/\\])\../.test(e)&&!t.startsWith(".env")&&!t.startsWith(".pp-dev")&&!t.startsWith(".pp-watch")},persistent:!0,ignoreInitial:!0,followSymlinks:!1});let a=null;return r.on("change",n=>{o(s.colors.blue(`🔧 Config file changed: ${w.relative(e,n)}`)),a&&clearTimeout(a),a=setTimeout(async()=>{try{o(s.colors.yellow("🔄 Restarting dev server due to config change...")),await t()}catch(e){o(s.colors.red(`❌ Failed to restart dev server: ${e?.message}. Stack: ${e?.stack}`))}},500)}),r.on("error",e=>{o(s.colors.red(`❌ Config watcher error: ${e}`))}),{watcher:r,restartCallback:t,logger:o}}function M(e){e.watcher&&e.watcher.close()}function q(e){if(!e||"object"!=typeof e||!("message"in e))return!1;const t=String(e.message);return/Turbopack is not supported/i.test(t)||/native bindings are not available/i.test(t)||/Only WebAssembly \(WASM\) bindings were loaded/i.test(t)}async function O(e){const{changelog:t,executionRoot:o,newAssetsPath:n,backupsDirPath:i,changelogDestinationPath:r,logLevel:a}=e;let l;if("string"==typeof t)l=w.resolve(o,t);else{if(!y.existsSync(i))return void s.createLogger(a).warn(s.colors.yellow("backups directory not found, skipping changelog generation"));const e=y.readdirSync(i,{withFileTypes:!0});if(!e.length)return void s.createLogger(a).warn(s.colors.yellow("no backups found, skipping changelog generation"));const t=e.filter(e=>e.isFile()&&e.name.endsWith(".zip"));if(!t.length)return void s.createLogger(a).warn(s.colors.yellow("no ZIP backups found, skipping changelog generation"));const o=t.reduce((e,t)=>y.statSync(w.resolve(i,e.name)).mtimeMs>y.statSync(w.resolve(i,t.name)).mtimeMs?e:t).name;l=w.resolve(i,o)}const c=new I({oldAssetsPath:l,newAssetsPath:n,destinationPath:r});await c.generateChangelog()}let V=global.__pp_dev_profile_session,H=0;const z=e=>{if(V)return new Promise((t,o)=>{V.post("Profiler.stop",(n,{profile:i})=>{if(n)o(n);else{const o=w.resolve(`./pp-dev-profile-${H++}.cpuprofile`);y.writeFileSync(o,JSON.stringify(i)),e(s.colors.yellow(`CPU profile written to ${s.colors.white(s.colors.dim(o))}`)),V=void 0,t()}})})},U=e=>{for(const[t,o]of Object.entries(e))Array.isArray(o)&&(e[t]=o[o.length-1])};function W(e){const t={...e};return delete t["--"],delete t.c,delete t.config,delete t.base,delete t.l,delete t.logLevel,delete t.clearScreen,delete t.d,delete t.debug,delete t.f,delete t.filter,delete t.m,delete t.mode,t}N.option("-c, --config <file>","[string] use specified config file").option("--base <path>","[string] public base path (default: /)").option("-l, --logLevel <level>","[string] info | warn | error | silent").option("--clearScreen","[boolean] allow/disable clear screen when logging").option("-d, --debug [feat]","[string | boolean] show debug logs").option("-f, --filter <filter>","[string] filter debug logs").option("-m, --mode <mode>","[string] set env mode"),N.command("[root]","start dev server").alias("serve").alias("dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action(async(e,t)=>{U(t);let o=null,i=null,r=!1;const c=e?w.resolve(process.cwd(),e):process.cwd(),d=s.createLogger(t.logLevel),p=async()=>{if(!r){r=!0;try{o&&(d.info(s.colors.yellow("🛑 Stopping existing dev server...")),await o.close(),o=null);const{clearConfigCache:f,getConfig:u}=await Promise.resolve().then(()=>require("./index-BcARY73n.js")).then(e=>e.config);f();const{createServer:g}=await(import("vite")),h=t.mode||"development",m=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(h,m);const v=await l.loadConfigFromFile({mode:h,command:"serve"},t.config,e,t.logLevel);let b=await a.getViteConfig(void 0,{mode:h,root:m});if(v){const{plugins:e,...t}=v.config;b=l.mergeConfig(b,t)}if(o=await g(l.mergeConfig(b,{root:e,base:t.base,mode:t.mode,configFile:t.config,logLevel:t.logLevel,clearScreen:t.clearScreen,optimizeDeps:{force:t.force},server:W(t),customLogger:d},!0)),!o.config.base||"/"===o.config.base)throw new Error('base cannot be equal to "/" or empty string');if(!o.httpServer)throw new Error("HTTP server not available");await o.listen();const y=global.__pp_dev_start_time??!1,P=y?s.colors.dim(`ready in ${s.colors.reset(s.colors.bold(Math.ceil(n.performance.now()-y)))} ms`):"";d.info(`\n ${s.colors.green(`${s.colors.bold("PP-DEV")} v${s.VERSION}`)} ${P}\n`),o.printUrls();const S=await u(m);if(!1!==S.inspector?.enabled){const e=o.resolvedUrls?.local[0],t=e?new URL(e).origin:`http://localhost:${o.config.server.port??5173}`;d.info(`\n ${s.colors.cyan("🔍 Request Inspector")} ${s.colors.dim(t+s.INSPECTOR_PATH)}\n`)}!function(e,t){if(!e.httpServer||!process.stdin.isTTY||process.env.CI)return;e._shortcutsOptions=t;const o=s.createLogger();t.print&&o.info(s.colors.dim(s.colors.green(" ➜"))+s.colors.dim(" press ")+s.colors.bold("h")+s.colors.dim(" to show help"));const n=(t.customShortcuts??[]).filter(L).concat(D);k?.(),k=null;let i=!1;const r=process.stdin.isPaused(),a=process.stdin,l=Boolean(a.isRaw),c=async t=>{if(""===t)return void process.kill(process.pid,"SIGINT");if(""===t)return void await e.close().finally(()=>process.exit(0));if(i)return;"h"===t&&o.info(["",s.colors.bold(" Shortcuts"),...n.map(e=>s.colors.dim(" press ")+s.colors.bold(e.key)+s.colors.dim(` to ${e.description}`))].join("\n"));const r=n.find(e=>e.key===t);r&&(i=!0,await r.action(e),i=!1)};process.stdin.setRawMode(!0),process.stdin.on("data",c).setEncoding("utf8").resume();const d=e.httpServer,p=()=>{k===p&&(d.removeListener("close",p),process.stdin.off("data",c),l||process.stdin.setRawMode(!1),r&&process.stdin.pause(),k=null)};k=p,d.on("close",p)}(o,{print:!0,customShortcuts:[...V?[{key:"p",description:"start/stop the profiler",async action(e){if(V)await z(d.info);else{const e=await import("node:inspector").then(e=>e.default);await new Promise(t=>{V=new e.Session,V.connect(),V.post("Profiler.enable",()=>{V?.post("Profiler.start",()=>{d.info("Profiler started"),t()})})})}}}]:[],{key:"l",description:"proxy re-login",action(e){e.ws.send({type:"custom",event:"redirect",data:{url:`/auth/index/logout?proxyRedirect=${encodeURIComponent("/")}`}})}}]}),i||(i=R(c,p,d.info),d.info(s.colors.blue("🔧 Config file watcher started"))),r=!1}catch(e){r=!1,d.error(s.colors.red(`error when starting dev server:\n${e.stack}`),{error:e}),z(d.info),process.exit(1)}}};j({logger:d,shutdown:async()=>{i&&(M(i),i=null),o&&(await o.close(),o=null),z(d.info)}}),await p()}),N.command("next [root]","start Next.js development server with pp-dev integration").alias("next-serve").alias("next-dev").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port",{default:3e3}).option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--cors","[boolean] enable CORS").option("--strictPort","[boolean] exit if specified port is already in use").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").option("--webpack","[boolean] use Webpack for Next dev (use when Turbopack/native SWC is unavailable)").option("--turbopack","[boolean] use Turbopack for Next dev when native bindings work").action(async(e,t)=>{U(t);let n=null,i=null,r=null,l=null,d=!1;const p=new Set,f=s.createLogger(),u=function(e=["uncaughtException"],t=process){const o=e=>t.listeners(e);let n=null,i=null;return{beforeCreate(){n=new Map(e.map(e=>[e,new Set(o(e))]))},afterCreate(){if(!n)return 0;const r=n,s=new Map(e.map(e=>[e,o(e).filter(t=>!r.get(e).has(t))]));let a=0;if(i)for(const[e,o]of i){const n=new Set(s.get(e).map(e=>e.toString()));for(const i of o)n.has(i.toString())&&(t.off(e,i),a+=1)}return i=s,n=null,a}}}(),g=async()=>{n&&"function"==typeof n.close&&await n.close(),n=null},h=async()=>{const e=i;if(e){for(const e of p)e.destroy();p.clear(),await new Promise(t=>{e.close(()=>t())}),i===e&&(i=null)}},m=async()=>{if(!d){d=!0;try{const{next:b,constants:P}=await a.safeNextImport(),{PHASE_DEVELOPMENT_SERVER:S}=P;r&&(await r.close(),r=null),i&&(f.info(s.colors.yellow("🛑 Stopping existing Next.js server...")),await h()),await g();const{clearConfigCache:x}=await Promise.resolve().then(()=>require("./index-BcARY73n.js")).then(e=>e.config);x();const{join:E,basename:T}=await(import("path")),{createServer:L}=await(import("http")),k=await(import("next/dist/server/config.js")),D=k.default.default||k["module.exports"].default||k.default,F=W(t),I=e?E(process.cwd(),e):process.cwd();a.loadPPDevEnv(t.mode||"development",I),f.info(I);const _=await D(S,I);let C=_?.ppDev||{};if(0===Object.keys(C).length)try{const{getConfig:e}=await Promise.resolve().then(()=>require("./index-BcARY73n.js")).then(e=>e.config),t=await e(I);Object.keys(t).length>0?(C=t,f.info(s.colors.blue("🔧 Loaded pp-dev config from standalone config file"))):f.info(s.colors.yellow("⚠️ No pp-dev config found in Next.js config or standalone file, using defaults"))}catch(e){f.info(s.colors.yellow("⚠️ Failed to load standalone pp-dev config, using defaults")),console.debug("Error loading standalone config:",e)}else f.info(s.colors.blue("🔧 Loaded pp-dev config from Next.js config"));let j=null;try{const{getPkg:e}=await Promise.resolve().then(()=>require("./index-BcARY73n.js")).then(e=>e.config);j=e(I).name}catch{j=T(I)}s.validatePPDevConfig(C,j??"");const A=s.normalizePPDevConfig(C,j??""),N=A.backendBaseURL??"http://localhost:8080",M=A.templateLess,O=A.v7Features,V=A.disableSSLValidation,H=A.enableProxyCache,z=A.proxyCacheTTL,U=A.personalAccessToken,B=A.miHudLess,Z=A.inspectorEnabled,G=A.inspectorMaxMemory,J=A.inspectorCaptureLimit,X=A.appId??(process.env.MI_APP_ID&&parseInt(process.env.MI_APP_ID,10)||void 0)??(process.env.MI_PORTAL_PAGE_ID&&parseInt(process.env.MI_PORTAL_PAGE_ID,10)||void 0)??1,K=_?.basePath;let Y="";K?Y=K:(Y=M?s.PATH_PAGE_PREFIX:O?s.PATH_TEMPLATE_LOCAL_PREFIX:s.PATH_TEMPLATE_PREFIX,Y+=`/${j}`);const Q=function(e){const t="1"===process.env.PP_DEV_NEXT_WEBPACK||"true"===process.env.PP_DEV_NEXT_WEBPACK;if(t&&(e.webpack||e.turbopack))throw new Error("Do not combine PP_DEV_NEXT_WEBPACK with --webpack or --turbopack");if(t)return{webpack:!0};if(e.webpack&&e.turbopack)throw new Error("Use only one of --webpack or --turbopack");return e.webpack?{webpack:!0}:e.turbopack?{turbopack:!0}:{}}(t),ee=async e=>{delete process.env.TURBOPACK,await g();const t={dev:!0,customServer:!0,hostname:F.host||"localhost",port:F.port,dir:I,conf:{..._,basePath:Y,assetPrefix:Y}};e.webpack?t.webpack=!0:e.turbopack&&(t.turbopack=!0),u.beforeCreate(),n=b(t),await n.prepare(),u.afterCreate()};if(Q.webpack)await ee({webpack:!0});else if(Q.turbopack)try{await ee({turbopack:!0})}catch(e){if(!q(e))throw e;f.warn(s.colors.yellow("⚠ Turbopack is unavailable (native bindings). Falling back to Webpack.")),await ee({webpack:!0})}else try{await ee({})}catch(e){if(!q(e))throw e;f.warn(s.colors.yellow("⚠ Turbopack cannot run (native Next.js bindings unavailable). Falling back to Webpack.")),await ee({webpack:!0})}if(!n)throw new Error("Next.js app failed to initialize");if(Y.endsWith("/")||(Y+="/"),"/"===Y)throw new Error('basePath cannot be equal to "/" or equal to empty string');f.info(s.colors.green("✅ Next.js app prepared successfully")),f.info(s.colors.blue(`🔧 pp-dev plugin configured for template: ${j}`)),f.info(s.colors.blue(`🔧 Base path configured: ${Y}`)),N&&(f.info(s.colors.blue(`🌐 Backend URL: ${N}`)),f.info(s.colors.blue(`🆔 Custom App ID: ${X}`)));const te=n.getRequestHandler(),oe="number"==typeof F.port?F.port:3e3,ne="string"==typeof F.host?F.host||"0.0.0.0":"localhost";i=L(async(e,t)=>{try{const o=e.url||"/",n=o.split("?")[0];let i=c.parse(o,!0);if(re.length>0){if(n.startsWith("/_next/")||"/favicon.ico"===n||n.startsWith("/__nextjs_")){if(se.length>0){let l=0;const d=()=>{if(l>=se.length)return void r();const o=se[l];l++,o(e,t,d)};return void d()}return void r()}let s=0;const a=()=>{if(s>=re.length)return void r();const o=re[s];s++,o(e,t,a)};return void a()}async function r(){if(n.startsWith(Y))i=c.parse(o,!0);else{if(n===Y.replace(/\/$/,"")){const e=o.replace(n,Y);return t.writeHead(302,{Location:e}),void t.end()}if(n.startsWith("/_next/")||"/favicon.ico"===n||n.startsWith("/__nextjs_"));else if("/"===n)return t.writeHead(302,{Location:Y}),void t.end()}await te(e,t,i)}r()}catch(p){f.error(`Error handling request: ${p instanceof Error?p.message:String(p)}`,{error:p instanceof Error?p:void 0}),t.statusCode=500,t.end("Internal Server Error")}});let ie=null,re=[],se=[];if(!1!==Z){const e=new s.RequestStore(G);s.registerInspectorRoutes(s.internalServer,e,J);const t=s.createRequestCaptureMiddleware(e,J);re.push(t)}if(N){const e=new URL(N).host,t=s.createUserHostGuard();se.unshift(t),re.unshift(t),N.startsWith("https://")&&(o.EventEmitter.defaultMaxListeners=Math.max(o.EventEmitter.defaultMaxListeners,20));const l={headers:{host:e,referer:N,origin:N.replace(/^(https?:\/\/)([^/]+)(\/.*)?$/i,"$1$2")},appId:X,templateLess:M,disableSSLValidation:V,v7Features:O,personalAccessToken:U??process.env.MI_ACCESS_TOKEN};ie=new s.MiAPI(N,l);const c=s.initPPRedirect(Y,j??void 0),d=(e,t,o)=>{c(e,t,o)};se.push(d),re.push(d);const p=a.createDevPanelAssetMiddleware(Y);if(se.push(p),re.push(p),H){let e=+z;(!e||Number.isNaN(e)||e<0)&&(e=6e5);const t={devServer:{middlewares:{use:e=>e},config:{logger:console}},ttl:e},o=s.initProxyCache(t),n=(e,t,n)=>{o(e,t,n)};re.push(n),f.info(s.colors.blue(`🔧 Proxy cache middleware added with TTL: ${e}ms`))}const u=new RegExp(`^((${v=Y,v.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})|/)$`),g=s.initLoadPPData(u,ie,Object.assign({base:Y},l,{miHudLess:B})),h=(e,t,o)=>{g(e,t,o)};re.push(h);const m=Y.endsWith("/")?Y.substring(0,Y.length-1):Y,b={middlewares:{use:e=>e},config:{logger:console}},S=s.initProxy({devServer:b,baseURL:N,proxyIgnore:["/@vite","/@metricinsights","/@",m,"/_next","/favicon.ico","/__nextjs_","/installHook.js.map"],disableSSLValidation:V,miAPI:ie,templateName:j??void 0}),x=(e,t,o)=>{S(e,t,o)};re.push(x);const E=s.internalServer,L=(e,t,o)=>{if(e.url?.startsWith("/@api/")||e.url?.startsWith(s.INSPECTOR_PATH)||e.url?.startsWith(s.VARIABLES_EDITOR_PATH)){return void E(e,t,()=>{})}o()};se.push(L),re.push(L);const k=s.initRewriteResponse(e=>{const t=e.split("?")[0];return t.startsWith(Y)&&!t.includes("/_next/")},(t,o)=>{const n=ie.buildPage(t,B),i=a.injectDevPanel(n,Y,{backendBaseURL:N,templateLess:M,appId:X,devPanelPosition:A.devPanelPosition,devPanelHidden:A.devPanelHidden,devPanelAutoHide:A.devPanelAutoHide});return Buffer.from(s.urlReplacer(e,o.headers.host??"",i))}),F=(e,t,o)=>{k(e,t,o)};re.push(F),r=new $;let C=_?.distDir;try{process.env[s.PP_DEV_NEXT_BUILD_ENV_VAR]="1";const e=await D(P.PHASE_PRODUCTION_BUILD,I);C=e?.distDir??C}catch{}const R=(C??"").replace(/\\/g,"/").replace(/\/+$/,"").replace(/\/dev$/,""),q=R&&".next"!==R?R:"out";let W,Z="0.0.0";try{const e=JSON.parse(y.readFileSync(w.join(I,"package.json"),"utf-8"));Z="string"==typeof e.version?e.version:Z,W="string"==typeof e.repository?e.repository:e.repository?.url}catch{}const G=new s.DistService(j??T(I),{root:I,backupFolder:w.resolve(I,A.syncBackupsDir),maxBackups:A.syncMaxBackups,nextBuild:{projectRoot:I,distDir:q,packageVersion:Z,packageRepositoryUrl:W}}),J={ws:r.ws,config:{clientInjectionPlugin:{v7Features:O}}};new s.ClientService(J,{distService:G,miAPI:ie}),s.registerVariablesEditorRoutes(s.internalServer,{distService:G,miAPI:ie}),s.registerUserRoutes(s.internalServer,{miAPI:ie}),s.startKeepingUsers({persist:A.persistUsers,miAPI:ie,projectRoot:I,miUrl:N});const K="function"==typeof n?.getUpgradeHandler?n.getUpgradeHandler():null;i.on("upgrade",(e,t,o)=>{r?.handleUpgrade(e,t,o)||(K?K(e,t,o):t.destroy())}),f.info(s.colors.blue(`🔧 ${re.length} pp-dev middlewares initialized`)),f.info(s.colors.blue(`🔧 ${se.length} essential middlewares for internal routes`)),f.info(s.colors.blue(`🔧 MiAPI initialized for backend: ${N}`)),f.info(s.colors.blue(`🔧 Custom App ID: ${X}`))}i.listen(oe,ne,()=>{f.info(s.colors.green(`✅ pp-dev Next.js server running at http://${ne}:${oe}`)),f.info(s.colors.blue(`📱 Next.js app accessible at http://${ne}:${oe}${Y}`)),!1!==Z&&f.info(s.colors.cyan(`🔍 Request Inspector: http://${ne}:${oe}${s.INSPECTOR_PATH}`)),f.info(s.colors.blue("🔧 Base path handling active")),l||(l=R(I,m,f.info),f.info(s.colors.blue("🔧 Config file watcher started"))),i.on("connection",e=>{p.add(e),e.on("close",()=>p.delete(e))})}),d=!1}catch(e){d=!1,f.error(s.colors.red(`❌ Failed to start Next.js server: ${e?.message}. Stack: ${e?.stack}`)),e instanceof Error&&e.message.includes("Next.js is required")&&(f.error(s.colors.red("❌ Next.js Peer Dependency Error:")),f.error(s.colors.red(e.message)),f.error(s.colors.yellow("\n💡 To fix this issue:")),f.error(s.colors.blue(" 1. Install Next.js in your project:")),f.error(s.colors.white(" npm install next@^16")),f.error(s.colors.blue(" 2. Or use yarn:")),f.error(s.colors.white(" yarn add next@^16")),f.error(s.colors.blue(" 3. Or use pnpm:")),f.error(s.colors.white(" pnpm add next@^16")),f.error(s.colors.yellow("\n📖 For more information, see:")),f.error(s.colors.blue(" https://nextjs.org/docs/getting-started"))),process.exit(1)}var v}};j({logger:f,knownRejections:[A],shutdown:async()=>{l&&(M(l),l=null),r&&(await r.close(),r=null),await h(),await g()}}),await m()}),N.command("build [root]","build for production").option("--target <target>","[string] transpile target (default: 'modules')").option("--outDir <dir>","[string] output directory (default: dist)").option("--assetsDir <dir>","[string] directory under outDir to place assets in (default: assets)").option("--assetsInlineLimit <number>","[number] static asset base64 inline threshold in bytes (default: 4096)").option("--ssr [entry]","[string] build specified entry for server-side rendering").option("--sourcemap [output]",'[boolean | "inline" | "hidden"] output source maps for build (default: false)').option("--minify [minifier]",'[boolean | "terser" | "esbuild"] enable/disable minification, or specify minifier to use (default: esbuild)').option("--manifest [name]","[boolean | string] emit build manifest json").option("--ssrManifest [name]","[boolean | string] emit ssr manifest json").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle (experimental)").option("--emptyOutDir","[boolean] force empty outDir when it's outside of root").option("-w, --watch","[boolean] rebuilds when modules have changed on disk").option("--changelog [assetsFile]","[boolean | string] generate changelog between assetsFile and current build (default: false)").option("--distZip","[boolean] pack build output into a ZIP archive; use --no-distZip to disable (default: pp-dev config build.zip, or true). Env: PP_DEV_DIST_ZIP").option("--distZipDir <dir>","[string] override the ZIP output directory (default: 'dist-zip'). Env: PP_DEV_DIST_ZIP_DIR").option("--distZipFilename <filename>","[string] override the ZIP output file name (default: '<app-name>.zip'). Env: PP_DEV_DIST_ZIP_FILENAME").option("--versionManifest","[boolean] emit VERSION-*.json + BUILD-MANIFEST.json; use --no-versionManifest to disable (default: pp-dev config build.versionFile, or true). Env: PP_DEV_VERSION_MANIFEST").option("--versionFileTemplate <template>","[string] override the VERSION file name template (default: 'VERSION-v{packageversion}-{currentDate}.json'). Env: PP_DEV_VERSION_FILE_TEMPLATE").action(async(e,t)=>{U(t);const o=W(t),n=a.resolveBuildCliOverrides(t);try{const i=t.mode||"production",r=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(i,r);const s=await l.loadConfigFromFile({mode:i,command:"build"},t.config,e,t.logLevel);let c=await a.getViteConfig(n,{mode:i,root:r});if(s){const{plugins:e,...t}=s.config;c=l.mergeConfig(c,t)}const d=l.mergeConfig(c,{root:e,base:t.base,mode:t.mode,configFile:t.config,logLevel:t.logLevel,clearScreen:t.clearScreen,optimizeDeps:{force:t.force},build:o},!0);if(await l.build(d),o.changelog){const n=e||process.cwd(),i=d.build?.outDir||"dist";let r="dist-zip";d.ppDevConfig&&(!1===d.ppDevConfig.distZip?r=i:"object"==typeof d.ppDevConfig.distZip&&"string"==typeof d.ppDevConfig.distZip.outDir&&(r=d.ppDevConfig.distZip.outDir)),await O({changelog:o.changelog,executionRoot:n,newAssetsPath:w.resolve(n,i),backupsDirPath:w.resolve(n,d.ppDevConfig?.syncBackupsDir||"backups"),changelogDestinationPath:w.resolve(n,r),logLevel:t.logLevel})}}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error during build:\n${e.stack}`),{error:e}),process.exit(1)}finally{z(e=>s.createLogger(t.logLevel).info(e))}}),N.command("next-build [root]","build a Next.js app for production (`next build`) and emit VERSION/BUILD-MANIFEST/zip in the same format as `pp-dev build`").option("--changelog [assetsFile]","[boolean | string] generate changelog between assetsFile and current build (default: false)").option("--distZip","[boolean] pack build output into a ZIP archive; use --no-distZip to disable (default: pp-dev config build.zip, or true). Env: PP_DEV_DIST_ZIP").option("--distZipDir <dir>","[string] override the ZIP output directory (default: 'dist-zip'). Env: PP_DEV_DIST_ZIP_DIR").option("--distZipFilename <filename>","[string] override the ZIP output file name (default: '<app-name>.zip'). Env: PP_DEV_DIST_ZIP_FILENAME").option("--versionManifest","[boolean] emit VERSION-*.json + BUILD-MANIFEST.json; use --no-versionManifest to disable (default: pp-dev config build.versionFile, or true). Env: PP_DEV_VERSION_MANIFEST").option("--versionFileTemplate <template>","[string] override the VERSION file name template (default: 'VERSION-v{packageversion}-{currentDate}.json'). Env: PP_DEV_VERSION_FILE_TEMPLATE").action(async(e,t)=>{U(t);const o=s.createLogger(t.logLevel),n=e?w.resolve(process.cwd(),e):process.cwd(),i=a.resolveBuildCliOverrides(t);process.env[s.PP_DEV_NEXT_BUILD_ENV_VAR]="1";try{a.loadPPDevEnv(t.mode||"production",n);const{constants:e}=await a.safeNextImport(),r=await(import("next/dist/server/config.js")),l=r.default.default||r["module.exports"].default||r.default,c=await l(e.PHASE_PRODUCTION_BUILD,n);let d,p=c?.ppDev||{};if(0===Object.keys(p).length){const{getConfig:e}=await Promise.resolve().then(()=>require("./index-BcARY73n.js")).then(e=>e.config);p=await e(n)}try{const{getPkg:e}=await Promise.resolve().then(()=>require("./index-BcARY73n.js")).then(e=>e.config);d=e(n).name}catch{d=w.basename(n)}const f=s.normalizePPDevConfig(p,d),u=a.applyDistZipOverride(f.distZip,i,s.createDefaultZipFileName(d)),g=a.applyVersionManifestOverride(f.versionPlugin,i),h=s.removeStaleDevTypes(n,c);h&&o.info(s.colors.dim(`[pp-dev] Removed stale dev route types: ${w.relative(n,h)}`)),o.info(s.colors.cyan("[pp-dev] Running `next build`...")),await s.runNextBuildProcess(n);const m="string"==typeof c?.distDir&&c.distDir?c.distDir:".next",v=".next"===m?"out":m,b=w.resolve(n,v);if(!y.existsSync(b)||!y.statSync(b).isDirectory())throw new Error(`Next.js build output directory not found: ${b}. "next-build" requires "output: 'export'" in next.config (static export).`);const P=JSON.parse(y.readFileSync(w.join(n,"package.json"),"utf-8"));if(!1!==g&&!1!==g.enabled&&(s.writeBuildVersionManifest({outDir:b,packageVersion:"string"==typeof P.version?P.version:"0.0.0",versionFileTemplate:g.versionFileTemplate,packageRepositoryUrl:"string"==typeof P.repository?P.repository:P.repository?.url,enabled:g.enabled}),o.info(s.colors.green(`✅ VERSION / BUILD-MANIFEST written to ${w.relative(n,b)}`))),!1!==u){const e=w.resolve(n,u.outDir),t=u.inDir?w.resolve(b,u.inDir):b,i=s.resolveOutputFilePath(e,u.outFileName,"ZIP output file name");y.mkdirSync(w.dirname(i),{recursive:!0});const r=await s.zipDirectoryToBuffer(t);y.writeFileSync(i,r),o.info(s.colors.green(`✅ Zip archive written to ${w.relative(n,i)}`))}if(t.changelog){const e=!1!==u?u.outDir:v;await O({changelog:t.changelog,executionRoot:n,newAssetsPath:b,backupsDirPath:w.resolve(n,f.syncBackupsDir),changelogDestinationPath:w.resolve(n,e),logLevel:t.logLevel})}}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error during next-build:\n${e.stack}`),{error:e}),process.exit(1)}finally{z(e=>s.createLogger(t.logLevel).info(e))}}),N.command("changelog [oldAssetPath] [newAssetPath]","generate changelog between two assets files/folders").option("--oldAssetsPath <oldAssetsPath>","[string] path to the old assets zip file or folder").option("--newAssetsPath <newAssetsPath>","[string] path to the new assets zip file or folder").option("--destination <destination>","[string] destination folder for the changelog (default: .)").option("--filename <filename>","[string] filename for the changelog (default: CHANGELOG.html)").action(async(e,t,o)=>{U(o);const{oldAssetsPath:n=e,newAssetsPath:i=t,destination:r=".",filename:a="CHANGELOG.html",logLevel:l}=o,c=process.cwd();n&&i||(s.createLogger(l).error(s.colors.red("error during changelog generation: oldAssetPath and newAssetPath are required")),process.exit(1));const d=w.resolve(c,n),p=w.resolve(c,i),f=w.resolve(c,r),u=new I({oldAssetsPath:d,newAssetsPath:p,destinationPath:f,changelogFilename:a});await u.generateChangelog()}),N.command("generate-icon-font [source] [destination]","generate icon font from SVG files").option("--source <source>","[string] path to the source directory with SVG files").option("--destination <destination>","[string] path to the destination directory to save the generated font files").option("--font-name, -n <fontName>","[string] name of the font to generate (default: 'icon-font')").action(async(e,t,o)=>{U(o);const{source:n=e,destination:i=t,fontName:r="icon-font"}=o,a=process.cwd(),l=w.resolve(a,n),c=w.resolve(a,i),d=new _({sourceDir:l,outputDir:c,fontName:r}),p=s.createLogger(o.logLevel);p.info(`Generating icon font from SVG files in ${s.colors.dim(l)}`),await d.generate(),p.info(`Icon font generated and saved to ${s.colors.dim(c)}`)}),N.command("optimize [root]","pre-bundle dependencies").option("--force","[boolean] force the optimizer to ignore the cache and re-bundle").action(async(e,t)=>{U(t);try{const o=t.mode||"production",n=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(o,n);const i=await l.loadConfigFromFile({mode:o,command:"build"},t.config,e,t.logLevel);let r=await a.getViteConfig(void 0,{mode:o,root:n});if(i){const{plugins:e,...t}=i.config;r=l.mergeConfig(r,t)}const s=await l.resolveConfig(l.mergeConfig(r,{root:e,base:t.base,configFile:t.config,logLevel:t.logLevel,mode:t.mode}),"serve");await l.optimizeDeps(s,t.force,!0)}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error when optimizing deps:\n${e.stack}`),{error:e}),process.exit(1)}}),N.command("preview [root]","locally preview production build").option("--host [host]","[string] specify hostname").option("--port <port>","[number] specify port").option("--strictPort","[boolean] exit if specified port is already in use").option("--https","[boolean] use TLS + HTTP/2").option("--open [path]","[boolean | string] open browser on startup").option("--outDir <dir>","[string] output directory (default: dist)").action(async(e,t)=>{U(t);try{const o=t.mode||"production",n=w.resolve(process.cwd(),e??".");a.loadPPDevEnv(o,n);const i=await l.loadConfigFromFile({mode:o,command:"build"},t.config,e,t.logLevel);let r=await a.getViteConfig(void 0,{mode:o,root:n});if(i){const{plugins:e,...t}=i.config;r=l.mergeConfig(r,t)}(await l.preview(l.mergeConfig(r,{root:e,base:t.base,configFile:t.config,logLevel:t.logLevel,mode:t.mode,build:{outDir:t.outDir},preview:{port:t.port,strictPort:t.strictPort,host:t.host,https:t.https,open:t.open}}))).printUrls()}catch(e){s.createLogger(t.logLevel).error(s.colors.red(`error when starting preview server:\n${e.stack}`),{error:e}),process.exit(1)}finally{z(e=>s.createLogger(t.logLevel).info(e))}}),N.command("migrate [config]","migrate pp-dev config from 0.x flat format to 1.0 grouped format").option("--dry-run","[boolean] print migrated config without writing any files").option("--format <format>","[string] output format: ts (default), js, json").option("--output <file>","[string] output file path (default: pp-dev.config.ts)").option("--no-backup","[boolean] skip backup of original config file").action(async(e,t)=>{const o=s.createLogger(t.logLevel),{isLegacyFlatConfig:n,isLegacyPPWatchConfig:i,isAlreadyMigrated:r,migrateLegacyFlatConfig:a,migratePPWatchConfig:l,generateConfigFileContent:c,discoverMigrateSource:d,loadPackageJsonMigrateConfig:p}=await Promise.resolve().then(()=>require("./migrate-CTAwfgnJ.js")),f=t.format??"ts",u=!1!==t.backup,g=process.cwd(),h=d(g,e);h||(o.warn(s.colors.yellow("No pp-dev or pp-watch config file found in the current directory.")),o.info(s.colors.blue('Supported files: pp-dev.config.{ts,js,cjs,mjs,json}, .pp-watch.config.{ts,js,json}, or a "pp-dev" field in package.json')),process.exit(1));const{sourceFile:m,isWatchConfig:v,isPackageJsonConfig:b}=h;o.info(s.colors.blue(`Found config: ${w.relative(g,m)}`));const{getPkg:P}=await Promise.resolve().then(()=>require("./index-BcARY73n.js")).then(e=>e.config),S=P();let x,E={};try{if(/\.[cm]?ts$/i.test(m)){const e=await(import("esbuild")),{pathToFileURL:t}=await(import("url")),o=(await e.build({absWorkingDir:g,entryPoints:[m],outfile:"out.js",write:!1,target:"node24",platform:"node",bundle:!0,packages:"external",format:"esm",mainFields:["main"]})).outputFiles[0].text,n=`pp-migrate-tmp-${Date.now()}.mjs`;y.writeFileSync(n,o);try{const e=await(import(t(w.resolve(g,n)).toString()));E=e.default?.default??e.default??e}finally{y.existsSync(n)&&y.unlinkSync(n)}}else if(/\.[cm]?js$/i.test(m)){const{pathToFileURL:e}=await(import("url")),t=await(import(e(w.resolve(g,m)).toString()));E=t.default?.default??t.default??t}else b?E=p(m):m.endsWith(".json")&&(E=JSON.parse(y.readFileSync(m,"utf-8")))}catch(e){o.error(s.colors.red(`Failed to load config file: ${e.message}`)),process.exit(1)}E&&"object"==typeof E||(o.error(s.colors.red("Config file did not export a valid object.")),process.exit(1)),r(E)?(o.info(s.colors.green("Config is already in 1.0 format — nothing to migrate.")),process.exit(0)):v||i(E)?(o.info(s.colors.blue("Detected pp-watch config format → migrating to 1.0")),x=l(E)):n(E)?(o.info(s.colors.blue("Detected 0.x flat config format → migrating to 1.0")),x=a(E,S.name)):(o.warn(s.colors.yellow("Could not detect config format. No known keys found.")),process.exit(1));const T=c(x,f),L=t.output??w.join(g,`pp-dev.config.${f}`);if(t.dryRun&&(o.info(s.colors.green(`\n--- Migrated config (dry-run) → ${w.relative(g,L)} ---\n`)),process.exit(0)),u&&!b&&y.existsSync(m)){const e=`${m}.bak`;y.copyFileSync(m,e),o.info(s.colors.blue(`Backed up original to: ${w.relative(g,e)}`))}y.writeFileSync(L,T,"utf-8"),o.info(s.colors.green(`✅ Migration complete → ${w.relative(g,L)}`)),b?o.info(s.colors.yellow('You can now remove the "pp-dev" field from package.json.')):m!==L&&y.existsSync(m)&&o.info(s.colors.yellow(`You can now delete the old config: ${w.relative(g,m)}`))}),N.help(),N.version(s.VERSION),N.parse(),exports.stopProfiler=z;
|
|
2
2
|
//# sourceMappingURL=cli.js.map
|