Compare commits

...
Author SHA1 Message Date
Paul Bottein 6573c08f37 Fall back to 5 sections when the custom max sections input is cleared 2026-10-15 17:06:38 +02:00
Paul Bottein dcfde89448 Simplify the max sections form handling 2026-10-15 17:06:27 +02:00
Paul Bottein 3016bbdfa2 Make the max sections setting of sections views easier to understand 2026-10-15 17:06:27 +02:00
Paul Bottein 630d7ff82e Limit the section preview to the view width and reset a cleared width 2026-10-15 17:06:20 +02:00
Paul Bottein 6874781340 Use early returns in the section editor 2026-10-15 15:24:12 +02:00
Paul Bottein be214acfd1 Add a preview and a clearer width setting to the section editor 2026-10-15 15:13:36 +02:00
Aidan TimsonandClaude Opus 5.5 7c74f45e5e Explain when HTTPS or the microphone blocks a feature (#54948)
* Fix Assist microphone not supported message showing [object Object]

The not supported microphone message was built as a Lit TemplateResult,
but chat messages are rendered through ha-markdown which expects a
string, so it was displayed as "[object Object]". Build the message as
markdown instead and narrow the message text type to string.

Fixes #29769

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Jza8VBEqKGoFP35sCcz35H

* Load Assist voice responses from Home Assistant's URL

* Explain when HTTPS or the microphone blocks a feature

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-15 14:42:26 +02:00
Ruslan Sayfutdinov 05848f0df4 Add gap between backup upload percentage and spinner (#54951) 2026-10-15 14:35:57 +03:00
Marcin BauerandClaude Opus 5.5 bfa14296d7 Show a toast instead of a dialog after reloading an integration entry (#54954)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-15 14:28:36 +03:00
renovate[bot] ba3722b983 Update vitest monorepo to v5.0.4 (#54953)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-15 14:27:46 +03:00
Lucas Deutschland cbc3b9dbaf Fix tile zone icons for zones with duplicate names (#54909)
* Fix tile zone icons for zones with duplicate names

* Match tile zone icons to the current tracker state

* Simplify person tile zone lookup
2026-10-15 14:11:06 +03:00
Lucas Deutschland 76f5280b0a Fix map activity for zones with duplicate names (#54908)
* Fix map activity for zones with duplicate names

* Preserve legacy zone icons in person activity

* Simplify map activity zone handling

* Fix map demo history zone membership
2026-10-15 14:10:57 +03:00
Petar Petrov 7123790fed Fix number selector validation on blur (#54944) 2026-10-15 11:03:10 +02:00
Petar Petrov ebfc19eff1 Fix validate-on-blur in the change password card and enter code dialog (#54945)
Fix auto-validate on the change password and enter code inputs
2026-10-15 11:02:21 +02:00
Petar Petrov 80b515fb77 Use contexts in small standalone components (#54943) 2026-10-15 10:59:52 +02:00
Aidan Timson 73200e7dc6 Use image select boxes for buttons or slider feature styles (#54947) 2026-10-15 10:59:19 +02:00
Petar Petrov 067aa09222 Use contexts in the add-on, config entry and service pickers (#54942) 2026-10-15 09:21:00 +02:00
Paulus SchoutsenandClaude Opus 5.5 c24f4d29a9 Add dialog to delete statistics in a time range (#54875)
* Add dialog to delete statistics in a time range

A bad measurement ruins the graphs of a statistic. Mean statistics
cannot be adjusted, so the only fix was to delete the complete
statistic. A new action in the statistics table opens a dialog to pick
a time range. The dialog previews the statistics in the range and
deletes them with the recorder/clear_statistics_range command.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

* Use recorder/clear_statistics with a time range

The backend adds the optional time range to recorder/clear_statistics
instead of a separate command.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

* Preview the full first period when clearing a statistics range

The recorder also deletes the statistics period in which the range
starts. The preview started at the exact start time, so it did not show
that period. Start the preview at the beginning of the period.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

* Fall back to hourly statistics in the clear range preview

The recorder purges the 5-minute statistics before the hourly
statistics. For an older short range, the preview showed "No statistics
found" and disabled Delete, although hourly statistics existed. Show the
hourly statistics when no 5-minute statistics are found.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

---------

Co-authored-by: Claude <[email protected]>
2026-10-15 09:17:31 +02:00
Petar Petrov 7597b5ce77 Reject invalid static prices in the energy source dialogs (#54940)
Block saving an invalid static energy price
2026-10-15 08:48:14 +02:00
Aidan TimsonandAlexander Schieweck a491966068 Add buttons or slider style to target temperature card feature (#54923)
* Add buttons or slider style to target temperature card feature

* Always disable the target temperature fallback slider

---------

Co-authored-by: Alexander Schieweck <[email protected]>
2026-10-15 09:06:08 +03:00
Balloob Bot ff76e4e1a0 Add default decision entity preferences to AI Task settings (#54728) 2026-10-15 07:23:54 +02:00
Elias Lecomte 2ad2c38a41 Prevent stale Energy refreshes from changing the selected period (#54741)
* Prevent stale Energy refreshes from overwriting the selected period

* Preserve Energy data when reapplying the current selection

* Handle Energy subscription refresh failures

* Refresh invalidated Energy selections on resubscribe

* Use checked Energy collection construction and a typed cache

* Restore Energy collection access on the connection

* Retain Energy preferences when the selected period changes
2026-10-15 08:16:29 +03:00
Paul Bottein 4277060d6c Hide divider above the first section row of an entities card (#54929) 2026-10-15 07:00:30 +02:00
renovate[bot] 284691592e Update dependency @vvo/tzdb to v6.201.1 (#54938)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-15 06:56:08 +02:00
renovate[bot] 736d1f4dec Update dependency maplibre-gl to v6.14.0 (#54928)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-14 15:52:01 +00:00
Petar Petrov 6a0a5fb2ef Reduce stale period for pull requests to 60 days (#54926)
* Reduce stale period to 60 days

* Only reduce stale period for pull requests
2026-10-14 17:39:11 +02:00
Marco HillgerandSeoFood a2ad5c4b14 Guard script field descriptions against non-string YAML values (#54924)
A field description of 123 saved through the config API or YAML reaches the editor as a number, and description?.trim() threw while rendering the field row and its sidebar. Reuse getRowNote, like the automation row notes.

Co-authored-by: SeoFood <[email protected]>
2026-10-14 18:01:02 +03:00
Aidan TimsonandCopilot Autofix powered by AI 95afebf538 Explain debug logging banner and make disable the main action (#54922)
* Explain debug logging banner and make disable the main action

* Improve debug logging description clarity

Updated the description for debug logging to clarify log file download availability.

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-10-14 17:56:47 +03:00
Aidan TimsonandClaude Opus 5.5 07f7bd91de Keep data table search, sorting and grouping in the URL, starting with the Marketplace (#54912)
* Add opt-in URL sync for data table search, sorting and grouping

Adds a shared query params controller and lets hass-tabs-subpage-data-table
keep its search, sorting and grouping in the URL (`search`, `sort`,
`direction`, `group`) when a page sets `sync-url`. Writes replace the current
history entry, search writes are debounced, and empty or default values are
left out. Params in the URL win over stored preferences; a link without table
params keeps what was picked before. Columns can give a short public name
(`urlName`) for the URL, grouping is only written for columns that have one.

No page opts in yet, so behaviour is unchanged.

Part of #54788

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Re1ptLgqtYo2EKj8FezHCp

* Keep links and searches intact in data table URL sync

- Read the URL once the table is opted in and has its columns, and only
  write after that, so a link isn't overwritten when sync is turned on or
  columns arrive after the first render
- Write a pending search as soon as the search field loses focus, so a
  dialog opened right after typing doesn't pick up the write and Back
  doesn't bring an older search back
- Keep other query params exactly as they are written instead of
  re-encoding them
- Note that a column's URL name must not match another sortable column id

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Re1ptLgqtYo2EKj8FezHCp

* Move the Marketplace tables onto the shared URL sync

* Shorten the urlName comment to one line

* Keep statuses picked on another Marketplace tab when applying a link

* Drop the rendering check from the Marketplace link test

* Cancel pending URL writes on navigation

* Write data table URL after update and reset typed search

* Track the host's first update in the URL params controller

* Add tests for the URL params controller

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 17:54:41 +03:00
Marco HillgerandSeoFood 9ca8f2e98b Use light color scheme for themes with a light mode (#54898)
* Use light color scheme for themes with an explicit light mode

* Only force the light scheme when a theme defines a light mode

---------

Co-authored-by: SeoFood <[email protected]>
2026-10-14 16:11:32 +02:00
Wendelin 04f46f037d Use ha-section-title for the picker sticky title and share its logic (#54916)
* Refactor section title handling in picker components and add utility function

- Removed unused sectionTitleFunction properties from ha-generic-picker and ha-picker-combo-box.
- Implemented findSectionTitle utility function to determine section titles based on visible items.
- Updated ha-picker-combo-box to use findSectionTitle for section title management.
- Cleaned up related code in ha-target-picker and ha-automation-add-search to enhance readability and maintainability.
- Added tests for findSectionTitle to ensure correct functionality.

* review
2026-10-14 14:41:54 +01:00
a9b25a3180 Guard automation row notes against non-string YAML values (#54911)
* Guard automation row notes against non-string YAML values

A note set in YAML is not guaranteed to be a string (e.g. `note: 123`),
so calling `note?.trim()` in the trigger, condition, action and option
rows and sidebars could throw while rendering. Add a `getRowNote` helper
that only trims string notes and use it everywhere notes are shown.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01W88iUfrBdggmpdR4NUHXUk

* Remove getRowNote comment

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01W88iUfrBdggmpdR4NUHXUk

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-14 13:27:10 +00:00
4b18f1233e Use rounded squares for avatars and entity pictures (#54902)
* Use rounded squares for avatars everywhere

The map draws person and device avatars as rounded squares, while the
user and person badges in the sidebar, people list, profile, pickers
and editors, the picture previews and the badge card's entity picture
were still circles. They now share one --ha-avatar-border-radius
token, defaulting to the large radius the map already used, so themes
have a single knob and the map markers follow the same token. The
large picture previews take the extra-large radius to keep the same
proportion.

* Use shared picture radius across entity images

Apply the theme radius to state badges, picture previews, and the crop overlay while keeping state-badge-specific overrides.

Co-authored-by: Copilot <[email protected]>

* Keep the small radius for media artwork

Media player and camera badges share the has-media-image class; the 8% fallback was replaced by the picture radius, contradicting the PR description.

* Give camera pictures the shared picture radius

Cameras were grouped with media players and kept the small artwork radius; only media artwork keeps it.

* Use a small picture radius for related item thumbnails

The shared 12px picture radius collapses to a circle on the 20px
related item pictures, so add a themeable small variant that keeps
visible straight edges at that size.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Claude Fable 5.1 <[email protected]>
2026-10-14 14:26:54 +01:00
Joakim PlateandClaude Opus 5.5 424068c4ca Fix media control card cut off for off players without turn on (#54904)
Players that are off with an assumed state but no TURN_ON support are
treated as unavailable, so the controls are not rendered. The controls
were still computed though, which dropped the no-controls class and
removed the bottom padding, clipping the card.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 15:15:00 +02:00
Erwin DounaandLucas Deutschland a6f4ab4a7a Add live log dialog to integration page (#54809)
* Add live log dialog to integration page

* Move live log button into the debug banner

* Limit retained integration live log lines to 5000

* Add filters and pause to the live log dialog

* Make integration live log retention configurable

* Align live log line limit input with toolbar controls

* Resubscribe live log after reconnect and use DialogMixin

* Keep reading position while searching live log

* Only show live log unsupported for unknown command

* Simplify the live log dialog

* Handle live log review feedback

* Apply live log review suggestions

---------

Co-authored-by: Lucas Deutschland <[email protected]>
2026-10-14 15:06:17 +02:00
Maarten Lakerveld cfde8cd14b Stop the user condition editor from duplicating selected users (#54921)
When the users finish loading, the list picks up the pre-selected items and
fires a selected event for them. The handler appended that user again on
every open of the editor, so a single user condition grew one duplicate id
per edit. Ignore selection events that do not change the configured users.

Fixes #54894
2026-10-14 15:02:38 +02:00
Paul Bottein 921ac4998a Show the color feature for light group members in color mode (#54918)
* Show the color feature for light group members in color mode

* Show hue and saturation for light group members

* Show only hue for light group members
2026-10-14 15:00:30 +02:00
Petar Petrov a0c7c36403 Follow up on choose option YAML editing (#54900)
* Follow up on choose option YAML editing

Make action and trigger migration safe for malformed YAML, drop the
option-specific sequence migration, type the option sidebar save value
as unknown and wire option YAML mode through the sidebar like the
other sidebars.

* Guard malformed trigger options during migration
2026-10-14 14:55:24 +02:00
WendelinandClaude Opus 5.5 21670e5ae6 Prevent iOS Safari text inflation on landscape rotation (#54914)
* Prevent iOS Safari text inflation on landscape rotation

Fixes #53060

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CPRiV8TCjj8Z4SX9jX9578

* also add the fix for gallery and demo

---------

Co-authored-by: Claude <[email protected]>
2026-10-14 15:53:15 +03:00
Paul Bottein 76e353b36b Fix hue scrubber zoom for features sharing the card width (#54917) 2026-10-14 15:49:44 +03:00
Aidan TimsonandClaude Opus 5.5 ddb33f7d12 Add accessible names to icon-only badges and interactive tile icons (#54907)
* Add accessible names to icon-only badges and interactive tile icons

ha-badge and ha-tile-icon could render a focusable button with no
accessible name. Add an accessibleLabel property to both, set as
aria-label on the button element (for ha-badge only in icon-only mode,
so visible text still names the button), and pass the entity or
shortcut name from the entity badge, shortcut badge, tile card and
toggle group card.

Fixes #54890

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018ysguoFdwq848WzsuFHkSn

* Name shortcut badges without an action label and document accessibleLabel

Fall back to the localized shortcut badge name when the shortcut has no
action-derived label, such as hold-only or double-tap-only badges, and
add accessibleLabel to the ha-badge gallery API table.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018ysguoFdwq848WzsuFHkSn

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 14:49:41 +02:00
Maarten LakerveldandClaude Fable 5.1 85ca758060 Draw the onboarding home marker like the home zone (#54903)
* Show a home icon for the location marker in onboarding

The onboarding location step passed no icon for its marker. On Leaflet that
fell back to the stock pin; since the MapLibre engine it is a bare dot, the
same element that marks a zone's draggable center. Use the home icon for the
editable marker, both before a search and for the highlighted search result,
so the step shows what the marker stands for.

* Draw the onboarding home marker like the home zone on a map

The location step showed a bare home icon, while the map card draws the
home zone as a colored circle with the icon. Let a point marker in the
locations editor opt into that zone marker, and use it in onboarding
with the home zone's color for the editable marker and the highlighted
search result, so the step shows the same marker the user will see later.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* Make the home marker color a memoization input

The memoized locations read the primary color implicitly, so a theme change left a stale radius color. Resolve the color in render and pass it in.

---------

Co-authored-by: Claude Fable 5.1 <[email protected]>
2026-10-14 14:42:55 +02:00
Paul Bottein 8401541c87 Fade light color features when the light is off (#54913)
* Fade light color features when the light is off

* Keep light color features faded while focused

* Show a neutral saturation gradient when the hue is unknown
2026-10-14 14:30:13 +02:00
JonathanandXyolyp 2b1b58d482 Link each run in the activity details to its own trace (#54592)
* Link each run in the activity details to its own trace

An automation and the scripts it calls share one context, and the trace contexts the logbook loads keep only one run per context, so every "View trace" link of such a chain opened the same trace. Core now names the run of a run row in its logbook entry: link that run, and keep the link by context for entries recorded before.

* Only link runs with trace contexts

Trace contexts are only loaded for admins and only hold stored traces.
Keep them as the condition for the link, so non-admins get no link to a
trace page they cannot open.

* Use getTraceUrl for the run trace link

---------

Co-authored-by: Xyolyp <[email protected]>
2026-10-14 12:01:42 +02:00
Paul Bottein 374864fcc1 Expand badge shorthand and drop empty entries when loading a dashboard (#54651)
* Expand badge shorthand and drop empty entries when loading a dashboard

* Normalize the generated config when saving a strategy dashboard
2026-10-14 11:58:19 +03:00
oneseventhreeandWendelin 1bcda9fb80 Add Edit in YAML for choose options in the automation editor (#53327)
* Add Edit in YAML for choose options in the automation editor

* Refactor automation sidebar option handling and validation logic

* copilot review

* fix copilot and regression

* Enhance note display logic in automation sidebar option

* copilot fix

* Add sidebarKey property to ha-automation-sidebar-option and update rendering logic

---------

Co-authored-by: Wendelin <[email protected]>
2026-10-14 11:50:04 +03:00
Jan Bouwhuis dca32d7065 Use unit of measurement selector and add device class to input number helper (#54785) 2026-10-14 08:43:55 +00:00
Paul Bottein cfc5add6cf Use the entity name formatter for all entity names (#54891)
* Use the entity name formatter for all entity names

* Guard entity completions until contexts are loaded
2026-10-14 11:36:43 +03:00
Aidan Timson ae6241859f Run tile card icon hold and double tap actions when icon tap is none (#54889) 2026-10-14 10:16:58 +02:00
Muhammad UmairandWendelin 4c190f806d Lower description search weight in automation add-element search (#53751)
* Lower description search weight in automation add-element search

* remove comment

---------

Co-authored-by: Wendelin <[email protected]>
2026-10-14 09:00:18 +03:00
charishma2k06andWendelin 6e698f8c7c Fix todo item input clearing (#54318)
* Fix todo item input clearing

* review

---------

Co-authored-by: Wendelin <[email protected]>
2026-10-14 08:59:33 +03:00
Paul Bottein 63708e9cba Add settings button to AI task entity pickers (#54886)
* Add settings button to AI task entity pickers

* Fix clearing AI task pickers and label settings buttons
2026-10-13 21:23:33 -04:00
Eric Lorenzo Benjamin Jr. f1763068e0 Treat contenteditable elements as text input for keyboard shortcuts (#53491)
canOverrideAlphanumericInput exempts textarea and the text-entry input types,
but has no branch for contenteditable, so an element the user is actively
typing into is still treated as fair game for global shortcuts. For an admin
that means a, c, d, e and m fire in the middle of a word.

The rest of the codebase already treats contenteditable as a typing surface
when it makes this decision, in ha-list-base and in the integrations
dashboard, and the HA-CODE-EDITOR tag name check in this same function is
that omission handled narrowly for CodeMirror, which is contenteditable
itself. Add the general check.

The HA-CODE-EDITOR entry is left in place. It is redundant in the common case
but it matches on the whole composed path rather than the event target, and
narrowing that belongs in its own change.

Adds tests for this function, which had none.
2026-10-13 14:10:59 +00:00
Aidan Timson 2c5970304a Use contexts in state-display (#54883)
* Use contexts in state-display

* Rename computeUpdateStateDisplay hass argument to options
2026-10-13 14:51:57 +01:00
WendelinandClaude Opus 5.5 eef2ad91cd Keep pending target temperature when entity state updates (#54854)
* Keep pending target temperature when entity state updates

Thermostat and water heater +/- taps were lost when the entity updated
during the 1 second debounce: willUpdate copied the entity's setpoint
over the value the user was still adjusting, so the debounced
set_temperature call sent the old value. This commonly happens when the
state update confirming the previous call arrives right after a new tap.

Add PendingValueSync, which skips copying entity state while a change is
scheduled or its service call is in flight, and resyncs from the latest
state once nothing is pending if an update was skipped or the call
failed. Use it in the target temperature card feature and the climate
and water heater more-info controls.

The single-setpoint buttons in the card feature now also display the
pending value instead of the entity attribute.

Fixes #54832

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NecjfzKMkYK4LPY3yxnXgu

* Keep pending target humidity when entity state updates

Apply PendingValueSync to the climate and humidifier humidity controls
and the target humidity card feature, which had the same race as the
temperature controls. The card feature calls the service on every tap,
so state updates from an earlier tap could reset the value before the
next one. It now also displays the pending value.

Always sync from state when the control switches to another entity, so
a pending value is never shown for or sent to a different entity. This
matters because more-info and card features reuse the control element.

When the slider commits a value, cancel any queued button call so it
does not clear the pending state too early.

Don't rethrow failed service calls: callService already shows a toast,
and the control resyncs from the entity state.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Implement cancel method in PendingValueSync and update entity state handling in climate controls

* review

* reduce helpers

---------

Co-authored-by: Claude <[email protected]>
2026-10-13 16:26:44 +03:00
f6a9b8e8a0 Location visibility condition: match zones by target - entity, label (#54679)
* Match zones by label in the location visibility condition

Add `target` (zones, or zones with a label) and `away` options to the
location visibility condition. `target` is matched against the person's
`in_zones` attribute, so overlapping zones match too. Existing `locations`
configs keep working and can be converted from the editor.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Make resolveLocationZones a private helper

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Cache resolved location zones, validate target, add tests

- Cache resolved zones per target and refresh them only when the entity,
  device or area registry changes, instead of scanning on every update.
- Validate `target` with the shared targetStruct.
- Match the existing helper text wording.
- Add tests for validation, area targets, cache refresh, and the editor's
  value handling and conversion.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Change button size from 'small' to 's'

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Fix button size attribute in ha-card-condition-location

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Validate location target and away shape, keep mixed fields in editor

- Reject a `target` that isn't a mapping and a non-boolean `away` in the
  location validator; evaluation ignores them instead of throwing.
- Keep `target` and `away` when editing a legacy condition, and merge
  into them when converting, so hand-written mixed configs aren't lost.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Migrate legacy location conditions when the editor opens

Replace the Convert button with automatic migration, following the
existing pattern for deprecated options. A warning alert explains that
the condition now matches any zone the person is in. Zone names that
match no zone are kept and shown as not found instead of being dropped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Show legacy location conditions migrated, keep same-named zones

Migrate for display only, like toCoreEditorCondition: the new format is
written once the condition is edited, so opening a card doesn't create
unsaved changes. Zone names aren't unique, so migrate a name to every
zone that has it, as the old condition matched all of them. Mention the
in_zones attribute in the alert.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Don't reuse an existing zone ID for a missing zone name

A renamed zone keeps its old ID, so slugifying a name that matches no
zone could select a zone the condition never matched. Add _2, _3 and so
on until the ID is unused, like the script editor and core do for new
entity IDs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Keep missing location names that slugify the same apart

Two names that match no zone but slugify to the same ID got the same
generated ID and collapsed into one. Reserve generated IDs while
migrating, and skip repeated names so they don't get a second one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Validate location target IDs, not just that target is a mapping

A target like {entity_id: 5} passed validation and threw while
resolving zones. The entity filter card, entity filter badge and map
card evaluate conditions without catching errors. Check target keys and
ID types the way targetStruct does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Keep other keys when editing a location condition

Spread the existing condition like the other condition editors, so
keys such as alias aren't dropped. Migrate legacy conditions when the
condition changes instead of on every state update.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Describe Away as the person being away, including passive zones

away matches the not_home state, which passive zones don't change, so
a person only in passive zones is away even though in_zones lists them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Pick up zone changes in the location editor, clarify texts

Redo the legacy migration when states change, so a zone renamed while
the editor is open isn't saved under a stale ID. Keep the same data
object when nothing changed. Drop backticks from the alert, which is
plain text, and mention areas and floors in the Zones helper.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Potential fix for pull request finding 'Add the required Oxford comma'

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Keep zones named home or not_home when migrating

A zone can be named home or not_home, and the old condition matched a
person in it as well, so collect zones by name for those values too.
Describe away as the not_home state in code comments.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Handle zones without a state in location resolving and migration

Resolving skips entities without a state, so a labeled zone evaluated
while zones reload was cached as missing until a registry change.
Resolve again on state changes while a registered zone has no state.
When migrating, treat registered zone IDs as taken even without a
state, so a missing name can't take over a reloading zone's ID.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Only redo location migration when zones change

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Export the location migration and test it directly

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Watch registered zones without a state in the location editor

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Add match_mode so converted location conditions keep matching the same way

Converted conditions get match_mode: active_zone, which matches the zone
shown as the person state like locations did. any_zone stays the default.
The editor warns when active_zone has passive zones selected.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Match the active zone by ID, localize the mixed-config error

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Skip location zones without a state on each check instead of in the cache

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Match the person state when in_zones is empty, for legacy device trackers

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Msmy1J8Q6xPA4i3diLjwbr

* Treat not_home as away in the location fallback, not as a zone name

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Msmy1J8Q6xPA4i3diLjwbr

* Cache location zones on the registries only

Resolve registered zones without a state through a placeholder, so one
missing zone no longer makes every location condition resolve again on
each state change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Msmy1J8Q6xPA4i3diLjwbr

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-10-13 16:08:41 +03:00
Paul Bottein 25d8c3cadb Use the snap bottom sheet for the automation sidebar (#54664)
* Use the snap bottom sheet for the automation sidebar

* Use a fixed collapsed height for the automation sidebar sheet

* Make room for the half sheet before scrolling to an opened row

* Close the automation sidebar sheet by dragging it below the collapsed state

* Fall back to vh where dvh is not supported in the automation sidebar sheet
2026-10-13 14:49:39 +02:00
renovate[bot] 2034395784 Update dependency prettier to v3.9.10 (#54879)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-13 12:12:20 +02:00
Petar Petrov 2ad11a808d Use i18n contexts in the language, country, currency and trace pickers (#54877) 2026-10-13 11:19:45 +02:00
Paulus SchoutsenandClaude Opus 5.5 14866713ba Fix values and time picker in the adjust statistic dialog (#54876)
* Show exact values in the adjust statistic dialog

The dialog rounded each change to the display precision and showed the
raw JavaScript number. This caused three problems:

- The adjustment was calculated from the rounded value. Setting a
  change of 1.2345 to 0 left 0.0045 in the database.
- Changes smaller than the precision showed as 0. They could not be
  found or set to 0, because the new value equaled the shown value.
- The numbers did not use the number format of the user's locale.

The adjustment is now calculated from the stored value. Small changes
get more digits, and the values are formatted with the user's locale.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

* Wrap the time field below the date field on narrow screens

The date and time fields of the datetime selector are too wide for one
row on a phone. The time field overflowed the dialog and cut off the
AM/PM field in the adjust statistic dialog.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

* Redraw the adjust statistic dialog when the locale changes

The values use the number format of the user's locale. The dialog only
redrew on hass changes when the translations changed, so a new number
format did not show until another change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

* Show a missing change as zero in the adjust statistic dialog

A statistic row without a sum has a null change. The digit count
treated it as a very small value and showed 20 decimals.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

---------

Co-authored-by: Claude <[email protected]>
2026-10-13 08:32:47 +03:00
Aidan TimsonandClaude Opus 5.5 d1365b02da Add sticky group headers to data tables (#54848)
* Add sticky group headers to data table

lit-virtualizer positions rows absolutely, so CSS sticky positioning
can't be used. Render an overlay copy of the current group header at the
top of the scroller, pushed up by the next group header, and allow
collapsing the group from it.

With the group header now always visible, leave the grouped column out
of the narrow secondary line (except for auto-height tables, which have
no sticky header).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

* Keep sticky group header aligned and clear of focused rows

Shift the sticky group header's cell with the scroller's horizontal
scroll, so it lines up with the group header rows it covers, including
in RTL.

Add scroll padding to grouped tables, so a focused control in a row is
not left hidden under the sticky group header. Collapsing a group from
the sticky header scrolls a rendered header to the top directly, as
scrollIntoView would now leave room for the padding.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

* Keep the sticky group header fixed instead of pushing it

Browsers scroll off the main thread, so the push offset set from scroll
events lagged behind the rows. Scrolling fast showed one header taking
over the other late, and scrolling up on mobile left a gap above the
next group header where rows showed through.

The sticky group header now stays at the top of the scroller, and the
next group header slides under it, so it no longer needs to move in
step with the scroll.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

* Resize the sticky group header with the data table

The sticky group header's width was only measured on scroll, so after
resizing the window it kept its old width until the next scroll, letting
rows show through beside it. Observe the table's size to update it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

* Count a sticky group header within a pixel of the top as reached

The virtualizer can place rows at fractional positions, so a group
header scrolled to the top could sit a fraction of a pixel below it.
The sticky header then kept showing the previous group over it, for
example after collapsing a group from the sticky header.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

* Refresh the sticky group after renders and make its whole row clickable

Filtering, sorting or collapsing can replace the virtualizer's items
without changing the visible range, so no visibility event fires and the
sticky group header kept showing the previous group until the next
scroll. Recompute it after each render.

The sticky header's cell shifts with horizontal scrolling, which left a
strip at the end of the header that didn't respond to clicks. Handle
clicks on the whole sticky row instead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

* Explain the sticky group scroll back for unrendered headers

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

* Memoize the data table row renderer

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qmCtZuDLFdT8P7zqUcELk

---------

Co-authored-by: Claude <[email protected]>
2026-10-13 08:31:08 +03:00
Erwin Douna 707dc96fb1 Localize live indicator on logs page (#54858) 2026-10-13 08:13:38 +03:00
Paulus SchoutsenandClaude db1a628b57 Keep hidden columns when reopening data table settings (#54874)
Keep column settings for tables without fixed last columns

The data table settings dialog dropped the stored column order when the
table had no lastFixed columns. With no column order, the dialog showed
every column as visible. Reopening the dialog on the statistics table
then showed hidden columns as enabled again.


Claude-Session: https://claude.ai/code/session_014uzH9wKHRBfTGqXypaYEgV

Co-authored-by: Claude <[email protected]>
2026-10-13 07:55:48 +03:00
renovate[bot] 21c059e9fc Update dependency @types/node to v24.19.2 (#54868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-13 06:28:23 +02:00
renovate[bot] 33c734ea8b Update pnpm to v12.11.2 (#54869)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-13 06:28:05 +02:00
Paulus SchoutsenandClaude d8751e5b89 Show Z-Wave device config link for controller node (#54859)
Claude-Session: https://claude.ai/code/session_01Q6GDGNkP4RZT3wg17BEhsD

Co-authored-by: Claude <[email protected]>
2026-10-12 19:18:05 +00:00
renovate[bot]andMaarten Lakerveld edb7a42a7e Update dependency @versatiles/style to v6.4.0 (#54856)
Co-authored-by: Maarten Lakerveld <[email protected]>
2026-10-12 14:33:35 +00:00
WendelinandClaude 65a1f0722f Fix image cropper race conditions (#54850)
* Migrate image cropper dialog to DialogMixin and wait for cropper ready

Closing the cropper dialog with the header close button or Escape did not
run closeDialog(), so the Cropper instance stayed bound to the removed
<img>. The next open called replace() on that stale instance: the new
image never got a source or crop overlay, and clicking Crop before the
hidden reload finished threw because getCroppedCanvas() returned null.

Using DialogMixin gives every open a fresh element, and the cropper is
destroyed on disconnect. The Crop button is now disabled until the
cropper is ready, and _cropImage bails out if no canvas is available.

Refs #54793

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_011UTN4HCGBVyXdJ7F7bQnBX

* Add file handling improvements to upload components and cropper dialog

- Reset native input value when cleared externally in ha-file-upload
- Introduce _pickedFile state in ha-picture-upload for better file management
- Ensure cancelCallback is invoked if cropping is not completed in image-cropper-dialog
- Update HaImageCropperDialogParams to include optional cancelCallback

* Handle unsupported file formats in picture upload and ensure dialog connection during blob creation

* Add handling for dialog closing state in image cropper dialog

---------

Co-authored-by: Claude <[email protected]>
2026-10-12 17:32:31 +03:00
Petar Petrov c1981b16f2 Disable Lit dev mode in the legacy build under pnpm (#54855)
Compile Lit without dev mode in the legacy build again
2026-10-12 16:17:28 +02:00
renovate[bot] dfc1971ab4 Update pnpm to v12.11.1 (#54851)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-12 17:08:11 +03:00
768d61e223 Add query strings and My links to the Marketplace (#54787)
* Open the Marketplace with a search from the link

* Add My links for the Marketplace tabs and custom repositories

* Sort ascending when a Marketplace link gives no direction

* Keep the Marketplace link in step with the table

* Apply Installed deep-link settings behind Marketplace warning

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-12 17:07:40 +03:00
Claudio Wunder 04af517a22 Show Thread network information on its own page (#54818)
* Show Thread network information on its own page

The Thread panel showed a network's details behind an unlabeled info
icon that opened a plain-text dialog. Zigbee shows the same kind of
details through a "Network information" row that opens its own page,
so move Thread to that pattern.

Each network card with a stored dataset now ends with a "Network
information" row that opens /config/thread/network-info/<dataset_id>.
A new thread-config-router serves the panel and the page, like the
Zigbee and Bluetooth routers, and the border router lookup moves to
findOTBRInfoForDataset so both match border routers the same way.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Align the Thread network delete button with the network name

The 48px icon button was top-aligned with the shorter header text, so it
sat about 10px low. Center it on the name, and pull its block margins in
so the header keeps the same height as cards without the button.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Show an error when Thread network info fails to load

If thread/list_datasets rejected, the page never finished loading and
stayed empty, with an unhandled rejection. Catch the failure, always
finish loading, and show the error message on the error screen.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Show the Thread dataset before border router details load

otbr/info asks every OpenThread border router over REST, with a 10 s
timeout per call, so the network information page stayed empty while
an unreachable border router timed out. Show the dataset as soon as it
loads, without waiting for otbr/info, and show a Loading row in place
of the border router details until it answers.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Rename the Thread config router to thread-config-dashboard-router

thread-config-router read like a Thread border router. Match
zha-config-dashboard-router and the other config dashboard routers.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Say what the Thread network information page is loading

Use "Loading border router details…" for the row shown while otbr/info
answers, instead of a bare "Loading".

Assisted-by: Claude Opus 5.5 <[email protected]>

* Name each Thread network information landmark after its network

Every network card had a navigation landmark named "Network
information", so screen reader landmark navigation couldn't tell them
apart. Include the network name, or its extended PAN ID when it has none.

Assisted-by: Claude Opus 5.5 <[email protected]>
2026-10-12 17:06:40 +03:00
Petar Petrov 0d74036677 Remove dead .hass bindings (#54853) 2026-10-12 15:46:46 +02:00
Petar Petrov 7a69aac65a Remove unused hass properties from selectors and pickers (#54852) 2026-10-12 15:45:26 +02:00
Josef Zweck 4407404206 Show translated backup agent errors (#54847)
* Show translated backup agent errors

* Add tests for localizing backup agent errors
2026-10-12 16:14:05 +03:00
Markus TuominenandCopilot Autofix powered by AI d6ed305a8b Offer versioned SSL profiles in the HTTP server settings (#54559)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-10-12 12:39:42 +00:00
Aidan TimsonandClaude 13ea2643ee Hide last updated time on narrow marketplace dashboard rows (#54846)
Hide Marketplace last updated on narrow rows

A bare relative time like "4 months ago" has no context in the narrow
secondary line. The repository overview already shows it with a label.


Claude-Session: https://claude.ai/code/session_01RYz4pEoJju2EYeHerCi5CG

Co-authored-by: Claude <[email protected]>
2026-10-12 12:25:20 +00:00
Aidan TimsonandClaude cbae291079 Match the tab badge colors to the Apps update tag (#54845)
Match the Marketplace update badge to the Apps update tag

The update badge on the Installed tab and its narrow dot used the
warning color, while Apps marks an available update with a light
primary tag. Use the same primary fill and text colors so both read
the same way.


Claude-Session: https://claude.ai/code/session_012e1fHsMG8ZxDjAzsM5FMvZ

Co-authored-by: Claude <[email protected]>
2026-10-12 15:16:59 +03:00
renovate[bot] 71c061b68b Update dependency @rsdoctor/rspack-plugin to v1.6.5 (#54844)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-12 15:02:04 +03:00
Aidan Timson 26dcbfccfc Fix Marketplace update badge and row numbers on mobile (#54843) 2026-10-12 13:47:42 +02:00
Paul Bottein 3bb04f417c Remove name prefix stripping from generated dashboards (#54727)
* Remove name prefix stripping from generated dashboards

* Keep an empty entity name in generated card rows
2026-10-12 13:45:53 +03:00
Paul Bottein 03e5b8148b Simplify entity name helpers (#54726) 2026-10-12 13:45:53 +03:00
Paul Bottein 49e6a744e2 Finalize the entity naming migration (#54725)
* Finalize the entity naming migration

* Open the name picker in custom mode for a text default name
2026-10-12 13:45:53 +03:00
Petar Petrov 23c75da8f5 Number energy grid colors per direction so export-only connections are not white (#54808) 2026-10-12 10:53:15 +02:00
Petar Petrov fdae33a5ec Keep History and Activity filters usable with many targets (#54786) 2026-10-12 09:06:45 +01:00
Bascht74 ae7ce92a79 Keep adjust statistic dialog open after adjusting and refresh the list (#54628)
* Keep adjust statistics dialog open and refresh list after adjusting

* Guard adjustment against dialog close and handle refresh errors

* Ignore results of outdated statistics fetches

* Reset dirty state on close and guard failed adjustment
2026-10-12 08:04:29 +00:00
renovate[bot] c3ed2635e4 Update pnpm to v12.11.0 (#54842)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-12 11:02:11 +03:00
Daan Vervacke 1f2d5af99f Add selection mode with bulk delete to the tags page (#54819) 2026-10-12 09:46:46 +02:00
Claudio Wunder 1b4ff42821 Show empty state on MQTT panel when MQTT is not set up (#54817)
The MQTT panel rendered nothing when there is no active MQTT config
entry, leaving a blank page. That happens when another integration
loads MQTT as a dependency, so the Connectivity page still links to
the panel. Show an empty state with a button that starts the MQTT
config flow instead.

Assisted-by: Claude Opus 5.5 <[email protected]>
2026-10-12 09:24:01 +03:00
Paulus SchoutsenandClaude Opus 5.5 eec2ff9fa5 Treat unknown media player state as available in media control card (#54835)
* Set no-controls on media control card when entity is unavailable

An entity in the unknown state with assumed_state and turn on/off
support gets control buttons from computeMediaControls. The card hides
the controls for unknown and unavailable entities, but still left out the
no-controls class. That removed the bottom padding and made the card too
short.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wa4wcvqMtHTDDqGChBiGcD

* Treat unknown media player state as available in media control card

A media player in the unknown state is available. The card now shows
its title and controls, such as the turn on and turn off buttons of an
assumed state player, instead of the unavailable layout.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wa4wcvqMtHTDDqGChBiGcD

---------

Co-authored-by: Claude <[email protected]>
2026-10-12 08:58:33 +03:00
6a9501fa8a Unsubscribe from system health info only once (#54838)
The info page and the system log detail dialog unsubscribe from the
system health callback. The callback runs again for each update that
arrives before the unsubscribe completes, and each run unsubscribes
again. The finish event can unsubscribe once more. The backend rejects
every extra unsubscribe with "Subscription not found.", which ends up
as an unhandled promise rejection.

Make the unsubscribe function from subscribeSystemHealthInfo run only
once, which fixes all callers.

Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-12 08:18:24 +03:00
bb7308a024 Fix Z-Wave node config page for parameters without an endpoint (#54840)
The backend sends endpoint as null for configuration values on the
root endpoint, because zwave-js-server-python types Value.endpoint as
int | None. The frontend typed it as number and grouped parameters
with item.endpoint.toString(), so the page threw on every render and
stayed on the loading spinner.

Type endpoint as number | null. Treat null as endpoint 0 when grouping
parameters and when setting a parameter, because the backend set
command only accepts an integer endpoint.

Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-12 08:16:08 +03:00
renovate[bot] 1c151c65f2 Update dependency del to v9 (#54831)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-12 07:04:32 +02:00
439d61966d Fix media control card reading state before config is set (#54834)
The card can update with hass before setConfig is called. The progress
controller reads the state object on every host update, and the
_stateObj getter read _config.entity without a check. Each card then
threw a TypeError as an unhandled promise rejection.

The frontend logger maps the stack of every unhandled rejection with
source maps on the main thread. On a dashboard with 40 media control
cards, the 80 rejections blocked the main thread for about 3 seconds
on load.

Return undefined from _stateObj until the card has a config.

Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-12 06:44:53 +02:00
renovate[bot] 6dea194706 Update relative-ci/agent-action action to v3.2.4 (#54836)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-12 06:44:35 +02:00
renovate[bot] 31b76346d2 Update dependency vite to v8.3.4 (#54829)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-12 06:44:28 +02:00
renovate[bot] 87c079829a Update release-drafter/release-drafter action to v7.9.0 (#54837)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-12 06:42:58 +02:00
Petar Petrov 158c14b6ab Show device area in energy device graph tooltips (#54826) 2026-10-11 17:27:19 +02:00
Paulus SchoutsenandClaude de82c36acb Add bottom padding to AI and entity ID format settings pages (#54828)
The last card on these pages touched the bottom edge when scrolled to
the end. Use the same 24px bottom spacing as the other settings pages.


Claude-Session: https://claude.ai/code/session_013YwRmqQXnkZ3UBQJyBRSS6

Co-authored-by: Claude <[email protected]>
2026-10-11 17:26:16 +02:00
Patrick DecatandClaude Opus 5.5 32801130ba Close the previous ZHA permit subscription on search again (#54811)
* Close the previous ZHA permit subscription on search again

"Search again" called _subscribe() while the subscription from the first
search was still open, since _deactivate() only stops the UI at the end of
the permit window. Each zha/devices/permit subscription keeps ZHA debug
logging enabled in the backend until it is closed, so the leaked one kept
the backend in debug mode until the websocket connection closed.

Close any previous subscription before opening a new one.

Co-authored-by: Claude Opus 5.5 <[email protected]>

* Wait for the previous ZHA permit subscription to close before resubscribing

_unsubscribe() only called the previous unsubscriber from a promise
callback, so _subscribe() sent the new zha/devices/permit subscription
before the old one was closed, and the backend started the next debug
logging session while the previous one was still running.

Chain the new subscription onto the previous unsubscribe instead.
_subscribed always holds the latest chain, so a quick second search waits
for the first one, and leaving the page unsubscribes whatever that chain
ends up subscribing.

Co-authored-by: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-11 09:28:35 +03:00
renovate[bot] 0f09f11ac4 Update CodeMirror (#54820)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-11 09:27:24 +03:00
MichaelandClaude Opus 5.5 6f3c4b427b Fix Matter add device button not opening the add device dialog (#54823)
The add device button on the Matter dashboard linked to
/config/matter/add, which navigated to the devices dashboard and opened
the Matter add device dialog without awaiting the navigation. The
navigation closes open dialogs before it completes, so the dialog was
closed again right away and the user ended up on the devices dashboard.

Open the dialog directly from the Matter dashboard, like the Z-Wave
dashboard does, and make the /config/matter/add route (used by the
add_matter_device my link) await the navigation before showing the
dialog from the app root, as its own element is detached by then.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-11 09:26:58 +03:00
renovate[bot] 809ebc5095 Update Playwright (#54824)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-11 09:26:06 +03:00
renovate[bot] fbd1de0ec7 Update dependency cropperjs to v1.7.0 (#54810)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-10 17:16:56 +02:00
renovate[bot] 9f50d399a6 Update babel monorepo to v8.0.7 (#54813)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-10 17:16:19 +02:00
renovate[bot] da632926bb Update dependency @versatiles/style to v6.3.1 (#54814)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-10 17:15:37 +02:00
renovate[bot] 0e9b62e7d0 Update dependency @versatiles/style to v6.3.0 (#54804)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-10 05:42:05 +00:00
Elias Lecomte 2f09fb9e5b Improve demo water consumption and cost statistics (#54648)
* Add demo water statistics and long energy source names

* Align demo water statistics scaling and consumption costs

* Preserve non-admin permissions when the test app refreshes its user

* Restore original demo energy meter friendly names

* Remove unrelated authentication scenario fix from water statistics PR

* Derive demo costs generically and scale water by bucket duration
2026-10-10 08:39:06 +03:00
karwosts 1a922fc067 Fix time_format field appearing when it shouldn't in tile editor (#54799)
Fix time_format field appearing when it shouldnt in tile editor.
2026-10-10 08:35:10 +03:00
renovate[bot] 54e15575d2 Update pnpm to v12.10.1 (#54803)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-10 08:32:26 +03:00
renovate[bot] e9bfc29729 Update dependency maplibre-gl to v6.13.0 (#54806)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-10 08:31:33 +03:00
Jan-Philipp Benecke 743755a59f Fix script graph crash on template shorthand conditions (#54798)
* Fix script graph crash on template shorthand conditions

* Move string to ConditionWithShorthand
2026-10-09 16:17:44 -07:00
Aidan TimsonandClaude ea1d3fef73 Add E2E tests for creating an automation (#54791)
Cover creating an automation from the picker through the save dialog,
the save dialog refusing an empty name, and discarding a new automation
when leaving the editor.

The app harness now registers the demo's display registry mock, which
answers the refetch the app makes when a saved automation fires
entity_registry_updated.


Claude-Session: https://claude.ai/code/session_011L15xnuJiRZnioxrmNwDfb

Co-authored-by: Claude <[email protected]>
2026-10-09 19:02:28 +03:00
karwosts 8a83331e94 Fix autocomplete trying to fill username in weird places (#54789) 2026-10-09 16:59:22 +02:00
renovate[bot] b207a486dd Update dependency @versatiles/style to v6.2.0 (#54777)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-09 15:39:04 +02:00
Petar Petrov 00b3dfd43a Link Ethernet Matter nodes to Home Assistant in the network map (#54784) 2026-10-09 14:00:12 +02:00
Aidan Timson 8f38778180 Only offer installed statuses on the Marketplace installed tab (#54662) 2026-10-09 13:51:22 +02:00
Petar Petrovandcopilot-swe-agent[bot] e9ed4c5c66 Add local disk mounts to storage settings (#53643)
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-09 13:04:57 +02:00
Bruno Pantaleão Gonçalves 3ae69b041b Let the tab padding give way before the tab label (#54670) 2026-10-09 13:03:42 +02:00
Paul Bottein f7804a92f4 Use the entity name formatter in voice assistant settings (#54775) 2026-10-09 12:56:39 +02:00
Maarten Lakerveld fb0dcf29cb Map overview fixes (#54774) 2026-10-09 12:55:19 +02:00
tzagim bf564163bf Fix RTL bidi corruption of temperature in weather entity row (#54776) 2026-10-09 12:38:11 +02:00
Bram KragtenandClaude Opus 5 93b04625ac Drop ha-formfield in favour of the switch's own label (#54200)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-09 12:26:20 +02:00
Bram KragtenandClaude Opus 5 13c3155dab Remove dead --mdc-typography-* custom properties (#54201)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-10-09 12:18:50 +02:00
WendelinandClaude 9435c5494d Remove @material/web (#54580)
Co-authored-by: Claude <[email protected]>
2026-10-09 12:00:20 +02:00
Paul Bottein 4fbd34ac81 Use the entity name formatter in the entity filter, related items and logbook (#54773) 2026-10-09 12:50:02 +03:00
Paul Bottein 70390d7e43 Simplify how data tables reach the screen edges (#54714) 2026-10-09 11:32:26 +02:00
Bram KragtenandClaude Opus 5.5 43395ab59b Remove invalid ::part() selector that broke CSS minification (#54772)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-09 09:27:11 +00:00
Jan-Philipp Benecke 4247a1439e Fix crash on null trigger entries in the automation editor (#54771) 2026-10-09 09:15:00 +00:00
JonathanandXyolyp 0ecf3a0bb3 Link trace steps to the script or automation run they started (#54518)
* Link trace steps to the script or automation run they started

A step that runs a script or triggers an automation already records the started run as child_id in its trace, but the step details only dumped it as raw YAML. Show a link to that run's trace instead, named after the script or automation. A link to another run of the same item, like a script that starts itself, only changes the query string, so the trace pages now pick up a changed run_id themselves. The logbook's trace link and the new link share one URL helper, which encodes the item id.

* Keep the shown trace run in the URL

A link to another run of the same script or automation adds a history entry, but the trace page only followed in-app navigation, so browser back and forward left the URL and the shown run apart. Write the shown run into the current history entry, follow popstate within the same trace page, and let only the latest trace list request update the page. Entries without a run_id are ignored, since closing a dialog with back lands on one with the same URL.

* Let only the latest trace request update the trace page

Going back to the shown run while a linked run was still loading left the older request in charge: it then showed the linked run and wrote it into the history entry the user went back to. Remember which run the latest trace list request is for and drop it when the URL returns to the shown run. Loading the same run twice could also let the older response win, so trace requests are numbered as well.

* Let a URL change replace the first trace list request

While a trace page was loading its first trace list, a link or browser history step to another run of the same script or automation was ignored, so that first request won and wrote its run into the newer history entry. Handle such a change right away, so it replaces the pending request.

* Let a run picked on the trace page win over a pending link

While a link to another run of the same script or automation was loading, a run picked with the trace picker or the arrows was overwritten once the link's trace list arrived, and Refresh dropped the linked run while the URL kept it. A picked run now cancels the pending link, and Refresh keeps the run the link asked for.

* Move the trace run navigation into a shared controller

Both trace pages carried the same logic to follow the URL, number their requests and write the shown run back into the URL. Move it into a TraceRunController with unit tests, build the trace page path in one place, and split the child trace name from its link. No change in behaviour.

* Link trace timeline steps to the run they started

The step details link a step that ran a script or triggered an automation to the run it started. Show the same link under that step in the trace timeline, and share the name lookup and the link between both views.

* Compare trace paths decoded

The route decodes the item id, so a trace page can also be opened by a
link that encodes it differently, like the logbook's links, which do not
encode it. Compare the decoded paths, so that the URL follows the shown
run there too.

---------

Co-authored-by: Xyolyp <[email protected]>
2026-10-09 11:56:00 +03:00
WendelinandClaude aea94f557b Migrate ha-outlined-icon-button to ha-icon-button (#54571)
Co-authored-by: Claude <[email protected]>
2026-10-09 10:55:32 +02:00
Franck Nijhof cd6bdc0344 Don't count the characters of a string target (#54769) 2026-10-09 08:52:30 +00:00
Franck Nijhof 844d7bc0e5 Keep custom logbook messages for automations and scripts (#54739)
* Keep custom logbook messages for automations and scripts

* Only match the domain's own run message
2026-10-09 11:48:14 +03:00
Franck Nijhof b4c6035a75 Convert CSS color names to hex when saving a label (#54738) 2026-10-09 08:45:01 +00:00
Franck Nijhof f77295fcfa Keep dropdown menus clear of safe areas (#54762) 2026-10-09 10:41:39 +02:00
Paul Bottein 951ca9e9f1 Use the entity name formatter in automation descriptions (#54767) 2026-10-09 10:41:23 +02:00
Claudio Wunder e7f3a02d73 Fix thin line flashing under empty sliders while dialogs open (#54716) 2026-10-09 08:40:44 +00:00
Franck Nijhof 9555f6f4d7 Give dialogs an accessible name (#54758) 2026-10-09 10:40:23 +02:00
Franck Nijhof d7f39d3804 Hide hidden cards in grid sections without :has() (#54764) 2026-10-09 11:39:41 +03:00
Franck Nijhof 854f28fc26 Translate attribute names every entity can have (#54768)
* Translate attribute names every entity can have

* Translate the supported features attribute name
2026-10-09 11:38:31 +03:00
Franck Nijhof ef587c6b77 Release streaming images when hui-image is detached (#54760) 2026-10-09 10:36:18 +02:00
Franck Nijhof 70a96e47ca Show the speech-to-text duration without VAD (#54759) 2026-10-09 10:35:26 +02:00
Franck Nijhof 28e7cb39fb Show the ZHA config entry state when it isn't loaded (#54756) 2026-10-09 10:32:10 +02:00
Maarten Lakerveld 49d01d20eb Center the map on a single entity instead of fitting it (#54718)
The vector map's globe projection (new in 2026.10) cannot solve a camera
for a zero-area bound, so fitting a single-entity map warned "Map cannot
fit within canvas" and left the view on the default location. Center a
single point directly with easeTo/flyTo rather than routing it through
fitBounds, carrying the fit's padding as a transient offset and honouring
its fly request.
2026-10-09 11:30:35 +03:00
Franck Nijhof 941b167c82 Keep icon button labels off the ha-button host (#54761) 2026-10-09 11:28:13 +03:00
Franck Nijhof e908ac15d3 Greet in the interface language when it is a variant of the pipeline language (#54766) 2026-10-09 11:27:33 +03:00
Aidan TimsonandPetar Petrov 20cd4683b0 Add area labels to the pull request labeler (#54697)
* Add area labels to the pull request labeler

* Label Labs pull requests from the Labs API as well as paths

* Rename the Landingpage label to Landing Page

* Label Supervisor pull requests that change src/data/hassio

* Label pull requests from area code as well as paths, and only add labels

* Remove stale labels again, owning code-matched ones in the script

* Warn instead of failing the labeler, and summarise changes

* Move the run summary into a shared helper

* Split the Activity label from History

* Add labels for the remaining areas and split broad ones

* Apply the Home Assistant Link label from the content script

* Catch more companion app usage in the content labels

* Add Notifications, Search and Sidebar labels and widen some rules

* Add the AI label

* Label trace changes as Automations

* Match content labels on whole calls against the current labels

* Run the labeler one at a time per pull request

* Label dashboard creation, quick bar and theme loading changes

* Compare Labs and companion app calls with their arguments

* Match full companion app calls and imports in content labels

* Label updates list changes as System

* Match companion app property reads and renamed files in content labels

* Remove

Co-authored-by: Petar Petrov <[email protected]>

* Add ingress panel

Co-authored-by: Petar Petrov <[email protected]>

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-10-09 11:25:29 +03:00
Franck Nijhof c6c85e862d Expose the real invalid state of inputs to screen readers (#54757) 2026-10-09 10:25:05 +02:00
Franck Nijhof c74b9831af Fit the add integration list on short screens (#54755) 2026-10-09 10:18:10 +02:00
Petar Petrov eb4b1e8b3d Fix negative upstream device untracked energy in devices detail graph (#54753) 2026-10-09 10:16:56 +02:00
Petar Petrov 3cd56c4b9c Follow the active row in virtual-focus lists after a removal (#54765) 2026-10-09 10:01:02 +02:00
WendelinandClaude Opus 5.5 e11cdc16ec Migrate remaining ha-md-list usages and remove ha-md-list (#54569)
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Claude <[email protected]>
2026-10-09 09:10:04 +02:00
Petar Petrov a42ba01ca2 Hide Zigbee from the ESPHome device setup wizard (#54751) 2026-10-09 08:59:02 +02:00
Franck Nijhof 941dbb5697 Fall back to local voice setup when the cloud status fails (#54754) 2026-10-09 09:51:54 +03:00
renovate[bot] 3d6061e6e0 Update pnpm to v12.10.0 (#54752)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-09 09:33:57 +03:00
Claudio Wunder 21b07240ab Speed up building history line chart data (#54671)
* Allocate less per point when building history line chart data

For a single dataset, a plain numeric value went through
pushData(date, [value]), which allocates a one element array and a
forEach callback for every point. Push [timestamp, value] directly and
reuse one array for prevValues, which is only ever read for its latest
entry. The output is unchanged.

pnpm test:bench state-history-chart-line-data, median of 8 alternating
runs: mixed large (100k states) 8.62 -> 5.83 ms, mixed medium (10k
states) 0.80 -> 0.58 ms. In a production browser build the function took
about 101 ms before and after on 1.34 million points.

Assisted-by: Claude Sonnet 5.5 <[email protected]>

* Tighten the per-point loop in history line chart data

Profiling generateStateHistoryChartLineData on a large history put most
of the remaining time in the per-point path. Iterate the states with an
indexed loop instead of forEach, read the series array once, and track
the y range inline instead of through trackY, since the value is always
finite there. The output is unchanged.

These only help together. On their own, the hoisted array and the inline
min/max measured no change, and for...of loses most of the gain, so
@typescript-eslint/prefer-for-of is disabled for this one loop.

Cold first call in a fresh headless Brave, median of 7 runs, on 1.34
million states: 87.9 -> 77.2 ms on top of the previous commit (98.7 ms
on dev). At 100k states: 5.2 -> 4.1 ms.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Add a test for history line chart states past the end time

The characterization tests never had a state after endTime, so the path
that drops those points was not covered. That path is where the faster
pushValue skips updating the reused prevValues array, and the end point
of the line depends on it.

Add a numeric sensor with a value and a gap that only closes after
endTime. The snapshot was generated on dev before being run against this
branch, so it pins the previous behavior. Updating the reused array
before the endTime check makes only this test fail.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Drop the indexed loop from history line chart data

The previous commit gives nearly all of the gain, so the indexed loop,
the hoisted series array and the inline y range aren't worth disabling
@typescript-eslint/prefer-for-of and keeping a second copy of trackY.

This reverts commit 952022b91.

Assisted-by: Claude Opus 5.5 <[email protected]>
2026-10-09 09:24:52 +03:00
4fa8cf6dc7 Show energy gas in the unit of its sources (#54677)
* Show therm gas in therms on the energy dashboard

Gas sources with an energy unit class were always converted to and shown
in kWh. Now that therm is a native energy unit, show gas in therms when
every gas source reports therms, and request those statistics in therms
for both the current and the compare period. Any other energy unit, or a
mix of units, keeps showing kWh as before.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

* Keep kWh when a therm gas statistic is also a device

The device charts read the same statistics map and label values as kWh.
If a therm gas statistic is also configured as an individual device, the
therm values would be shown as kWh there, so keep kWh for gas in that case.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

* Use the unit of energy gas sources for any energy unit

Volume gas and water already use the display unit of their sources when
they all share one. Do the same for energy gas instead of always showing
kWh, by adding an ENERGY_UNITS list next to VOLUME_UNITS and requesting
the gas statistics in that unit. Different units, or a gas statistic that
is also an individual device, still fall back to kWh.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

* Refactor energy statistics handling in energy.ts

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Test gas statistics shared with grid, solar and battery

Cover the fallback to kWh when a therm gas statistic is also used as a
grid, solar or battery statistic, and update the comment to match.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

---------

Co-authored-by: Claude Sonnet 5.5 <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-10-09 06:18:46 +00:00
Franck Nijhof c0ed2e1b59 Keep the label of color inputs raised (#54737) 2026-10-09 08:52:39 +03:00
Simon Lamon 5a96e1829f Restore compatibillity with older chromium devices in ScrollFadeController (#54742)
Restore compatibillity with older chromium devices
2026-10-09 08:49:33 +03:00
renovate[bot] 10c91bb9a3 Update dependency vite to v8.3.3 (#54748)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-09 05:08:01 +00:00
renovate[bot] d74804b44f Update dependency zxing-wasm to v3.1.5 (#54747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-09 06:56:27 +02:00
renovate[bot] fbe209cd0b Update dependency nanoid to v6.0.2 (#54746)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-09 06:24:23 +02:00
renovate[bot] a66e13b0b9 Update dependency js-yaml to v5.4.3 (#54745)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-09 06:24:04 +02:00
Franck Nijhof dca4a8e0a9 Load Marketplace icons through the Marketplace brands view (#54740) 2026-10-08 15:27:54 -04:00
480182c2b3 Make the Marketplace warning a friendlier modal over the Marketplace (#54586)
* Make the Marketplace warning a friendlier modal over the Marketplace

Replace the full-page first-run warning with a calmer dialog shown over
the Marketplace, which stays visible but can't be used until the notice
is accepted. Continue is enabled once the checkbox is ticked, without
the 30 second countdown. Go back, or Escape, leaves the Marketplace.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LZuGZHa3FZ9tNHtuuSy8c3

* Update the Marketplace warning to the new design

Lead with what installing can do, in a highlighted list, followed by
numbered steps to stay safe, and agree to the risks explicitly.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LZuGZHa3FZ9tNHtuuSy8c3

* Update the Marketplace warning tests to the modal

Test the warning's accept, failure and go back logic instead of the
countdown, test that the Marketplace is inert behind the warning and
starts over once it is accepted, and drop the countdown strings.

Focus the checkbox when the warning opens, and drop the close handler:
neither Escape nor the scrim close the warning, Go back leaves it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LZuGZHa3FZ9tNHtuuSy8c3

* Keep links from acting behind the Marketplace warning

Until the warning is accepted, the Marketplace behind it shows the
catalog whatever the route is, so a link can't add a repository or open
a dialog over the warning. It starts over on the route once accepted.

Use the animation duration token for the agree row, which respects
reduced motion.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01LZuGZHa3FZ9tNHtuuSy8c3

* Add role attribute to marketplace warning list

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Enhance ha-dialog-header and ha-marketplace-warning components with improved structure and styling

* Refactor marketplace panel tests to improve clarity and structure

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Wendelin <[email protected]>
2026-10-08 20:30:54 +02:00
Petar Petrov 2d11eba37f Show only serial integrations when setting up an ESPHome serial port (#54668)
* Show only serial integrations when setting up an ESPHome serial port

The add integration dialog gets an integrationFilter param with a list of
domains and trims the integration descriptions to them. The ESPHome serial
Set up button fetches usb/list_serial_integrations and passes it. If that
fails, it opens the unfiltered dialog as before.

* Check for a newer add integration load after loading translations
2026-10-08 20:23:20 +02:00
Maarten Lakerveld 5821cc6e53 Drop the Mapbox RTL text plugin now that MapLibre shapes RTL text itself (#54706)
Since MapLibre 6.9.0 Arabic and Hebrew labels are shaped and reordered by
MapLibre, and setRTLTextPlugin is deprecated. We were still loading the
0.4.0 plugin, which only replaced that built-in implementation with the
same result. Version 1.0.0 of the plugin drops the UMD bundle we copied
into static assets and no longer works as a plugin at all, so bumping it
breaks the build. Remove the dependency, the static copy and the plugin
registration instead.
2026-10-08 20:21:45 +02:00
renovate[bot] ade5d15fee Update dependency @formatjs/intl-datetimeformat to v7.8.1 (#54735)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-08 18:15:34 +00:00
Paul Bottein b8ea4d12b9 Replace map overview more info button with a header icon (#54704)
* Replace map overview more info button with a header icon

* Reuse the show more information label

* Show a settings button for admins in the map overview

* Hide the map overview settings button in the demo
2026-10-08 20:14:37 +02:00
Paul Bottein fcb7efdec2 Use the entity name formatter in dashboards (#54724)
* Use the entity name formatter in dashboards

* Refresh map trail names when the entity name formatter changes

* Show the device only once in the card editor entity search

* Make the name optional in the bootstrap entity name formatter
2026-10-08 20:08:21 +02:00
renovate[bot] 8dfcbe7a74 Update dependency intl-messageformat to v12.1.3 (#54734)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-08 18:04:13 +00:00
JonathanandXyolyp 5509c405ad Encode the automation id in activity trace links (#54733)
Encode the item id in the activity trace link

Automation ids are free-form, so an id with a question mark, a hash or a
percent sign broke the "View trace" link of the activity details. Encode
it like the automation editor and the automation list do.

Co-authored-by: Xyolyp <[email protected]>
2026-10-08 19:59:02 +02:00
Paul Bottein bdd67e89e2 Add side padding to the statistics search field (#54717) 2026-10-08 19:56:05 +02:00
renovate[bot] a9f1a24860 Update dependency typescript-eslint to v8.71.1 (#54732)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-08 19:53:44 +02:00
renovate[bot] 20062433ec Update dependency marked to v18.1.0 (#54730)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-08 19:38:39 +02:00
Franck Nijhof d3ed92978f Only cache the frontend's own static files in the service worker (#54707) 2026-10-08 18:09:28 +02:00
Franck Nijhof 2ae987504a Show the right page title for more settings pages (#54708) 2026-10-08 17:54:56 +02:00
Franck Nijhof 8662da2e8a Respect custom icons for built-in panels in the sidebar (#54709) 2026-10-08 18:24:05 +03:00
Paul Botteinandcopilot-swe-agent[bot] f2c2b9e472 Add a debug tool to simulate safe areas (#54719)
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-08 15:01:14 +00:00
Petar Petrov 47289adbab Drop hass from ha-network-graph and add a reduced motion context (#54713) 2026-10-08 16:52:15 +02:00
Claudio Wunder 6315f4a9e2 Coalesce live updates on large history charts (#54669)
* Add a delay calculation for live history updates

Rebuilding the History charts for a large history takes tens of
milliseconds, and it grows with the number of states, so applying every
live stream message to one makes the page hitch.

Add countHistoryStates and computeHistoryUpdateDelay. A history under
100,000 states is never delayed. For a larger one the delay is the time
one chart pixel covers (assuming 1000 pixels), between one second and a
maximum the caller passes in.

Assisted-by: Claude Sonnet 5.5 <[email protected]>

* Coalesce live updates on large history charts

When a History range ends in the future, Core keeps streaming states and
every message rebuilds the whole history: computeHistory, the line chart
data and the downsampling all run again over every point. With 1.34
million states (30 days of a sensor updating about every 2 seconds)
that is a 150 to 200 ms long frame per message.

Apply the first message right away, then coalesce later ones with
computeHistoryUpdateDelay, using MIN_TIME_BETWEEN_UPDATES as the maximum.
Every message carries the full history, so the latest one wins. The
timer is cleared when the panel unsubscribes.

A replaced subscription can still deliver until its unsubscribe is
acknowledged. Ignore those messages, so a coalesced one can't land
minutes later on top of the new range.

Over 25 s on a production demo build with a mocked live stream (median
of 5 runs): rebuilds 21 -> 0, long frames 22 -> 0, main thread blocked
2057 -> 0 ms, heap after GC 500 -> 288 MB.

Assisted-by: Claude Sonnet 5.5 <[email protected]>

* Use the measured chart width for the live update delay

The delay was the time one pixel covers on a chart assumed to be 1000
pixels wide. Measure the charts the same way the timeline downsamples
them, so wider or high density charts update as often as a pixel
changes.

Assisted-by: Claude Opus 5.5 <[email protected]>

* Keep the history legends current while live updates wait

The line chart legends show the current state of each entity, but the
charts skip updates where only hass changed. While a live update waited,
the legends could lag behind by up to five minutes. Request an update of
the charts when an update is held back, so they follow the current
states.

Assisted-by: Claude Opus 5.5 <[email protected]>
2026-10-08 17:34:30 +03:00
Artur Pragacz 6269d09b0d Fix translation key for external config flow step description (#54722) 2026-10-08 14:19:51 +00:00
Petar Petrov 98cb371d86 Drop hass from the distribution card (#54711)
* Drop hass from the distribution card

The card consumes the states of its own entities, the formatters,
localize and the core config. It no longer re-renders when an
unrelated entity changes.

* Re-render the distribution card when the theme changes

The card resolves its graph colors from the theme when it renders, so
it has to render again when the theme changes.
2026-10-08 16:07:39 +02:00
Petar Petrov 308b03e432 Pass localize and config to createEntityNotFoundWarning (#54710)
The helper took a hass-shaped object and an unused entity ID. It now
takes the two values it reads. The dead .hass bindings on hui-warning
are removed too; the element has had no hass property since #52926.
2026-10-08 15:54:14 +02:00
Claudio Wunder 24e15e76d9 Avoid recomputing chart series when only options change (#54666)
* Avoid recomputing chart series when only options change

The history line chart downsamples every point of a series before it is
handed to ECharts. ha-chart-base did that again on every options change:
_updateHiddenStatsFromOptions requested an update for _hiddenDatasets
each time it ran, even when no dataset had been hidden, and
_applyChartUpdate rebuilds and downsamples all series whenever
_hiddenDatasets is flagged.

Only the history line chart samples its data, and its x axis bounds
change together with its data, so rebuilding on data or hidden dataset
changes covers every input of _getSeries.

On a 30 day range of a sensor with 1.34 million states, loading the chart
called _getSeries 4 times, and now calls it once. Median of 7 runs on a
production demo build: _getSeries 85 -> 29 ms, time from data delivery to
the first frame 273 -> 209 ms.

Assisted-by: Claude Sonnet 5.5 <[email protected]>

* Drop the chart screen reader connection when the options change

Chart2Music is built with the axis names and value labels of the
current options. It used to be dropped on every options change because
_hiddenDatasets was always flagged, which now only happens when a
dataset gets hidden. Drop it whenever the options change, so the next
keyboard focus rebuilds it with the current ones.

Assisted-by: Claude Opus 5.5 <[email protected]>
2026-10-08 13:30:11 +00:00
XanderandClaude Opus 5.5 77d80bdec4 Add copy, cut and paste for dashboard sections (#54652)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 10:46:01 +00:00
Franck Nijhof 8d0d8160f5 Handle map labels without a name (#54689) 2026-10-08 12:16:49 +02:00
Bram KragtenandClaude Opus 5.5 463bda3e7c Add realistic automations to the demo (#54647)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 12:05:54 +02:00
Marcin BauerandClaude Opus 5.5 dfdaeee75b Allow running and testing disabled actions and conditions (#54649)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 12:01:37 +02:00
Franck Nijhof f0a67727a2 Fix ZHA reconfigure dialog errors after closing and on reconnect (#54684)
* Fix ZHA reconfigure dialog errors after closing and on reconnect

* Only handle reconfigure messages of the current run
2026-10-08 11:54:09 +02:00
Paul Bottein e47a7c3a45 Allow sections to contain badges and sections (#54624) 2026-10-08 09:30:26 +01:00
WendelinandClaude Opus 5.5 da70ab7268 Refactor UI support checks into static methods and add validation helpers (#54493)
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Claude <[email protected]>
2026-10-08 10:27:10 +02:00
Franck Nijhof 2f15c7640f Keep boolean fields inline in the narrow action editor (#54686) 2026-10-08 09:18:40 +01:00
Bram KragtenandClaude Opus 5.5 1c8da1329e Add focus indicator to entity and sensor cards (#54644)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 09:16:21 +01:00
Franck Nijhof a9c449f502 Load the HLS source once instead of on every media attach (#54683) 2026-10-08 08:55:09 +01:00
Franck Nijhof 568d842245 Let long dropdown submenus scroll (#54692) 2026-10-08 07:48:26 +00:00
Petar Petrov 796795818d Show the newest history states when the browser clock runs behind (#54688) 2026-10-08 08:44:19 +01:00
Franck Nijhof 33c1a3acfd Keep a cleared input value when focusing it again (#54690) 2026-10-08 09:40:27 +02:00
Franck Nijhof 9e0f0931ae Keep the key order when duplicating a script (#54687) 2026-10-08 09:29:30 +02:00
b71c47f2e8 Add unit of measurement selector (#54391)
* WIP

* Implement unit of measurement picker and selector

* Disable units for device classes that do not support units

* Fix no unit

* Follow sensor entity unit rules in unit of measurement selector

Non-numeric device classes only allow no unit, and a device class or
state class without a unit table (such as monetary or measurement)
no longer restricts the units.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Follow up on comments

* Lint error

* Add context info to config

* Only clear the unit when the context filters change

ha-form, the blueprint editor and the gallery create a new context object
on every render, so editing an unrelated field counted as a context
change and could clear a saved unit. Compare the filter values instead.

A filter can be a list of device classes or state classes, so compare
them by value rather than by reference.

Co-authored-by: Petar Petrov <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Petar Petrov <[email protected]>
2026-10-08 09:25:14 +03:00
karwosts 6afbc6322d Fix unhandled undefined label registry access (#54659) 2026-10-08 09:13:19 +03:00
bd286f2519 Add power values to energy dashboard (#54627)
* Bugfixes

* Remove useless updates

* Fix updating issue

* Remove useless check

* Rename test case for clarity

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Petar Petrov <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-10-08 05:49:43 +00:00
Jump-333 fb16219c5b Add legend values in the devices details graph (#54631)
* Add legend values in the electricity page

* Fix localization issue and tests

* Add tests and fix localization issues

* Remove energy usage graph legend
2026-10-08 08:25:34 +03:00
Aidan Timson 4852d3c609 Add repository source filter and grouping to Marketplace (#54654)
* Add a source filter and group by source to the marketplace

* Plural form

* Test that marketplace browse links keep the source

* Drop the Marketplace filter pane rendering test
2026-10-08 08:22:14 +03:00
Jump-333 26c332d922 Remove duplicate condition from the automation editor code (#54674)
Remove duplicate condition
2026-10-08 08:13:04 +03:00
renovate[bot]andPetar Petrov b829ba9eca Update dependency jsdom to v30.1.2 (#54642)
* Update dependency jsdom to v30.1.2

* Focus shadow-rendered buttons in dialog-form tests

jsdom 30.1.2 no longer focuses light-DOM children of a shadow host
without a slot. The ha-form mock has no slot, so the opener buttons
were never rendered. Put them in the form's shadow root, where real
ha-form controls live.

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <[email protected]>
2026-10-08 06:40:44 +02:00
Franck Nijhof 46c65973a0 Wrap descriptions in voice assistant settings (#54678) 2026-10-08 06:39:03 +02:00
karwosts 4bb7908f60 Fix create floor memoization issue (#54675) 2026-10-08 06:38:34 +02:00
Paul Bottein bc21992178 Snap the map overview bottom sheet to fixed positions (#54663)
* Snap the map overview bottom sheet to fixed positions

* Include the safe area in the collapsed stop and follow reduced motion
2026-10-07 17:50:09 +02:00
Bram KragtenandClaude Opus 5.5 28f53d9f5a Show the next demo card on the home page demo again (#54646)
* Show the next demo card on the home page demo again

The home overview strategy now generates the favorites section itself
instead of returning a common-controls section strategy, so the demo
strategy no longer found the section to add its card to. Find the
favorites section by its heading instead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Keep at least six favorites next to the demo card

The section strategy used to get a limit of two less, so seven tiles
became six. Only drop as many tiles as needed to keep six.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Keep the current user when the demo user subscription refreshes

The auth/current_user mock answered with the user from startup, so the
user subscription reset a changed user, like the non-admin scenario of
the e2e tests, to the initial admin user.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 17:33:31 +02:00
Aidan Timson d2fa820035 Add group by to Marketplace tables (#54653)
* Add group by status and type to the marketplace

* Update the marketplace dashboard test for grouping

* Group the marketplace by status by default

* Type the Marketplace grouping events and drop the panel test
2026-10-07 17:05:45 +02:00
Petar Petrov 0e34aa06c1 Align history timeline X axis with line charts (#54657) 2026-10-07 17:53:03 +03:00
Marcin BauerandClaude Opus 5.5 bb168601b8 Restore left-column timeline names on the history-graph card (#54661)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 15:47:15 +01:00
Aidan Timson 1823e783ee E2E test fix: Keep the current user in the demo auth stub (#54658) 2026-10-07 15:56:00 +02:00
Marcin BauerandClaude Opus 5.5 03a815bb2e Fix long entity names overflowing the entities picker (#54656)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 13:13:50 +00:00
Marcin BauerandClaude Opus 5.5 adde734800 Make disabled automation rows easier to read (#54650)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 14:58:02 +02:00
Petar Petrov 8598a35c88 Add reset zoom button to network graphs (#54510) 2026-10-07 14:30:10 +02:00
WendelinandClaude Opus 5.5 7008f2ee38 Keep dropdown menus within the viewport and wrap long items (#54643)
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Claude <[email protected]>
2026-10-07 14:23:54 +02:00
Paul Bottein 0a8a71049b Use generic paths to address Lovelace dashboard items (#54207)
* Use generic paths to address Lovelace dashboard items

* Return node target for container paths

* Remove dropped card node when creating a section from a drop

* Refuse to write through a missing list item

* Only build card and badge paths in edit mode

* Use optional badge config in edit badge dialog params

* Append cards in a single write in addCards

* Append badges in a single write in addBadges

* Pass a save callback to the badge edit dialog

* Handle ll-create-card from custom layouts that don't bubble it
2026-10-07 14:20:51 +02:00
Bram KragtenandClaude Opus 5.5 79488d0c09 Mock editing the own profile in the demo (#54645)
The demo did not answer person/update_own_profile, so saving the profile
dialog showed an error. Also answer auth/current_user, so the user
subscription picks up the new name.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 15:00:39 +03:00
WendelinandClaude d0c09951e6 Dismiss reboot/shutdown toast when frontend reconnects (#54640)
The "Rebooting system" toast was shown without an id and with no
timeout, so nothing could ever close it and it stayed on screen after
the host came back. Give it an id, dismiss it when the connection is
re-established, and also when the action fails with an error dialog.

Fixes #54630


Claude-Session: https://claude.ai/code/session_01SkS1AB8w2GPUuRBaDDmsEu

Co-authored-by: Claude <[email protected]>
2026-10-07 10:37:54 +02:00
Aidan Timsonandcopilot-swe-agent[bot] 3d57d1b949 Remove the blocking-label workflow (#54064)
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-07 10:33:37 +02:00
Maarten Lakerveld d02b605916 Zone editor: fit without passive zones, hide covered radius handles, name tooltips, and start new zones at the map center (#54597)
* Leave passive zones out of the zones map fit

Opening the zones page fitted the map around every zone, so a few remote
passive zones pushed the view out to the whole globe and adding a zone took
a lot of zooming. Passive zones are still drawn and editable, but no longer
count toward the fit unless they are the only zones there are. Editable
locations gained a fit flag for this.

Fixes #54595

* Hide a zone's radius handle while the circle is under its icon

Zoomed out on the zones page, every zone's radius handle collapsed onto the
zone icon and covered it. The handle now hides while the radius on screen is
shorter than the icon's half width, so it returns as soon as the circle's
edge shows past the icon, and it stays while the radius is being dragged.

* Show a zone's name in a tooltip when hovering its marker on the zones map

The marker only had a native title, which appears late and in the
browser's own style. Every named editable location now gets an ha-tooltip
anchored to its element, so hovering a zone icon on the zones page names
it promptly; the native title is dropped so the two do not stack.

* Start a new zone at the center of the zones map

Create zone placed the new zone at a random spot up to 500 meters from
home, so it landed somewhere unexpected and often off-screen. When the zones
page has its map open, a new zone now starts at the center of the current
view, so panning to the right place first works as expected. A location
handed in, as from a person's Create zone action, still wins; without a map
the random offset around home remains.
2026-10-07 10:12:08 +02:00
Maarten Lakerveld a9c1531e37 Map: float every marker, keep the selection in the URL, pan-first focus, and fix attribution and zone radius display (#54596)
* Auto-hide compact map attribution and restyle it for dark mode

MapLibre decides compact mode from the map canvas width alone (640px), so
shrinking the window flipped the attribution from compact back to inline
when the sidebar became a drawer and the map got wider. The engine now adds
the control itself and forces compact on a narrow viewport (870px, the app's
own narrow layout), swapping it when the breakpoint changes.

MapLibre only collapsed the opened compact attribution on a drag; it now
also collapses by itself after five seconds, unless the user opened it from
the info button.

MapLibre's stylesheet hardcodes a white attribution with black text, which
Home Assistant never overrode, so it stood out on a dark map. The dark mode
rules now match the zoom control styling, and the inline text color is set
explicitly instead of inherited from a page that may be in the other mode.

* Add show_zone_radius option to the map card

In panel layout the map hides zone radii except on the Zones tab, for the
selected zone, and while editing. A user asked to always see them, so the
new option draws the radius of every visible zone on all tabs. Other layouts
already show radii and are unaffected.

* Regroup map clusters up front for every fit

Clicking a bubble already regrouped its members at the zoom the fit would
land on, so they parted as the animation started. Any other way of zooming
in, such as picking a person in the map overview, waited for the move to end
before the bubble split. The fit itself now does the regrouping, for all
markers, so every animated fit shows the bubbles as they will end up.

* Return the map to its previous view from the overview's back button

Leaving a selected person or zone cleared the selection but left the map
zoomed in on it. The card now remembers where the map was when the overview
drilled in: the exact camera, or the previous entity's fit when one selection
followed another, and the back button eases back there. A camera that was
still auto-fitting resumes auto-fit instead of freezing. Clicking the map to
deselect stays put, since that is the user looking around.

Engines gain getView, and setView can animate.

* Float the selected map marker above a dot at its location

Selecting a person or device marked it with a ring only, and inside a zone
it stayed hidden in the zone's bubble. The selected marker is now excluded
from clustering, drawn a quarter larger, and hangs above a small dot at the
exact coordinate with a tail pointing down to it. The accuracy circle around
the dot carries the entity color, so the ring is dropped; an entity that
reports no accuracy gets a nominal 5 meter circle so the color still shows.
A fix of 10 meters or better draws that circle as a soft disc without an
outline, since a hard edge would claim more precision than is known; map
circles gained an outline option for this. The engine's marker anchor puts
the dot on the coordinate; both engines support it. Bubble avatars keep
their size.

* Open more info from a button in the map overview detail

The selected person, device or zone's name was the only way to the more-info
dialog, which made the title read as a link. The name is plain text now and
a filled More info button sits below the activity, where the user expects an
action. Focus still moves to the name when the detail view opens.

* Always show the selected marker's accuracy circle

The circle only appeared for a GPS fix looser than 100 meters, so most
phones never showed one. The selected marker now floats above a dot at its
coordinate, so even a small circle around that dot reads clearly; it is
never hidden for the selected entity. Focusing still fits the circle into
view only above 100 meters, since a tighter circle fits at the focus zoom.

* Describe every toggle in the map card editor

Only Show all and Show zone radius explained themselves; Scale ruler, Auto
fit, Fit zones and Cluster markers now have helper text too.

* Float every map marker above its location

Only the selected marker hung above a dot with a tail; the rest sat
centered on their coordinate, so a marker's frame always hid the spot it
marked. Every entity marker is now a pin whose tail points just above its
coordinate. Selecting one scales its frame up and shows the dot at the
exact location. Cluster bubble avatars keep their plain frames.

* Keep the map overview selection in browser history

The card remembered a single camera to restore from the overview's back
button, so after selecting one entity and then another the original view
was lost, and back from the second left the map zoomed on the first while
the overview showed the list. The selected entity now lives in the URL as
an entity_id query parameter; selecting pushes a history entry, and so
does deselecting, whether from the overview's back arrow or a click on
the map, so the browser's back and forward step through every selection.
The overview's arrow itself always returns to the list. Selecting focuses
the entity; deselecting leaves the map where it is. Only selectable
domains are accepted from the URL; anything else is dropped from it. The
saved camera, the animated setView and the autoFit view flag had no
other users.

* Pan to a selected map entity instead of zooming in on it

Focusing a person jumped to zoom 19 and a zone fitted its circle, which
often zoomed much further in than the user had been. Selecting now keeps
the current zoom and pans the entity into the free part of the view. It
only zooms in when another marker sits within 80 screen pixels, and then
just far enough to clear it, capped at zoom 17. Markers at the very same
position cannot be separated by zooming and are left alone. A zone is
fitted as its whole circle with a little room around it under that same
zoom cap, so a zone that fits the view keeps the zoom and a bigger one
zooms out just enough. A marker already on screen eases over; one off
screen flies there in an arc. Fits gain a fly option for this, and every
other fit now eases straight to its bounds on both engines, where
MapLibre used to fly. Map-engine gains pixelDistance, the Web Mercator
screen distance at a zoom level, with a test for its scale.

* Float every cluster bubble above its location

Only a bubble attached to a zone had a tail and hung above the zone's
circle; a bubble of nearby markers sat centered on the cluster, hiding the
spot it stood for. Every bubble now has the tail and floats above its
location with the same lift as a single marker's pin, so the two read as
one style. A zone's bubble keeps floating above the zone circle.
2026-10-07 10:09:07 +02:00
Matthias AlphartandClaude 87166c98dc Sort selected weekdays in time trigger and condition (#54623)
Co-authored-by: Claude <[email protected]>
2026-10-07 09:16:10 +02:00
Artur Pragacz 89c333894d Consider next name part when unprefixing entity name (#54633)
* Consider next name part when unprefixing entity name

* Adjust
2026-10-07 08:39:45 +03:00
karwosts d994db64cb Fix script duplication (#54637) 2026-10-07 08:20:57 +03:00
renovate[bot] d6a3c6efcc Update dependency @versatiles/style to v6.1.1 (#54629)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-07 05:01:37 +00:00
Paul Botteinandcopilot-swe-agent[bot] ce58026788 Fix section editor crash while typing a strategy in YAML (#54622)
* Fix section editor crash while typing a strategy in YAML

* Reject array-valued section strategies in YAML

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-07 04:59:26 +00:00
2e09d1a43b Correct system and diagnostics API types in the frontend (#54290)
* Correct system and diagnostics API types in the frontend

Compare the system health, log, repairs and related data modules with
the handlers that produce them, and fix the mismatches.

The system health failure detail was read from a key that does not
exist, so a failed check rendered blank. Repairs issues carry several
always-present nullable fields and no active flag. Saving the core
config and ignoring a repair return nothing, and the icon types were
missing a nesting level.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

* Surface the HTTP fallback port and the failure reason

Warn separately when the server fell back to the previous default
port, which the saved configuration warning did not cover.

Show the diagnostic message a failed configuration carries, and fall
back to the error code when there is none.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-07 06:52:57 +02:00
WendelinandClaude Opus 5.5 45e2392eeb Fix leaked WebRTC peer connections in ha-web-rtc-player (#54557)
* Abandon superseded WebRTC starts to avoid leaking peer connections

If ha-web-rtc-player was disconnected (or restarted) while awaiting the
WebRTC client configuration, the start continued afterwards and created
an RTCPeerConnection that nothing ever closed.

Track a start id that is bumped on every clean up and bail out when a
start has been superseded. Negotiation now also checks that it still
belongs to the current peer connection.

Fixes #54482

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014ZzvX8SAHt1knzzJNULtZx

* Bind WebRTC signaling callbacks to their own peer connection

Events of an offer subscription that belongs to a superseded start could
still reach the current stream before the unsubscribe completed, sending
candidates to the old session or applying the old answer to the new
offer. Ignore events whose peer connection is no longer the current one,
and don't report errors from operations rejected because a superseded
connection was closed.

Also show an error instead of leaving an unhandled rejection when
fetching the WebRTC client configuration fails.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014ZzvX8SAHt1knzzJNULtZx

* Localize WebRTC player errors and handle rejected offer subscriptions

Error messages of ha-web-rtc-player were hardcoded English strings. They
are now stored as an error type plus the backend message and localized
when rendering.

The try/catch around webRtcOffer() never caught anything because the
subscription returns a promise, so a rejected offer left an unhandled
rejection and no error. Handle the rejection, and don't let clean up
re-raise it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014ZzvX8SAHt1knzzJNULtZx

* Rename WebRTC start id to clean up count

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014ZzvX8SAHt1knzzJNULtZx

* Don't start a WebRTC stream on a disconnected player

Lit still runs a pending update after the element was disconnected, so
a player added and removed in the same task (or given a new entityid
after removal) started a stream after its last clean up, which nothing
closed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_014ZzvX8SAHt1knzzJNULtZx

---------

Co-authored-by: Claude <[email protected]>
2026-10-07 06:52:10 +02:00
renovate[bot] b0c5ea6296 Update pnpm to v12.9.1 (#54635)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-07 06:49:20 +02:00
renovate[bot] c0204eeb25 Update dependency maplibre-gl to v6.12.0 (#54636)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-07 06:49:03 +02:00
59444f72bc Add a gallery page for ha-picker-combo-box (#54588)
* Add a gallery page for ha-picker-combo-box

The picker combo box is only ever seen inside a popover or dialog, which
makes its two render paths and two row highlights hard to inspect. This
page renders it directly in four states: a plain list under the
MAX_PLAIN_LIST_ITEMS threshold, a virtualized list of 200 items, an empty
list, and one with a current value pinned into view.

The component takes no hass, so the page provides internationalizationContext
directly rather than going through a fake hass object.

Co-Authored-By: Claude Opus 5 <[email protected]>

* WIP - combobox gallery

* Tighten the picker combo box gallery text

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Improve documentation for ha-picker-combo-box

Clarified rendering behavior and filtering logic in the documentation. Updated keyboard shortcuts and added information about selected sections.

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Fix Prettier formatting in picker combo box gallery page

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-10-06 13:52:15 +00:00
Petar Petrov 6856449bd3 Drop hass from the home summary card (#54606)
* Drop hass from the home summary card

The card consumes the contexts it reads and computes its summary text
from statesContext, so it only re-renders when the text changes. It
subscribes to the energy collection through EnergyCollectionController,
which gains a beforeSubscribe hook to set today's period, and fires
hass-action like the button card. isSecurityAlertActive and the battery
filters take the values they need.

* Test isSecurityAlertActive against every alert domain
2026-10-06 15:42:24 +02:00
Petar Petrov 9fa168e22c Pass registries to generateEntityFilter as separate values (#54605)
generateEntityFilter takes states, entities, devices, areas and floors
instead of a hass-shaped object, so callers without hass can use it.
2026-10-06 15:24:18 +02:00
Marcin BauerandClaude Opus 5.5 6d6aaecb39 Remove no-op refresh button from activity panel (#54620)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-06 15:20:22 +02:00
Jump-333 d9f2baeeb4 Add badge for the wait for a template row (#54529)
* Add badge for the wait for a template row

* Removed literal text filter
2026-10-06 15:35:55 +03:00
Aidan Timson 234eb800bb Fetch nightly translations artifact directly with retry backoff (#54574)
* Fetch nightly translations artifact directly with backoff

* Type nightly translations fetch and use shared retry helper

* Retry GitHub API calls in workflow scripts
2026-10-06 15:27:36 +03:00
Wendelin 40c76b3993 Upgrade webawesome to version 3.14 (#54616)
* Upgrade @home-assistant/webawesome to version 3.14.0-ha.0 in package.json and pnpm-lock.yaml

* Update bundle size budget for frontend-modern and frontend-legacy
2026-10-06 15:11:29 +03:00
WendelinandClaude 7ca12940d9 Increase touch area of ha-checkbox (#54617)
Co-authored-by: Claude <[email protected]>
2026-10-06 13:11:20 +01:00
Aidan Timson 19630745d8 Follow webawesome fork releases in Renovate (#54619) 2026-10-06 12:08:17 +00:00
Marcin BauerandClaude Opus 5.5 69f83e0ddc Move dashboard edit mode help button to the overflow menu (#54608)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-06 14:34:55 +03:00
Marcin BauerandClaude Opus 5.5 afac5d6e56 Add undo action to cut toast in automation editor (#54612)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-06 13:19:41 +02:00
Aidan Timson c40846ada7 Skip release delay for first-party packages (#54614) 2026-10-06 13:18:24 +02:00
Bram KragtenandClaude 388c4f856b Simplify CI workflow: make build depend on lint and test (#54609)
Co-authored-by: Claude <[email protected]>
2026-10-06 12:09:47 +01:00
Aidan Timson 7051fd27f7 Add a custom repositories page to the Marketplace (#54604)
Manage custom Marketplace repositories on their own page
2026-10-06 12:27:42 +03:00
Jonathan 6fca7a89b6 Show the requested run when a trace page switches item (#54591) 2026-10-06 11:26:46 +02:00
Wendelin 121b3dade7 Fix HaChipBase border radius (#54603)
Add border-radius to HaChipBase styles for improved appearance
2026-10-06 12:19:56 +03:00
Marcin BauerandClaude Opus 5.5 5a5611df6b Load History and Activity results only after closing the sources sheet on mobile (#54602)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-06 11:05:39 +02:00
Paul Bottein a7c435e1a0 Show referenced triggers instead of generated IDs in automation and trace descriptions (#54587) 2026-10-06 10:52:45 +02:00
Petar Petrov 8bc7ab0e74 Drop hass from the energy total badges and the statistics graph card (#54590)
The badges and the card subscribe to the energy collection through
EnergyCollectionController and consume contexts for everything else.
statistics-chart moves to contexts with them and regenerates on a theme
change. The controller unsubscribes when config() returns undefined, so
turning energy_date_selection off stops the subscription.
2026-10-06 09:40:38 +01:00
Bram KragtenandClaude Opus 5.5 5ca2ac68a3 Use standard Apache 2.0 license text so GitHub detects it (#54599)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-06 10:35:17 +02:00
Petar Petrov eb43b1eab8 Migrate energy, power, gas and water cards to context instead of hass (#54560)
* Migrate energy, power, gas and water cards to context instead of hass

The cards consume only the context slices they read. A new
EnergyCollectionController replaces SubscribeMixin for the energy
collection subscription. ha-chart-base, ha-sankey-chart and
hui-energy-period-selector move to contexts too, and the energy and
recorder helpers take Pick<HomeAssistant, ...> slices.

* Inline the energy collection Pick type

* Pass values instead of hass-shaped objects to energy and recorder helpers

The helpers take states, formatEntityName, callWS, locale or panelUrl
directly. getEnergyDataCollection takes the connection plus an options
object, since it needs several inputs.

* Use consumeContext in EnergyCollectionController

The controller extends ContextController and declares its consumed
values as decorated fields instead of wiring each subscription by hand.

* Consume the internationalization context once in energy cards and charts

ha-chart-base, the period selector and the energy cards read both
localize and locale, so they consume the whole context as _i18n
instead of subscribing to it twice.

* Drop the connected-host guard from EnergyCollectionController

ContextController now defers its setup on connected hosts, so the
controller no longer needs to guard against running before its options
are set.
2026-10-06 10:27:06 +02:00
Petar Petrov 96684da7a7 Add a consumeContext decorator for reactive controllers (#54575)
* Add a consumeContext decorator for reactive controllers

Controllers extend ContextController and decorate their fields with
consumeContext({ context, subscribe, transform }). The base class keeps
each field current and calls contextUpdated() only when the transformed
value changes. ServiceInfoController uses it instead of its own
ContextSubscriptionController wiring.

* Defer context setup on connected hosts and check consumeContext fields

A controller created on a connected host no longer runs subclass code
from super(): Lit calls hostConnected() from addController(), so the
subscriptions are set up after construction instead. consumeContext
also rejects public fields that cannot hold the stored value, like
@consume does.
2026-10-06 10:08:11 +02:00
WendelinandClaude Sonnet 5.5 13e9127bdb Fix config entry state styling (#54584)
* Restore needs attention color on config entry rows

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Restore config entry row state styling

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Highlight config entry state with border color instead of tint

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Add quiet fill background to config entry states

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Use semantic colors for config entry state borders

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Drop state border colors and use semantic text colors

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Use semantic color for config entry link icon

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Add divider between discovered and attention flow rows

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Use semantic border and fill colors for discovered and attention lists

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Use warning colors for discovered list too

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Use standard divider color for flow list borders

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Use border width token for flow list borders

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* Restore warning icon color for failed unload state

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01PMDcr7YWpvXhByiZZqoeAc

* review

---------

Co-authored-by: Claude <[email protected]>
2026-10-06 09:59:54 +02:00
karwosts 9a45b6a200 Cleanup multiple unnecessary usages of entitySources (#54556)
* Cleanup multiple unnecessary usages of entitySources

* performance

* don't need entitySources for device integration

* memoize and filter device integration lookups

* Fix race condition fetching config entries

* Gate deviceIntegratonLookup in selector.ts on integration filter
2026-10-06 09:56:57 +03:00
Einar Skreslett a3f5929ddd Fix invisible inherited label tooltip text colour (#54521)
* fix invisible inherited label tooltip text colour

* fix tooltip while keeping theme text colour
2026-10-06 05:51:42 +00:00
Aidan Timson 0fed256025 Use context in Marketplace, prepare shared layouts for future context migrations (#54566)
* Read config and translations from context in shared layouts

* Use context instead of hass in Marketplace pages

* Provide contexts in Marketplace and tabs subpage tests

* Use provideHass for the Marketplace dialog test host

* Pass entities to tab page filters

* Update tab filters when entities change

* Fall back to hass localize in error screen

* Note when to inline error screen localize
2026-10-06 08:35:04 +03:00
ae3b3eefb3 Forward OAuth authorization parameters to the login flow (#54548)
* Forward OAuth authorization request parameters to the login flow

* Defer OAuth resource forwarding to a separate change

* Test preservation of empty PKCE parameters

* Do not forward state to the login flow

Core does not use state. The frontend appends it to the redirect
after the login flow finishes. The createLoginFlow type excludes
state, because Core rejects unknown fields.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Reduce the login flow change to forwarding response_type

Keep the positional createLoginFlow signature, the existing property
and import order, and the existing tests. Forward response_type and
send empty PKCE values instead of dropping them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-06 08:33:40 +03:00
renovate[bot] 1e9d0432b3 Update dependency eslint to v10.12.0 (#54593)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-06 06:58:30 +02:00
renovate[bot] 60027ef4b1 Update pnpm to v12.9.0 (#54594)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-06 06:48:33 +02:00
Paul Bottein 5b25a220df Treat an entity name equal to its device name as no own name (#54585)
* Treat an entity name equal to its device name as no own name

* Use the same device name check when computing entity names

* Only check the user-set name against the device name

* Add tests for the device name check

* Clarify why only the user-set name is matched loosely
2026-10-05 18:54:27 +02:00
Paul Bottein 74c44e7c71 Fix first badges cut off in centered scrolling view header (#54565) 2026-10-05 18:50:36 +02:00
Paul Bottein 7b6561491a Fix option labels overflowing horizontal control selects (#54582) 2026-10-05 15:38:32 +00:00
Paul Bottein 17e0352ecf Show then branch before else in trace graph (#54583) 2026-10-05 17:03:31 +02:00
Maarten Lakerveld 7b379d587c Bump home-assistant-js-websocket to 9.7.1 (#54577)
Exclude our own packages from the 3-day minimumReleaseAge rule so
fixes we publish ourselves can be picked up immediately. The
no-downgrade trust policy still rejects unsigned releases.
2026-10-05 16:54:43 +02:00
Paul Bottein 6b32c87702 Fix map history paths flickering on every update (#54573)
Update map paths and zone circles in place instead of redrawing them
2026-10-05 15:40:34 +03:00
Jan-Philipp Benecke 2482b47d0b Hide dangling trace graph connectors when nothing follows (#54568) 2026-10-05 13:53:55 +02:00
Wendelin e9507ad201 Fix styling for config entry device rows (#54570) 2026-10-05 12:29:17 +01:00
Paul Bottein c26790e54d Add light color card feature with hue scrubber (#54219)
* Add light color card feature with hue scrubber

* Keep only the hue example in the scrubber gallery page

* Fix cancel event, card suggestion and white light hue in light color feature

* Update saturation gradient live while dragging hue

* Send terminal slider-moved after keyboard changes in scrubber

* Fix End key in wrap mode and keep focus when swapping light color controls

* Center collapsed hue preview on current hue and animate scrubber wrap by shortest path

* Hide the light color indicators when the light has no color
2026-10-05 12:16:16 +02:00
Aidan Timson 7eeca385a8 Shorten Marketplace warning countdown in development (#54564) 2026-10-05 11:55:17 +02:00
0149516743 Highlight the picker row that Enter would pick (#54319)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Wendelin <[email protected]>
2026-10-05 11:54:25 +02:00
karwosts a270426d98 Show entity diagnostic in a readonly editor w/ copy button (#54536) 2026-10-05 12:26:05 +03:00
Wendelin f8d70893a1 config-area-page fix missing list-item import (#54563) 2026-10-05 09:25:46 +00:00
karwosts 2cc6112d6f Fix stale missing entities in target picker (#54544) 2026-10-05 12:10:13 +03:00
Jason Hunter bfe09bd2e7 Preserve OAuth callback state through login and onboarding (#54547)
Preserve OAuth callback state when logging in and resuming onboarding
2026-10-05 09:52:41 +03:00
Jump-333 d1370c8577 Add source names for SoC badges (#54370)
* Add device names for SoC badges

* Fixed reload issues

* Removed useless fallback

* Modified badge name source

* Remove useless check
2026-10-05 08:19:33 +03:00
renovate[bot] 430890f401 Update dependency @types/node to v24.19.1 (#54553)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-05 07:05:29 +02:00
renovate[bot] ba536e13e7 Update home-assistant/actions digest to 06749dd (#54552)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-05 07:05:10 +02:00
renovate[bot] 4278d16a62 Update github/codeql-action action to v4.38.2 (#54555)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-05 07:04:46 +02:00
renovate[bot] 1c28b7fef1 Update dependency globals to v17.13.0 (#54539)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-04 21:04:49 +02:00
renovate[bot] f867b6186f Update dependency vite to v8.3.2 (#54541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-04 19:50:00 +02:00
Paulus SchoutsenandClaude Opus 5.5 7432e63c16 Show the Marketplace risks alert full width without an icon (#54540)
* Show the Marketplace risks alert full width without an icon

The risks alert spans the full card width, so it reads as a band in the
card. The text aligns with the card content. The alert icon is hidden
because the heading already shows a large warning icon.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wt676c2KAQ1NnNWNRm7dV5

* Scope the full-width alert styles to the risks alert

The error alert for a failed acceptance keeps its icon, corners and
padding.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wt676c2KAQ1NnNWNRm7dV5

* Start-align the Marketplace warning heading and intro

The heading and intro line up with the risks and the checkbox below
them. The warning icon stays centered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wt676c2KAQ1NnNWNRm7dV5

---------

Co-authored-by: Claude <[email protected]>
2026-10-04 19:49:40 +02:00
Paulus SchoutsenandClaude 0bda4a13ca Add the Marketplace to the demo (#54546)
The demo registers the Marketplace panel and mocks its read commands.
A list of community repositories shows on the discover, browse and
installed pages, and each repository has its own page. The warning
screen is skipped.

The mocks load with the config panel chunk. A loaded Marketplace config
entry lets the panel start. Commands that change the Marketplace, such
as install and uninstall, are not mocked.


Claude-Session: https://claude.ai/code/session_01Wt676c2KAQ1NnNWNRm7dV5

Co-authored-by: Claude <[email protected]>
2026-10-04 19:48:24 +02:00
karwosts dd0a0df88f Fix max_columns number selector (#54542) 2026-10-04 15:51:41 +02:00
renovate[bot] 6775b1e2bb Update vitest monorepo to v5.0.3 (#54535)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-04 08:56:20 +02:00
renovate[bot] 06df4046a9 Update pnpm to v12.8.2 (#54538)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-04 08:56:16 +02:00
renovate[bot] 634b6ddfcd Update dependency browserslist to v4.29.3 (#54531)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-03 08:06:47 +02:00
Paulus SchoutsenandClaude 970bb12856 Hide MCP URL hint until the server is enabled (#54532)
When the MCP server is not set up, the card has no URLs to show.
The description told the user to add one of the URLs below. Show
only the documentation link until the server is enabled.


Claude-Session: https://claude.ai/code/session_01MeyiXPWWRNRpD2XHVrtPSr

Co-authored-by: Claude <[email protected]>
2026-10-03 08:06:41 +02:00
Jan-Philipp Benecke c03750e605 Handle undefined trigger condition IDs in rendering (#54527)
* Handle undefined trigger condition IDs in rendering

* Handle trigger conditions without ID in editor and updates
2026-10-02 16:41:55 +02:00
Maarten Lakerveld 655e11ac1c Keep padded map fits within the poles (#54526)
The MapLibre engine pads a fit by a fraction of its span. A zone whose
circle reaches a pole, or markers far apart, pushed the padded
latitude past 90, and MapLibre throws on such bounds, so the fit never
happened and the console filled with errors. The padded latitude is
now clamped to the poles.

Fixes #54498
2026-10-02 15:03:02 +02:00
Paul Bottein b25cf13401 Add signed and offset modes to the duration selector (#54111)
* Add signed and offset modes to the duration selector

* Remove translation key from the duration selector

* Address review comments on the duration selector

* Expose the duration selector mode in the selector editor

* Remove allow_negative from the selector editor

* Migrate allow_negative to mode when editing a duration selector

* Derive the magnitude of mixed-sign legacy durations from their total

* Test the duration sign and value helpers

* Merge the duration sign helpers into normalizeDuration

* Omit the negative flag for positive signed durations

* Keep the pending offset type in local state instead of writing negative false

* Keep the offset type when the duration is cleared to zero

* Rename the offset type state

* Address remaining Copilot comments on the duration selector

* Simplify the duration sign handling

* Reset the offset type when the duration changes from outside

* Translate the duration selector mode in the selector editor

* Write negative durations as negative components instead of a negative key

* Simplify duration sign handling around a single normalizeDuration

* Keep the offset type as local state and refresh duration fields with live

* Forget the emitted duration after an external change

* Keep the duration sign at zero and use selector units everywhere

* Simplify duration sign handling and compute typed negative values

* Hide the clear button of offset durations
2026-10-02 09:02:45 +00:00
Wendelin 24c3ab6061 Use optional short issue title localization to repairs dialog (#54506)
Add short issue title localization to repairs dialog
2026-10-02 07:52:22 +00:00
Bram KragtenandClaude Opus 5.5 2c73378e9d Cache map tiles per asset class and stop refetching what still works (#54451)
* Cache map tiles per asset class and stop refetching what still works

The service worker kept glyphs, sprites and tiles in one 500-entry LRU, so
panning around evicted the fonts that every label on every map needs. Glyphs
and sprites move to a cache of their own, on the 30 day age core already sends
them with, and the tile ceiling goes up.

The TileJSON was deliberately left on the network because it is the switching
point for the tile source. Every map waits on it before asking for a tile
though, and at a five minute max-age that is a round trip before the first one.
Served stale-while-revalidate instead: out of the cache immediately, refreshed
behind it, so a moved endpoint still arrives.

The raster fallback redrew on every token rotation, refetching every tile on
screen twice an hour whether or not anything had failed. Later tiles pick up a
new token by themselves, so only a layer that actually had one refused needs
asking again - and since a refused tile is the only sign that path gets that
its token is stale, it now asks for a new one instead of waiting for the
refresh interval to come round.

Style requests that are in flight are shared, so a dashboard of maps, or a
theme toggle switching all of them at once, fetches each style once. Only while
in flight: a settled request is dropped, or a style that failed once would
never be fetched again.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Hand the raster fallback the current map tiles token

A rotation is only announced once, so a vector layer that later falls back
handed the raster layer the token it was created with, and the refresh that
follows a refused tile fetches the already-current token and announces
nothing. The vector layer now tracks rotations itself.

Also covers in-flight style sharing, and passes a map style rather than
`false` in the raster recovery tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-10-02 09:50:33 +02:00
Paul Bottein d8e09dd120 Show entered and left in map zone activity (#54516)
* Show arrived and left in map zone activity

* Use entered instead of arrived in map zone activity
2026-10-02 07:49:26 +00:00
Jan-Philipp Benecke 6cdfafcbf9 Fix misplaced trace graph icons on iOS (#54520) 2026-10-02 09:40:29 +02:00
Elias Lecomte 4819cd6d27 Fix long source name overflow in energy dashboard totals (#54522)
* Fix long source name overflow in energy dashboard totals

* style: format with prettier
2026-10-02 09:39:16 +02:00
karwosts c5f099dab7 Remove spurious color clear button (#54515)
* Improve number selectors in section settings

* Fix sections editor default color
2026-10-02 09:33:42 +02:00
renovate[bot]andSimon Lamon 2da41b6e59 Update dependency zxing-wasm to v3.1.4 (#54480)
* Update dependency zxing-wasm to v3.1.4

* Update type-fest version to 5.10.0

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Simon Lamon <[email protected]>
2026-10-02 09:27:41 +02:00
renovate[bot] b7bb487208 Update pnpm to v12.8.1 (#54523)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-02 08:11:53 +03:00
renovate[bot] dfaf2a6f72 Update dependency @types/luxon to v3.7.6 (#54525)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-02 08:10:43 +03:00
renovate[bot] 8639ccde06 Update dependency typescript-eslint to v8.71.0 (#54517)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-01 20:07:31 +02:00
ee67f6b99f Add dependency review workflow (#54490)
* Add dependency review workflow with npm metadata checks

* Temporarily run dependency review on push

* Remove temporary push trigger from dependency review

* Encode the full package name in npm registry URLs

* Check optional/peer dependencies and fail on npm registry errors

Co-authored-by: timmo001 <[email protected]>

* Convert npm metadata check to TypeScript

* Type workflow scripts with Node 24 types instead of DOM

* Detect npm alias target changes as new dependencies

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-10-01 20:02:11 +02:00
renovate[bot] e569664724 Update dependency @rspack/core to v2.2.8 (#54514)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-01 19:58:07 +02:00
Maarten Lakerveld c113eb1f9a Fix map overview tabs, activity timeline, cluster counts, zone fit and the new-zone route (#54512)
* Show four avatars in a cluster bubble before counting

A bubble capped at three avatars added a +1 chip for the fourth
member, taking a fourth slot to hide one avatar. Four members now show
as four avatars; from five on, three avatars and a count fill the same
four slots.

* Open the new zone dialog on every visit to /config/zone/new

The route was only handled in firstUpdated. The config panel is kept
alive between visits and the router reuses the zone page when it is
already the current one, so "Create zone from current location" did
nothing once the zone list had been opened earlier in the session. The
route is now handled on every route change, like /edit/ already was.

The dialog also opened before the more-info dialog it was launched
from had finished leaving the history, and that departure closed the
new dialog again. The page now awaits the replace navigation, which
waits for closing dialogs, before opening it.

* Hide the map overview while the dashboard is being edited

In panel view edit mode the map card kept rendering its overview. On
phones that is a bottom sheet fixed over the bottom of the screen,
which covered the card's edit bar and the view's add button, so the
map dashboard could not be edited in portrait. The overview is for
using the map, not configuring it, so it is left out while editing.

* Show only the overview tabs that have something to list

People and Zones were always offered, with an empty message when the
map card's entities held none of them; only Devices was hidden when
empty. All three now appear only with entries, the first remaining tab
takes over when the selected one empties, and the overview tells the
card so its marker filter follows. The empty-tab messages are gone
with the empty tabs.

* List the person of the current user first, as "Me"

The overview's People tab sorted everyone alike. The person linked to
the user looking at the map now comes first and is named "Me" in the
list and the detail header, through a localized string. Their initials
still come from their real name.

* Draw the overview activity as a timeline

The activity list reused logbook rows: the person's name on every row,
the state pushed to the right, dividers between rows. It is now a
timeline of its own. Each row names where the person went, with the
clock time and how long ago underneath, hung off a dot in the zone's
color with a rail to the next row. A zone's rows name who came or
left and where they are. Five rows show at first, with a "Show more"
button for the rest. The overview no longer needs the broad hass
object, which only the logbook row took.

* Fit the map to its zones when they are all it shows

Zones only joined the auto-fit with the fit_zones option. The panel
map does not set it, so on the Zones tab, with no people or devices
left, the fit found nothing and jumped straight to the home
coordinates at the default zoom. Zones now stand in whenever nothing
else is on the map, which goes through the animated fit like the
other tabs. With fit_zones they still join a fit of people and devices.
2026-10-01 17:56:01 +02:00
Franck Nijhof 1f98d6ef6b Add Marketplace panel (#54437)
* Add store panel as a copy of the HACS frontend

Verbatim copy of src/ from hacs/frontend at d97dce0 into src/panels/store. Imports still point at the HACS submodule layout and the iframe shell is still present; this is the baseline for the port.

* Rewrite store panel imports and drop the iframe shell

Every import that pointed at the old `homeassistant-frontend` submodule now
resolves inside this repository's `src/` tree. Five components were renamed or
removed upstream, so they point at their current equivalents: `ha-button-menu`
and `ha-menu` to `ha-dropdown`, `ha-md-menu-item` to `ha-dropdown-item`,
`ha-fab` to `ha-button`, and `ha-circular-progress` to `ha-spinner`. The
`@material/mwc-button` and `@material/mwc-linear-progress` side-effect imports
are gone with them; those packages are no longer dependencies here.

`main.ts` becomes `ha-panel-store.ts` and registers `ha-panel-store`. It now
receives `hass`, `narrow`, `route` and `panel` from the panel resolver, so
everything that only made sense inside an iframe is removed: applying themes to
the parent element, forwarding haptic and keydown events to the main window,
bridging `location-changed`, the document-level navigation click handler, the
dialog manager, the injected body stylesheet, and the redirect to the default
route. `entrypoint.ts`, `extra.ts`, `html/` and `version.ts` are deleted for the
same reason.

* Move store panel translations into the frontend translation tree

The panel's own translation bundle is gone. Its keys now live under
`ui.panel.store` in `src/translations/en.json`, and `panel.store` gives the
sidebar its "Community store" title. Every `hacs.localize("some.key")` call
became `hass.localize("ui.panel.store.some.key")`, which means the `localize`
member on the `Hacs` interface, the `HacsLocalizeKeys` type and the localize
bootstrap in `HacsElement` are no longer needed. `TranslationDict` is derived
straight from `en.json`, so the moved keys type-check without any casts.

`dialog_about.frontend_version` did not come along: its only consumer was the
frontend version constant that went away with the iframe shell.

* Hold store panel state in the panel instead of a HACS mixin

The panel element now owns the repository list and the info payload as
internal state, loads both on first update and refreshes them from the
store/subscribe signals through SubscribeMixin. That drops the
HacsElement base class and its logger, so the hacs object handed to the
child components is plain data. Children that used to patch that object
with an update-hacs event now fire store-refresh instead and let the
panel refetch.

Also moves every WebSocket command over to the store/ prefix and trims
the info payload to what the backend still returns.

* Update the store panel to current frontend components

Rebuilds the panel on the components the frontend ships today: the
dialogs get their heading from ha-dialog itself and their buttons from
ha-dialog-footer, the overflow menus become ha-dropdown with
ha-dropdown-item, the download action becomes a fab-slotted ha-button,
and the progress and spinner indicators move to ha-progress-bar and
ha-spinner. brandsUrl loses the dropped useFallback option.

Also clears the eslint backlog the panel came in with: no arrow
functions in templates, no console calls, alt text on the brand images,
and private members named consistently.

* Register the store panel and route old HACS paths

Add the store panel to the panel resolver so the backend can serve it,
and move every internal navigation path in the panel from /hacs to
/store. The /hacsfiles static prefix stays, the backend serves it.

Repoint the hacs_repository my-redirect at the store panel and add a
store_repository alias next to it. Both keep the same target, so the
owner, repository, and category parameters still reach the panel's
redirect handler. Existing README badges keep working.

* Rename HACS to Community store in the store panel

Bring the ported panel in line with the repository conventions: panel
parts are ha-*, dialogs are dialog-* with a matching show-dialog-*
helper, and the typo in the overflow menu filename is fixed.

Rename the code identifiers to match, so the panel talks about a store
instead of HACS: StoreData, StoreInfo, StoreDispatchEvent, a store
property on the child elements, storeStyles and --store-* custom
properties.

Reword every user-facing string that named HACS. Backend names stay put:
the hacs_dispatch_* signal values, the /hacsfiles static prefix, the
hacs_repository my-redirect key, and the hacs.xyz documentation and
catalog infrastructure.

The stale HACS-REPOSITORY-PANEL nodeName check now matches the element
it was always meant to match, so removing a repository from its own page
navigates back again.

* Show a message when the store panel is opened without the integration

The panel is registered on every install while the integration is only set up on some, so an empty store must not try to talk to a backend that is not there.

* Link the Community store from the Settings dashboard

The store panel is hidden from the sidebar, so reach it from the Settings dashboard instead and give its pages a way back.

* Fit the store pages into the main layout

The repository page still sized itself to the viewport and the router recoloured the header with sidebar colours, both leftovers from running inside an iframe. Next to the sidebar that made the page a sidebar-width too wide, pushing the toolbar menu off-screen and un-centering the card.

* Let the quick bar create My links for store repositories

The repository page listened for the "m" key on the document body and opened a My link itself, which fought the quick bar's own "m" shortcut once the panel stopped living in an iframe. The quick bar now resolves a store repository page to the hacs_repository redirect by looking up the repository name, and the panel's handler is gone. The reload after installing a dashboard resource no longer goes through the main window helper, and unused scrollbar styles are dropped.

* Remove the external links from the store menu

The About dialog, the issue tracker link and the link to the HACS GitHub organisation pointed at a project outside Home Assistant. The store is part of Home Assistant now, so they go. The documentation link stays until the documentation moves.

* Fix runtime bugs in the store panel

* Remove external HACS leftovers from the store panel

* Tidy types and conventions in the store panel

* Clean up the store panel translations

* Give the store redirect error screen its hass and narrow properties

Without them the screen's back and refresh buttons render without labels.

* Use the store signal names and local resource URLs

The backend renames these in lockstep: the dispatcher signals lose their
`hacs_dispatch_` prefix, and downloaded dashboard resources are served
from `/local/community/` with a `v` cache-busting parameter instead of
the store-owned `/hacsfiles/` route and `hacstag`.

* Drop the disabled reasons the store backend no longer reports

Setup failures now surface through the config entry state instead of a disabled store, so only the runtime reasons remain.

* Rename the Community store to Marketplace

The panel, its elements, dialogs, data types, WebSocket commands,
dispatcher signals and translations now use marketplace, matching the
renamed backend domain. The hacs_repository My link keeps its slug.

* Finish the Marketplace panel

* Confirm replacing a built-in integration with the download

* Fix README links, older versions and grouping in the Marketplace panel

* Handle list continuations and placeholder characters in Marketplace READMEs

- Indented lines inside a list item are treated as text, so their links and issue references get rewritten.
- A README that already contains the private placeholder characters is left alone.

* Keep indented code inside list items literal in Marketplace READMEs

* Fix the warning title, icon colors and dead subscriptions in the Marketplace panel

- The warning takes its title from the Marketplace translations, it is not empty on a direct visit.
- Icons keep the colors of the menu or chip they are in.
- Dismissing new repositories is offered whatever the filters show.
- The dialogs no longer subscribe to an error signal the backend never sends.
- The custom repositories list names the category in the language of the user.

* Handle the edges of the Marketplace panel more carefully

- The warning can be continued again when the panel did not take over.
- Only a query with an owner and a repository opens a repository as a My link.
- Links to /hacs inside Home Assistant open the Marketplace.
- A rate limit after the download dialog closed opens nothing.
- A removed entry takes its catalog with it.
- The quick bar says why it could not make a My link for a repository.

* Type the Marketplace panel against the backend contract

- The data types match what the backend sends.
- Errors are caught as unknown and read through one helper.
- Events are typed from their declarations.
- Spacing uses the theme tokens.

* Make the wording of Marketplace actions clearer

* Leave the way back from the Marketplace warning to the header

* Show the download progress in the Marketplace download dialog

* Offer to set up a newly downloaded integration right away

* Make the Marketplace download dialog plainer and move other versions to the menu

- One sentence says what the download or update does, no paths or technical details.
- Warnings span the top of the dialog, like in the more-info dialog.
- The progress shows where the update dialog shows it, and the button shows it is busy.
- A restart is only mentioned for updates of integrations.
- Choosing another version moved to the repository menu, it opens on its own when the newest version is too new.

* Use the consume decorator of the frontend in the Marketplace dialogs

* Save the Marketplace search, and keep search and filters per session

* Lay out the Marketplace repository page like the other Settings detail pages

* Bring the Marketplace list page in line with the other Settings lists

* Use the standard Settings dialogs, styles and strings in the Marketplace

* Name the Marketplace data helpers like the rest of the frontend and drop the global refresh event

* Center the Marketplace warning and say how long accepting it lasts

* Call it installing in the Marketplace, and set up right after installing

* Use the uninstall command of the Marketplace

* Fix the row menu, the failed setup screen and README links in the Marketplace panel

* Guide uninstalling an integration that is in use, and offer it after deleting the last entry

* Fix reinstalling, filters, stale pages and README handling in the Marketplace panel

* Explain why an integration in use can not be uninstalled

* Test that accepting the warning and uninstalling in use really happen

* Point HACS links and icons at the Marketplace, and clarify its copy

* Share the error message and menu rendering of the Marketplace panel

* Split the long renders of the Marketplace panel

* Treat Marketplace repository ids as strings

* Guide the user after installing or uninstalling from the Marketplace

* Count down before the Marketplace warning can be accepted, and show it only once

* Show what to do next and who made it on the Marketplace repository page

* Title the Marketplace repository page Marketplace and keep signals one line

* Say which Home Assistant a Marketplace repository requires

"Works with Home Assistant 2025.1 or newer" read as a promise it had been tried there. It is a minimum the repository asks for, so say it that way.

* Explain adding to the Marketplace from a GitHub link

The dialog was called "Custom repositories" and opened on a list of them. Someone adding their first one saw an empty list and two bare fields.

It now says what it is for, and that what is added this way is made by the community like everything else in the Marketplace. Both fields say what they want. The list of what was added from links comes after that, under its own heading, and only once there is any.

* Give the Marketplace Discover, Browse and Installed tabs

The Marketplace was one long table, grouped by status. Finding what you have installed, or what waits for an update, meant scrolling past everything else.

Discover opens with what is popular and what changed lately. Each section links to Browse, sorted and filtered the way the section picked from it. The sorting and filters are in that link, so it works in a new tab or when shared too. Browse is the full table, without the grouping. Installed lists only what is installed, and its tab says how many updates wait.

On the tables, the icon shows a check for what is installed and an arrow for what waits for an update. The search says how many items it looks through. Adding from a GitHub link also got its own button in the toolbar.

Tabs take an optional badge for the update count.

* Find out what is added from a link in the Marketplace

The dialog asks only for the link. What it holds is found out when it is added, and only when that does not settle it, the dialog asks for the type, from what it might be.

* Fix races and lost answers in the Marketplace panel

The add from link dialog could add another link than the one it looked at, a See all link followed a second time kept the filters of the first, Retry did not retry a My link, and a My link that finished late replaced the repository opened meanwhile. A /hacs link from a dashboard showed the Marketplace without its translations. Uninstalling after deleting the last entry could hang when it failed, and a failed removal from the list closed as if it worked. Code inside a quote in a README got issue links.

* Tidy up small things in the Marketplace panel

The README was prepared again for every change of an entity, a screen reader heard the name of a tab but not its badge, and four exports and a type member were left from before.

* Show Marketplace errors in the language of the user and refresh less

Errors from the backend are translated with their key and placeholders in
the panel and when offering to uninstall after deleting an entry, with the
message of Home Assistant as fallback. The repository page reloads after
updating its information, since the list does not carry everything it
shows. Repository signals share one list request, with one more after it
when anything changed meanwhile, and Discover parses each date once.

* Fix the Marketplace strings that showed placeholders and wrong plurals

The add repository question showed {repository} literally, the quotes
around it escaped the placeholder. Seconds, downloads, stars and issues
now say one instead of ones, the status names match across the list and
the repository page, and the GitHub and log messages read the same as
the rest.

* Handle the review of the Marketplace panel

Links to /hacs reach beforeRender again, a route alias was resolved
before it. A refetch on a signal no longer opens the GitHub dialog by
itself, a failed release list is told once, and a failed first load is
translated without logging to the console. Deleting an entry only offers
the uninstall for custom integrations, after the restart and credential
prompts. The YAML resource address carries the version and is encoded.
Applied links mark their history entry instead of listening on the
window, and the last updated column sorts on a number.

* Rewrite Marketplace README addresses once they are rendered

ha-markdown gets an optional rewriteUrl, which runs over every link and
image of the rendered HTML in an inert template, before anything loads.
The README of a repository uses it, so reference links, entities and
unquoted attributes no longer slip through as addresses on Home
Assistant. The regular expressions that set aside links and addresses
for issue references only start where those can start, a README with a
long word or many unclosed links no longer freezes the page.
2026-10-01 11:19:21 -04:00
renovate[bot] e01f5b830f Update dependency @versatiles/style to v6.0.3 (#54509) 2026-10-01 15:45:05 +01:00
Petar Petrov b85cd00cc8 Detect the ESPHome Z-Wave discovery flow by the device MAC (#54513) 2026-10-01 16:44:38 +02:00
Paul Bottein e63fe4d631 Fix area switch for entities without their own name (#54503) 2026-10-01 15:30:53 +02:00
Aidan Timson d24d9d6051 Replace ha-ripple Material base with own implementation (#54508)
* Replace ha-ripple Material base with own implementation

* Remove ha-ripple origin comment

* Restore ha-ripple control setter and CSS zoom handling

* Defer ha-ripple forced-colors check to event handling
2026-10-01 15:10:44 +02:00
Bram Kragten 6c882f47bb Resolve split devices in the logbook card (#54507) 2026-10-01 14:59:12 +02:00
Petar Petrov 3689442f43 Fix double side padding around more-info history and activity (#54511) 2026-10-01 14:16:18 +02:00
Bram KragtenandClaude Opus 5 d19635b6bd Draw the globe against a sky when the map is zoomed out (#54485)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-01 14:14:40 +02:00
Bram KragtenandClaude Opus 5 6ef7072e08 Add ha/no-unused-element-import lint rule (#54210)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-01 13:27:03 +02:00
renovate[bot] 36829e0e05 Update dependency browserslist to v4.29.2 (#54504)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-01 11:46:51 +02:00
574c89b5fd Update dependency sortablejs to v1.15.7 (#54476)
* Update dependency sortablejs to v1.15.7

* Move sortablejs patch to 1.15.7 and update lockfile

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: timmo001 <[email protected]>
2026-10-01 12:34:39 +03:00
4384336476 Migrate combo box item to new lists (#54453)
* Move pickers onto the new list components

Pickers, the quick bar, the automation element search and the card
picker entity tree now use ha-list-base and its item family instead of
Material Web list items.

- Add a virtual-focus mode to ha-list-base and ha-list-virtualized:
  focus stays in a search field and the list marks the active row.
- Render picker rows as ha-list-item-option, with the current value as
  the selected option.
- Make ha-combo-box-item a presentational row layout on ha-row-item.
- Render ha-picker-field as a native button with the clear button next
  to it.
- Let held arrow keys repeat in pickers and the automation search.
- Fix list items not unregistering after they leave the DOM, and an
  unhandled rejection when a virtualized list is removed mid-layout.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Fix section titles

* fix e2e

* mage entity tree search like picker and automation

* remove comments

* fix picker field aria label

* fix disabled field style selector

* Update src/components/ha-picker-combo-box.ts

Co-authored-by: Petar Petrov <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Petar Petrov <[email protected]>
2026-10-01 08:46:56 +00:00
Paul Bottein bc5eb1af2d Give zones their own map colors and prefer white zone icons (#54499)
* Give zones their own map color sequence

* Prefer white zone icons when contrast allows
2026-10-01 10:43:10 +02:00
renovate[bot] 6c81951d88 Update pnpm to v12.8.0 (#54502) 2026-10-01 09:23:18 +01:00
renovate[bot]andPetar Petrov 36b31d2c50 Update dependency tinykeys to v4.0.1 (#54479)
* Update dependency tinykeys to v4.0.1

* Move tinykeys patch to 4.0.1 and update lockfile

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Petar Petrov <[email protected]>
2026-10-01 10:06:16 +02:00
Aidan Timson e98710867f Ignore .pnpm-store directory (#54500) 2026-10-01 07:55:01 +00:00
renovate[bot] b5afb05d7b Update dependency @lezer/highlight to v1.2.5 (#54501) 2026-10-01 07:53:56 +00:00
Aidan Timson 3f882c9a9b Type check workflow scripts (#54494)
* Convert workflow scripts to TypeScript

* Type check workflow scripts in lint:types
2026-10-01 08:39:21 +01:00
renovate[bot] 94c7d6e20a Update dependency @versatiles/style to v6.0.2 (#54497)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-10-01 08:25:05 +03:00
Bram KragtenandClaude Opus 5 8acc456dfd Hash the pnpm patches directory in the rspack cache version (#54478)
The persistent cache version still hashed `.yarn/patches`, which moved to
`patches/` in #54392. The lookup is guarded by `existsSync`, so it failed
silently and patch contents stopped contributing to the version at all.

That hash is the only thing that notices a patch change: a patch alters a
package's files but not its version, which is all rspack's node_modules
snapshot checks. Editing a patch therefore left the cache version
identical and the build reused stale compiled modules.

Co-authored-by: Claude Opus 5 <[email protected]>
2026-10-01 08:22:39 +03:00
Tom Mittelstädtand1358 d68a113f4c Give tentative calendar events a striped background (#54483)
* Give tentative calendar events a striped background

A tentative bar gets a light fill in its calendar color with diagonal stripes in the text color, instead of the outline alone. A tentative dot keeps its color and size and gets stripes in the calendar's contrast color. The stripes set a tentative event apart from past days, which are already drawn faded. They repeat on whole pixels, so every stripe looks the same.

* Strengthen tentative dot stripes and add a forced-colors fallback

The stripes on a tentative dot are its only cue, so they now reach at least 3:1 against the dot. In forced colors the stripes and the dot's fill are dropped, so a tentative bar falls back to a dashed border and a tentative dot to a ring of the same size.

---------

Co-authored-by: 1358 <[email protected]>
2026-10-01 08:21:40 +03:00
karwosts 95a4ca587b Improve number selectors in section settings (#54487) 2026-10-01 08:17:13 +03:00
Jan Čermák f5ac90a1f9 Copy locale data to the landing page build (#54488)
The landing page bundle includes the Intl polyfill. When a browser
needs a polyfill, it loads locale data from /static/locale-data/.
The landing page build never copied that directory, so these requests
returned 404. The language picker then showed raw language codes.

Fixes home-assistant/landingpage#216
2026-10-01 08:14:20 +03:00
renovate[bot] 6b060d3082 Update pnpm to v12 (#54486)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-30 21:41:00 +02:00
Bram Kragten 2f8bdf4260 Bump saturation of the default light mode map (#54492)
bump saturation of the default light mode map
2026-09-30 19:28:52 +00:00
Paul Bottein ee1e27772f Show people and zones on the demo map (#54496) 2026-09-30 21:19:22 +02:00
Bram Kragten d7f8d25a1d Bumped version to 20260930.0 2026-09-30 16:22:54 +02:00
Bram Kragten 33615bc5dc Merge branch 'rc' into dev 2026-09-30 16:21:00 +02:00
Bram Kragten 87105ea76a Fix ha-map crash when themes are not loaded yet (#54489) 2026-09-30 16:13:11 +02:00
Paul Bottein c1ea783993 Fade scrolling badges only where content is hidden (#54469)
* Fade scrolling badges only where content is hidden

* Add tests for the scroll fade controller

* Ignore Safari overscroll when fading scrolling badges
2026-09-30 16:01:10 +02:00
51e8f4792a Migrate chips from Material to Web Awesome (#54124)
* Migrate chips from Material to Web Awesome

* Fix button mock for chip inheritance in config flow tests

* Reflect chip disabled state and test chip interaction contracts

Co-authored-by: timmo001 <[email protected]>

* Delete test/components/chips.test.ts

* Restore legend chip sizing in chart and distribution card

* Skip chip set arrow navigation with a single chip

* Import ha-svg-icon in filter chip

* Improve chip disabled states, icon sizing and focus after removal

* Use toolbar role for chip sets only when labelled

* Drop href from disabled link chips

* Restore toolbar role for chip sets

* Forward referrerPolicy to link chips

Co-authored-by: timmo001 <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-09-30 16:55:06 +03:00
Bram KragtenandClaude Opus 5 e174e924e8 Let users pick and adjust the map style (#54477)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-30 15:54:51 +02:00
Petar Petrov 8c1ef5954a Address review feedback on the ESPHome device setup (#54474) 2026-09-30 14:56:42 +02:00
Maarten Lakerveld 82a6dffe29 Map bug fixes - Show map markers per overview tab, hide markers behind the globe, and cluster bubbling fixes (#54467) 2026-09-30 14:55:40 +02:00
renovate[bot] 8a916c56a5 Update dependency @lezer/common to v1.5.3 (#54475) 2026-09-30 11:44:42 +00:00
Bram KragtenandClaude Opus 5 6834cce8d6 Recolor the default vector map style (#54473)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-30 13:35:13 +02:00
Franck NijhofandClaude 2679d83028 Migrate from Yarn to pnpm (#54392)
* Migrate from Yarn to pnpm

Switch the package manager to pnpm 11, keeping every resolved
dependency version from yarn.lock.

- Move resolutions to pnpm overrides and Yarn patches to patches/
- Enable supply-chain protection: 3 day minimum release age,
  trust policy that blocks provenance downgrades, and dependency
  build scripts denied by default
- Declare dependencies that were imported but only available through
  Yarn's hoisting: zrender, @lezer/common, zxing-wasm,
  @babel/helper-compilation-targets, core-js-compat, @types/geojson
- Look up pinned license overrides in pnpm's node_modules layout
- Update CI, scripts, git hooks, Renovate, and documentation

* Cache the pnpm store with node_modules in CI

Jobs that restore the shared node_modules cache skip the install, so
the pnpm store is empty there. The license file generation runs
`pnpm licenses list`, which reads package metadata from the store and
fails without it.

* Point the demo e2e comment at the real test:e2e:demo script

---------

Co-authored-by: Claude <[email protected]>
2026-09-30 11:32:16 +00:00
Petar Petrov ddd1db7961 Add ESPHome device setup checklist (#53781)
* Add an ESPHome device setup checklist on the device page.

Surface advertised proxy capabilities in a banner and dialog so users can continue Bluetooth, audio, Z-Wave, and serial setup after the device is added.

* Harden the ESPHome setup wizard after review feedback.

Show cached capabilities while offline, wait for user data before the banner, and expose setup status to assistive tech.

* Mark ESPHome serial setup completed when a UART port is in use.

* Mark ESPHome Z-Wave setup completed when zwave_js matches the proxy home ID.

* Align the ESPHome setup wizard with Sendspin audio and the existing add-integration dialog.

Music stays incomplete until Music Assistant is installed and Sendspin is on, and serial setup no longer offers a hardcoded integration list.

* Fix storage chart size labels after bidirectional isolate

bidiIsolate can return undefined, so the gigabyte formatter needs a string fallback for the type check.

* Show the ESPHome setup banner only for music, Z-Wave, or serial devices, and use the finished headline once nothing remains to set up.

* Let the ESPHome music row finish once Music Assistant is installed.

The Sendspin switch is optional and matched by object id, a finished checklist uses the reminder, and the storage chart label matches dev after the bidiIsolate change.

* Give ESPHome music setup its own sequence so Sendspin is enabled after the Music Assistant offer.

* Show ESPHome audio install progress after the offer buttons hide, and drop the guest PIN step until that switch exists.

* Keep ESPHome setup on the device's own Z-Wave and music steps when discovery already started or Music Assistant is cancelled.

A detected controller was treated as not started, cancelling the Music Assistant dialog still enabled Sendspin, and a missing discovery flow opened a generic Z-Wave flow.

* Keep ESPHome setup honest when USB usage or Z-Wave flow lookup fails.

A failed USB scan was shown as unused ports, overlapping capability requests could overwrite a newer result, and a rejected Z-Wave flow lookup never showed the retry error.

* Use the repo consume decorator in the ESPHome setup UI.
2026-09-30 14:17:17 +03:00
Tom Mittelstädtand1358 3f4c57d31b Mark tentative calendar events (#54457)
* Mark tentative calendar events

A tentative event is drawn hollow: a ring instead of a dot and an outline instead of a filled block. The event dialog names the status. Confirmed events and events without a status look as before.

* Remove the tests for tentative events

---------

Co-authored-by: 1358 <[email protected]>
2026-09-30 13:53:31 +03:00
Aidan Timson 619abbc55f Note addressed review threads so they can be resolved (#54471) 2026-09-30 10:48:10 +00:00
Aidan Timson 5361cf04cd Make review comments lead with removal of unwanted code (#54470)
Lead review comments with removal when guidance rules code out
2026-09-30 12:37:18 +02:00
Faizan Saiyed 305b7cbc4b Fix light color temperature gradient in RTL (#54468) 2026-09-30 10:30:57 +00:00
Marcin BauerandClaude Opus 5.5 468afadee2 Keep bottom sheet header fixed while content scrolls (#54466)
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-09-30 11:05:04 +01:00
Petar Petrov 06ac6a59be Patch ECharts so pinch zoom follows the fingers (#54465) 2026-09-30 11:31:28 +02:00
Artur Pragacz 37827ea9a2 Fix computed entity name in voice settings (#54454) 2026-09-30 10:32:37 +02:00
dependabot[bot] 1ff226ebbd Bump undici from 6.28.0 to 6.29.0 (#54462)
Bumps [undici](https://github.com/nodejs/undici) from 6.28.0 to 6.29.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.28.0...v6.29.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.29.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-30 06:45:58 +02:00
7de77d5f91 Skip remaining upstream-only workflows on forks (#54458)
Forks lack the RelativeCI, Lokalise, and wheels secrets, so these
workflows fail on every sync of a fork's dev branch and email the fork
owner. Release Drafter also creates a stray draft release on the fork.

Guard them with the same repository check as the scheduled workflows:
- RelativeCI upload jobs (workflow_run after CI)
- Translations upload (push to dev touching en.json)
- Release Drafter (push to dev)
- Release landing-page job (release published)

Co-authored-by: Paulus Schoutsen <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-09-29 21:59:12 +02:00
karwosts 12226569a3 Fix two invalid attributes (#54456) 2026-09-29 19:34:16 +02:00
Bram KragtenandClaude Opus 5 8e061973ee Send the map tiles token in a header, so tile URLs stop rotating (#54452)
The access token rotates every half hour and lives in the query string, so it
is part of the browser's cache key: every rotation orphans every cached tile,
and the week-long max-age core sends is worth nothing. The service worker works
around it by stripping the token from its own cache key, but a service worker
only runs on https or localhost - on a plain http LAN origin, which is how a
lot of instances and the companion apps are reached, there is no cache at all
between the map and the network.

Anything that can set a header sends the token there instead, which leaves the
URL, and with it the cache key, stable across rotations. Raster tiles come from
an <img> and stay on the query parameter, and so does Cast: cross-origin a
custom header would cost a CORS preflight per tile.

Needs the matching core change; against a core without it the proxy refuses
every tile.

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-29 16:30:54 +00:00
karwosts e427136cdc Fix cover/value more-info icons (#54455) 2026-09-29 16:14:32 +00:00
b7aa648f0b Automation row threshold details (#54049)
* Add ha-automation-row-threshold component and integrate with automation rows

* Update ha-automation-row-behavior config property to be optional and adjust condition rendering based on target entity count

* Fix order and review

* add format number

* remove row-behavior and adopt row order

* Update range formatting to use an en dash

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Fix minus

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: MindFreeze <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-29 17:12:52 +02:00
Paul Bottein 2ea40a6b96 Add button role and label to card and badge edit controls (#54449) 2026-09-29 17:06:30 +02:00
Markus TuominenandClaude Fable 5.1 924b55c443 Fix description of the enable new entities system option (#54446)
The description said newly discovered devices would be automatically
added, but the setting controls whether newly discovered entities are
enabled. Devices and entities are still added either way; when the
option is off, new entities are created disabled.

Co-authored-by: Claude Fable 5.1 <[email protected]>
2026-09-29 15:02:44 +00:00
WendelinandClaude Opus 5.5 cb971dc1a3 Replace ContextConsumer with ContextSubscriptionController (#54450)
* Replace ContextConsumer with ContextSubscriptionController

`@lit/context`'s `ContextConsumer` has the same problem as its `consume`
decorator: it calls `host.requestUpdate()` on every provider notification.

- Migrate `ha-map`, `hui-map-card`, `automation-trigger-controller` and
  `service-info-controller` to `ContextSubscriptionController`. Their
  callbacks already write to `@state()` fields or request an update
  themselves when the result changes.
- Accept any `ReactiveControllerHost` element as controller host, so plain
  controllers can use it.
- Forbid importing `ContextConsumer` from `@lit/context` with ESLint.
- Document the controller in the contexts skill.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UFoL6HHkeK4X9gx4xo9of6

* Use own consume in profile dialog and picture upload

Both were added in #54400 with `consume` from `@lit/context`, which the
lint rule now forbids and which forces a host update on every context
change.

Drop `@state()` from the consumed fields that are only read outside the
render cycle: `_api` and `_connection` in both components, and `_states`
and `_hassConfig` in the profile dialog, which only seeds its form from
them in `connectedCallback`.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UFoL6HHkeK4X9gx4xo9of6

---------

Co-authored-by: Claude <[email protected]>
2026-09-29 16:55:20 +02:00
Paul Bottein 74adb1da49 Add UI support for section strategies (#54040)
* Add UI support for section strategies

* Use card editor style YAML toggle for sections
2026-09-29 16:12:12 +02:00
renovate[bot] 682c68c1e3 Update dependency maplibre-gl to v6.11.2 (#54448) 2026-09-29 14:09:01 +00:00
68c5e080ac Update dependency maplibre-gl to v6 [SECURITY] (#54073)
Co-authored-by: Maarten Lakerveld <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: bramkragten <[email protected]>
Co-authored-by: Bram Kragten <[email protected]>
2026-09-29 15:58:42 +02:00
Jeremy Cook c3d872734d Stop cropping tile info text in fixed-height grid cells (#54237) 2026-09-29 14:28:21 +01:00
WendelinandClaude 5fb0090c71 Add own consume decorator that does not force host updates (#54443)
Co-authored-by: Claude <[email protected]>
2026-09-29 15:04:51 +02:00
Wendelin 498a25a488 Fix target picker section height (#54445) 2026-09-29 16:00:53 +03:00
Franck NijhofandClaude Opus 5.5 e908f75074 Let users edit their own name and picture from their profile (#54400)
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Claude <[email protected]>
2026-09-29 13:25:27 +02:00
Petar Petrov 5054c17381 Render login fields in the light DOM so password managers can find them (#54278) 2026-09-29 12:31:24 +02:00
Aidan Timson e30caa464f Show load errors on config data table pages (#54434)
* Show config entry load errors with retry on devices page

* Show load errors on config data table pages

* Show load errors in the data table

* Use data table load errors on config pages

* Keep table semantics and block retries during load errors

* Add default load error text and English fallbacks to data table
2026-09-29 12:18:43 +02:00
Aidan Timson 27c06e067c Show skeleton rows while data tables load (#54328)
* Show skeleton rows while data tables load

* Use skeleton placeholders for devices metadata

* Announce data table loading to screen readers

* Inline data table skeleton rows

* Simplify devices metadata placeholders

* Show loading state in more config data tables

* Leave Bluetooth advertisement loading for the follow-up

* Preserve table cell semantics while loading

* Show loading labels for pending integration groups

* Handle devices page load failures

* Show config entry load errors with retry on devices page

* Move data table cell helpers into the class

* Remove config entries reload listener on disconnect

* Say error in devices integrations load failure text

* Clarify devices integrations load failure has an unknown cause

* Move devices load failure alert to a follow-up

* Show dashboards skeleton until custom dashboards load
2026-09-29 11:37:17 +02:00
Paul Bottein cacfb940f6 Use the device area when the entity uses the device name (#54235)
* Use the device area when the entity uses the device name

* Keep the device area switch off after turning it off
2026-09-29 09:52:32 +02:00
Paul Bottein 73451bb8b4 Add a switch to use the device name for entities (#54021)
* Add a checkbox to use the device name for entities

* Replace checkbox with a use device name switch row

* Only treat an empty name as using the device name

* Keep child view titles in the settings view

* Use row item for the device name row

* Treat an empty entity name as using the device name

* Remove unused icon button next import

* Follow the device name when renaming entities named after their device

* Keep the empty name when renaming Z-Wave entities

* Use the device name for ZHA entities with an empty name
2026-09-29 09:31:50 +02:00
Paul Bottein 717e79063b Omit owners in another area from entity context (#54193)
* Omit owners in another area from entity context

* Rename context source to next name part

* Use picker display for entity editor rows
2026-09-29 09:19:18 +02:00
renovate[bot] 25259ff668 Update dependency lint-staged to v17.6.0 (#54442)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-29 09:49:57 +03:00
João Pedro Hickmann 955344b44c Use tap-to-show chart tooltips for touch input (#54353)
* Use tap-to-show chart tooltips for touch input

On mobile-size screens the tooltip already opens on a tap (#24083), but
touch devices above that size kept the hover trigger, so the tooltip
followed the finger. Touching the axis pointer handle, which sits below
the grid, then hid the tooltip and the handle, so the handle added for
touch devices (#26088) could not be dragged.

Open the tooltip on a tap whenever the chart is used with touch, and keep
hover for a mouse, also on devices that have both: the trigger follows the
pointer type of the last pointer event, which arrives before the touch and
mouse events echarts handles.

With the tooltip opened by a tap, a tap anywhere else on the page closes
it.

* Clean up the outside tap listener and treat pen as touch

Remove the outside tap listener when the chart is recreated, since the
new chart starts with its handle hidden and nothing would remove it.
Only switch to tap-to-show tooltips on touch devices, where the handle
and outside tap handlers are installed, and count a pen as touch as
echarts does. Restore the full echarts default trigger, including
mousewheel, when switching back to the mouse.

* Close the chart tooltip on a pen tap outside it

A pen counts as touch for tap-to-show tooltips, but it does not reliably
fire touch events, so tapping outside with a pen left the tooltip open.
Listen to pointerdown instead and leave out the mouse, since echarts
already hides the tooltip when the mouse leaves the chart.

* Switch the chart tooltip trigger in the capture phase
2026-09-29 09:33:16 +03:00
dependabot[bot] 4627b92de1 Bump ip-address from 10.5.0 to 10.7.2 (#54441)
Bumps [ip-address](https://github.com/beaugunderson/ip-address) from 10.5.0 to 10.7.2.
- [Release notes](https://github.com/beaugunderson/ip-address/releases)
- [Commits](https://github.com/beaugunderson/ip-address/compare/v10.5.0...v10.7.2)

---
updated-dependencies:
- dependency-name: ip-address
  dependency-version: 10.7.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-29 09:28:53 +03:00
Maarten Lakerveld ed2d316f00 Map marker styling (#54308)
* Expose CSS parts on ha-entity-marker

Styling tools can target ::part(marker) and ::part(picture) from the
map's scope, so a style applies to markers as they are created instead
of being re-injected into each new element. Documents the marker's
custom properties and parts as its styling surface.

* Reuse cluster bubble avatars across rebuilds

Cluster bubbles are rebuilt whenever the camera settles or an entity
changes state, and each rebuild created new ha-entity-marker elements.
Pictures were re-decoded, the entity state subscription was torn down
and set up again, and styles applied to a marker by styling tools were
lost on every pan or zoom.

Avatars are now cached per entity id and moved into the new bubble.
An avatar still on screen is left alone: Leaflet's markercluster keeps
the outgoing bubble visible during its zoom animation, and taking its
avatar would empty it mid-fade. Avatars of entities no longer shown are
dropped when entities are redrawn.

* Rebuild Leaflet cluster icons on every add

markercluster caches a cluster's icon object and re-appends the same bubble
element when zooming back out, without asking for a new one. Once avatars
are reused across bubbles, a cluster that splits (removed before its child
is created) loses its avatars to the child bubble and comes back empty.
Building the divIcon inside createIcon runs the builder on every add, so
the shown bubble always takes the avatars from the cache.

* Export the marker parts through ha-map

Both ha-entity-marker instances live in ha-map's shadow root, so their
parts were unreachable from outside. Each marker now exports them under
the generic names and per entity, e.g. marker-person-anne, so a page can
style one person's marker with ha-map::part(marker-person-anne).

* Reuse entity markers across redraws

Every state change of a listed entity redraws all markers, and until now
only cluster avatars kept their element. Standalone markers now come from
the same per-entity cache through one helper, which also carries the
reuse guard: an element still on screen is left alone and a fresh one
takes its place, since Leaflet keeps an outgoing bubble during its zoom
animation. Duplicate entities in one draw get their own element.
2026-09-29 09:18:06 +03:00
github-actions[bot]andpiitaya fd8bf65f3d Update sensor entity constants (#54440)
Co-authored-by: piitaya <[email protected]>
2026-09-29 06:16:39 +00:00
Maarten Lakerveld 5229607bb9 Versatiles style bump to v6 (#54432)
* Generate the map styles with @versatiles/style v6

v6 removed the colorful and eclipse builders; osm({ theme }) replaces
them, with eclipse mapping to the retuned colorful-dark palette. The
sprite sheet is renamed from basics to base and its icon ids change,
so core's tile proxy has to serve the base sheet before this ships.

v6 also defaults to the globe projection and the styles keep it. Only
the MapLibre engine renders them: from ha-map the Leaflet engine runs
without WebGL2 or raster-only after a MapLibre failure, so nothing
ties the map to Mercator any more.

* Bundle the VersaTiles base sprite sheet

The styles referenced the sprite sheet through core's proxy, which
fetched it from the OpenStreetMap Foundation. The OSMF only mirrors
the retired v5 basics sheet, and VersaTiles warns that the assets on
tiles.versatiles.org change with every release, so neither is a stable
source for the exact sheet the pinned @versatiles/style expects.

The base sheet now ships with the frontend under static/map/sprites,
fetched from the versatiles-style release matching the installed
package with `yarn gulp update-map-sprites`. The style build checks
that every icon the styles reference exists in the bundled sheet, so a
bump that renames icons fails the build instead of shipping POIs
without icons. Sprites resolve against the page rather than the
instance, since on Cast the frontend is not served by the instance,
and the demo no longer needs its own sprite override.

* Open a PR when the bundled map sprite sheet drifts

Runs the sprite update after a push to dev touches package.json, which
is how a @versatiles/style bump lands, and opens a PR with the
re-vendored sheet when it changed. Mirrors the device class and sensor
constant sync workflows.

* Exclude vendored map sprite metadata from Prettier

The sprite JSON is extracted verbatim from the @versatiles/style release
in its upstream compact form, which fails prettier --check. Ignoring it
keeps lint green and keeps the sync workflow's drift check byte-identical
with upstream.

* Format map-assets.js with Prettier

* Note that the sprite sheet ships with the frontend

The module header still said sprites come through core's proxy, which
stopped being true when the sheet was bundled.

* Gate merges on the bundled map sprite sheet

A @versatiles/style bump that references new icons used to fail only the
build job, which the dev ruleset does not require, so the bump could be
merged red and the post-merge sync workflow was left to repair it. Run
the sprite check in the required lint job instead, so the sheet has to be
re-vendored on the dependency PR itself, and drop the sync workflow that
existed to clean up after the merge.

* Only treat image properties as sprite references

The sprite check walked every string under layout and paint, so any
base-prefixed text value would have failed the required lint job without
asking for an image. Collect from the image-bearing properties only.

* Version the sprite URL with a hash of the vendored sheet

Core serves /static with a month of max-age and the service worker does
not precache the map assets, so a re-vendored sheet at the same URL would
keep coming from the browser cache next to a freshly fetched style that
expects the new icons. Append a short content hash of the four sheet
files as a query parameter. MapLibre appends the format and extension to
the pathname, so the query survives, and the test now guards that the
absolute-URL rewrite keeps it too.
2026-09-29 09:15:51 +03:00
karwosts e5ef589931 Fix Object object error messages from websocket errors (#54438)
* Fix Object object error messages from websocket errors

* simplify
2026-09-29 09:14:09 +03:00
dependabot[bot] 1ef136f851 Bump fast-uri from 3.1.6 to 3.1.8 (#54439)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.6 to 3.1.8.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.6...v3.1.8)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.8
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-29 09:13:18 +03:00
Paulus Schoutsen b3a7c35685 Revert "Add a user picker to an assist pipeline" (#54433)
Revert "Add a user picker to an assist pipeline (#54276)"

This reverts commit 0cb50303c3.
2026-09-28 18:12:58 +02:00
João Pedro Hickmann f3f42492ce Only start chart sonification from the keyboard (#54354)
* Only start chart sonification from the keyboard

Clicking or tapping a chart focuses it, which loaded Chart2Music and, once
connected, moved the tooltip to the first data point. On touch devices the
tooltip jumped to the start of the chart right after the first tap.

Chart2Music only responds to the keyboard, so start it on keyboard focus
(:focus-visible), or on the first key pressed in a chart that was focused
by pointer.

* Replay the key that starts chart sonification

Chart2Music only listens for keys once it is connected, so the first key
pressed on a chart focused by pointer only started loading it, and a
navigation key scrolled the page. Hold navigation keys and Space back
from the page while loading and replay the key once connected, unless a
page shortcut already handled it. Lone modifiers, Meta shortcuts and
Ctrl or Alt with anything but a navigation key are left to the browser.

* Move the chart keydown listener above the focus listeners

Keeps it apart from the pointer listeners added in #54353, so the two
PRs merge without conflicts.

* Drop the keyboard fallback and key replay, only start on focus-visible
2026-09-28 16:45:59 +03:00
Maarten Lakerveld 50b0b3f493 Fix the device class and sensor constant sync workflows (#54431) 2026-09-28 15:24:56 +02:00
Petar Petrov c49085e830 Show battery discharge per battery in energy usage graph (#54341) 2026-09-28 14:52:42 +02:00
d9ac1c1452 Update dependency prettier to v3.9.9 (#54397)
Co-authored-by: timmo001 <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-09-28 14:40:28 +02:00
João Pedro Hickmann 93c1543127 Hide the chart tooltip while panning with the mouse (#54356)
* Hide the chart tooltip while panning with the mouse

Dragging a zoomed chart with the mouse pans it, and the tooltip kept
following the pointer across the moving data. Hide it while the pan moves
the chart, from the datazoom handler, and show it again when the mouse
button is released, also when that happens outside the chart.

* Restore the configured tooltip visibility after panning

Reset the press and pan state on disconnect, and hide and restore each
configured tooltip instead of forcing a single tooltip on.

* Only track primary mouse button presses for panning

A right click could leave the press flag set when the context menu took
the mouseup, and zrender doesn't mark touch as touch when it listens to
pointer events, as on Edge. Either way a later zoom hid the tooltip.

* Move the pan state cleanup and helpers away from #54353's changes

Resets the pan state after the legend cleanup and places the mouseup and
tooltip helpers after the data zoom handler, so the two PRs merge
without conflicts.

* Use the zrender mouseup to end panning instead of a window listener
2026-09-28 15:40:13 +03:00
Aidan Timson e16f683a5a Share shadow root host lookup (#54430) 2026-09-28 13:49:11 +02:00
Paul Bottein 99d2742f4a Fix list item supporting text ellipsis (#54429) 2026-09-28 11:27:27 +00:00
WendelinandClaude Opus 5.5 ca51e06181 Fix dev server failing after translation changes (#54420)
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Claude <[email protected]>
2026-09-28 11:54:15 +01:00
renovate[bot] c8593510c4 Update vitest monorepo to v5.0.2 (#54426) 2026-09-28 10:49:27 +00:00
renovate[bot]andPetar Petrov dbc9bf2288 Update formatjs (#54414)
Co-authored-by: Petar Petrov <[email protected]>
2026-09-28 11:41:44 +01:00
WendelinandClaude 410e22388b Fix bidiIsolate return type for string input (#54427)
Add overloads so bidiIsolate returns string when given a string,
fixing the type error in storage-breakdown-chart introduced in #54205.


Claude-Session: https://claude.ai/code/session_01Rtu8Rd2oU3DM6oiy23f63z

Co-authored-by: Claude <[email protected]>
2026-09-28 10:38:48 +00:00
renovate[bot] 16183f9ecf Update dependency intl-messageformat to v12 (#54424) 2026-09-28 11:15:53 +02:00
Yosi LevyandCopilot Autofix powered by AI 2386e84da4 RTL fixes - units (#54205)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-28 11:10:55 +02:00
Petar Petrov 90aa8462fb Fix date range picker ranges in server time zone mode (#54422) 2026-09-28 11:03:34 +02:00
Petar Petrov 11d41b837f Fix energy ranges counting an extra day across time zones (#54423)
* Fix energy ranges counting an extra day across time zones

* Test energy statistics request ranges
2026-09-28 10:52:38 +02:00
João Pedro Hickmann 83af6058b7 Fix chart tooltip lag when dragging on touch devices (#54352) 2026-09-28 10:25:22 +02:00
WendelinandClaude 788eb4d781 Show app count in installed apps search placeholder (#54415)
Claude-Session: https://claude.ai/code/session_01SXNDbcPtJDCrtJZVzdj9uD

Co-authored-by: Claude <[email protected]>
2026-09-28 10:11:59 +03:00
renovate[bot] 9283c8ba91 Update Playwright (#54417)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 10:11:13 +03:00
renovate[bot] 0ec99e866b Update dependency jsdom to v30.1.1 (#54413)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 10:08:55 +03:00
karwosts 40d2aedc1d Restore by-card tab in footer dialog (#54403) 2026-09-28 08:59:25 +02:00
renovate[bot] 66321c57d2 Update dependency home-assistant-js-websocket to v9.7.0 (#54412)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 08:59:51 +03:00
renovate[bot] f990c85b32 Update dependency eslint to v10.11.0 (#54411)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 08:59:28 +03:00
nokside 97336c4009 Add default support to object selector fields (#53739)
* Add default support to object selector fields

* Clone object selector field defaults

* Use unknown for object selector defaults

* Use deepClone for object selector defaults
2026-09-28 08:42:28 +03:00
Dominik c3e84e4bb4 Remove backdrop from text-only markdown (#54390) 2026-09-28 08:41:56 +03:00
renovate[bot] 90f8e2f8d6 Update dependency browserslist to v4.29.1 (#54410)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 08:39:38 +03:00
renovate[bot] daaa673113 Update dependency @lokalise/node-api to v16.6.0 (#54409)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 08:39:12 +03:00
Paulus SchoutsenandClaude 113d645dad Hide the host in the MCP server URLs (#54375)
The MCP card showed the full URLs, which reveal the host of the
Home Assistant instance in screenshots. The card now shows only the
path. The copy button still copies the full URL.


Claude-Session: https://claude.ai/code/session_01GXiaNSBbB8C33fBL9yg5EP

Co-authored-by: Claude <[email protected]>
2026-09-28 05:57:05 +02:00
renovate[bot] 2d05e8f90f Update Yarn to v4.18.1 (#54407)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:53:15 +02:00
renovate[bot] c376786885 Update dependency @html-eslint/eslint-plugin to v0.66.1 (#54408)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 03:41:36 +00:00
renovate[bot] 61e15a6a4a Update dependency typescript-eslint to v8.70.1 (#54401)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 03:38:50 +00:00
Franck NijhofandClaude b4d65e3b83 Use a toggle for unlimited login attempts in HTTP config (#54399)
Use an unlimited toggle for the HTTP login attempts threshold

Core uses -1 to mean unlimited login attempts. Instead of asking users to
type -1, show an "Unlimited login attempts" toggle and only show the
number field when it is off. The -1 mapping stays internal to the form.

Co-authored-by: Claude <[email protected]>
2026-09-28 05:31:20 +02:00
renovate[bot] 728bb8055c Update dependency @lezer/highlight to v1.2.4 (#54387)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:29:27 +02:00
renovate[bot] 70e8cd376b Update dependency @rspack/core to v2.2.7 (#54388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:29:09 +02:00
renovate[bot] 9fc555ced6 Update dependency fs-extra to v11.4.1 (#54394)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:28:40 +02:00
renovate[bot] 72b3a52a2e Update dependency js-yaml to v5.4.2 (#54395)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:28:21 +02:00
renovate[bot] dbbaa3e626 Update dependency marked to v18.0.14 (#54396)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:27:25 +02:00
renovate[bot] 11401b2a79 Update dependency vite to v8.3.1 (#54402)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:26:34 +02:00
renovate[bot] 01124ffbb2 Update vitest monorepo to v5.0.1 (#54405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-28 05:26:01 +02:00
Allen Porter fd19a0e4e3 Forward PKCE code_challenge parameters in login flow (#54389)
* Forward PKCE code_challenge parameters in login flow

* Move auth data test to test/data/auth.test.ts
2026-09-27 17:59:30 -04:00
Marcel van der Veldt 40270f5a86 Send the right route to apps opened from their sidebar entry (#54404) 2026-09-27 17:58:26 -04:00
Franck Nijhof e7d76ce6c9 Move GitHub Actions updates from Dependabot to Renovate (#54382) 2026-09-27 19:34:43 +02:00
renovate[bot] 6c53fd6c4f Update CodeMirror (#54385)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-27 15:24:41 +02:00
renovate[bot] d54b818d83 Update babel monorepo to v8.0.6 (#54384)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-27 15:24:24 +02:00
Franck Nijhof c4f1a1bea2 Fix Renovate keeping the Playwright container update pending forever (#54380) 2026-09-27 15:24:10 +02:00
Felix Schneider 0cb50303c3 Add a user picker to an assist pipeline (#54276)
Let an assist pipeline act as a user

Needs home-assistant/core#182750.
2026-09-27 08:01:51 +00:00
Paulus SchoutsenandClaude Opus 5.5 d16e04a2b4 Enable the MCP server in one click (#54349)
* Enable MCP in one click and show discovered MCP servers

Enable now creates the Model Context Protocol Server entry without a
dialog and then opens the options flow. If the config flow still asks
for input, the config flow dialog opens instead.

The MCP card lists MCP servers that apps offer through Supervisor
discovery, with actions to add or ignore each one. The section is
hidden when nothing is discovered.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GXiaNSBbB8C33fBL9yg5EP

* Move discovered MCP servers to a separate pull request

This pull request only makes Enable create the Model Context Protocol
Server entry without a dialog.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GXiaNSBbB8C33fBL9yg5EP

* Keep the options closed after enabling the MCP server

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GXiaNSBbB8C33fBL9yg5EP

* Keep the Enable button loading until the MCP card reloads

The button became clickable again while the card was still loading
the new entry.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01GXiaNSBbB8C33fBL9yg5EP

---------

Co-authored-by: Claude <[email protected]>
2026-09-27 07:42:38 +00:00
Paulus SchoutsenandClaude 21957ed41f Correct registry and auth API types in the frontend (#54288)
Compare the registry, auth and tag data modules with the handlers that
produce them, and fix the mismatches.

Updating a floor returned the floor entry, not an area. Looking up
extended entity entries returns null for an id the registry does not
know, so the callers now drop those before use.

Correct the refresh token payload, which was missing the provider type
and typed several always-present nullable fields as optional, and drop
a field the auth provider list does not return.


Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

Co-authored-by: Claude <[email protected]>
2026-09-27 09:37:36 +02:00
Paulus SchoutsenandClaude Opus 5 8b5302ac06 Correct device protocol API types in the frontend (#54287)
* Correct device protocol API types in the frontend

Compare the Z-Wave, Zigbee, Matter, Thread, MQTT, Bluetooth and
ESPHome data modules with the handlers that produce them, and fix the
mismatches.

Widen the unions the backends have outgrown. The Zigbee radio type
gained a member the union did not list, and the Matter topology node
kind is documented as an open set.

Correct several declared results that never matched the wire,
including the rebuild and abort commands, the smart start calls, and
the log level setter. Mark the many controller and node fields the
Z-Wave server can omit as nullable, and split the MQTT debug message
type from the subscription message, which carries no timestamp.

Correct the Zigbee signal strength, which the frontend typed as text
and the library reports as a number.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

* Separate the Z-Wave set config parameter result from its display state

The command reports a numeric SetValueStatus, but the type declared a
string status and an error field the backend never sends. The node
config view reused that type for its own row state, so it fed the
number straight into a translation key and the result line rendered
nothing.

Type the command result as sent, give the view its own state, and map
one to the other.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

---------

Co-authored-by: Claude <[email protected]>
2026-09-27 09:36:11 +02:00
Paulus SchoutsenandClaude 4db73f6a3d Correct backup, onboarding and cloud API types in the frontend (#54286)
Compare the backup, onboarding and cloud data modules with the
handlers that produce them, and fix the mismatches.

Several backup calls declared the wrong result. Deleting a backup
returns agent errors, generating one returns a job id rather than a
backup id, and restoring one returns nothing. The backup list carries
extended content, not the base type.

Add the blocked manager state, which is the state the manager starts
in and replays to new subscribers, along with the event reason fields
and the core_restart restore state.

Correct the onboarding installation type, which listed a value the
backend never sends and omitted one it does, and narrow the cloud
onboarding status to the single field that endpoint returns.

Remove the cloud strict connection preference and its translations.
No such preference exists in core, so the warning it gated could never
render.


Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

Co-authored-by: Claude <[email protected]>
2026-09-27 09:35:47 +02:00
Paulus SchoutsenandClaude 7c5a7c81e5 Hide MCP options for a disabled MCP server entry (#54369)
A disabled Model Context Protocol Server entry showed the URLs and the
options flow, although the server does not run. The card now shows
Enable instead, which enables the existing entry.


Claude-Session: https://claude.ai/code/session_01GXiaNSBbB8C33fBL9yg5EP

Co-authored-by: Claude <[email protected]>
2026-09-27 09:34:30 +02:00
karwosts 8da3713ec4 Standardize translation function for 'Ctrl' key. (#54368) 2026-09-27 09:33:47 +02:00
karwosts e7f60b8583 Fix multiple invocations of image cropper (#54376) 2026-09-27 09:32:09 +02:00
dependabot[bot] 6d7ecb90a1 Bump the codeql-action group across 1 directory with 2 updates (#54377)
Bumps the codeql-action group with 2 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.38.0 to 4.38.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...1c5b675653bb5c22dbe9b12b556ec555138e09fd)

Updates `github/codeql-action/analyze` from 4.38.0 to 4.38.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...1c5b675653bb5c22dbe9b12b556ec555138e09fd)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-27 09:32:06 +02:00
Tom Carpenter 8fcf822025 Fix energy period selector icon resizing (#54372)
On narrow screens, the energy period selector resizes its date picker icon to ensure there is enough space to render the buttons. However the CSS used to target this icon is not specific enough meaning the resize leaks into elements within the date picker itself.

To fix this, add a part specifier to the date range inputs on the ha-date-range-picker, and target the CSS at that. This prevents targetted CSS from leaking into the picker itself.
2026-09-27 08:43:45 +02:00
Paulus SchoutsenandClaude 6878828996 Fix type error for notifications without a title (#54374)
A persistent notification can have a null title, but estimateDirection
takes a string. The function already treats a falsy value as an empty
string, so the behavior does not change.


Claude-Session: https://claude.ai/code/session_01GXiaNSBbB8C33fBL9yg5EP

Co-authored-by: Claude <[email protected]>
2026-09-26 20:36:14 -07:00
Paulus SchoutsenandClaude Opus 5 5c187a4e13 Correct Assist pipeline and speech API types in the frontend (#54285)
* Correct Assist pipeline and speech API types in the frontend

Compare the pipeline, conversation, speech and Wyoming data modules
with the handlers that produce them, and fix the mismatches.

The pipeline run events were the furthest adrift. Correct the wake
word, speech-to-text, intent and text-to-speech payloads, add the
stt-vad-start and stt-vad-end events, and drop keys the backend never
sends.

Two of these were live bugs. The chat log subscription nests its
payload under chat_log, so the log was read one level too high. The
debug view read the wake word result as ww_id, which is wake_word_id,
so that field always rendered undefined.

Rewrite the Wyoming info types against the wyoming library, which the
previous types modelled as empty tuples.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

* Leave the chat log tool result to its own change

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

---------

Co-authored-by: Claude <[email protected]>
2026-09-26 13:13:08 +02:00
56f695f4ed Clarify that IP bans do not expire (#54365)
* Clarify that IP bans do not expire

* Apply suggestion from @silamon

Co-authored-by: Simon Lamon <[email protected]>

---------

Co-authored-by: Petar Petrov <[email protected]>
Co-authored-by: Simon Lamon <[email protected]>
2026-09-26 11:52:21 +02:00
João Pedro Hickmann e0b7b929dd Skip drawing hidden line chart symbols to speed up tooltips (#54355)
* Don't draw the invisible symbols of line charts

The chart theme sets a 1px symbol for line series, so symbols are not
visible, but echarts still draws one per data point. Every tooltip or
axis pointer move repaints the whole layer, including those hundreds of
symbols: on a power sources graph with 200 points per series, one drag
step repainted about 1000 elements.

Set showSymbol: false in the theme. Echarts still draws the symbol of the
hovered point. On a slow tablet this cut the repaint per drag step from
about 50ms to 8ms and roughly halved the frame time while dragging.

* Fix ECharts capitalization
2026-09-26 12:38:51 +03:00
Paulus SchoutsenandClaude Opus 5 f0c63f8840 Correct config flow and integration API types in the frontend (#54289)
* Correct config flow and integration API types in the frontend

Compare the config entry, flow and manifest data modules with the
handlers that produce them, and fix the mismatches.

Split the in-progress flow message into a discriminated union, because
the removed event carries no flow. Mark the flow step fields the
backend sends as null, and correct the manifest, where the discovery
entries and several always-optional keys did not match the schema.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

* Request a single config flow handler type

The endpoint indexes one key, and only "helper" and "integration"
exist. Asking for a list joined them into one unknown key, so looking
up a non-helper integration raised on the backend.

Add the config entry unloading state and the virtual integration type,
both of which the backend reports, with the strings they render.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

---------

Co-authored-by: Claude <[email protected]>
2026-09-26 10:44:43 +02:00
Paulus SchoutsenandClaude 1ac04b0a65 Correct energy, history and recorder API types in the frontend (#54292)
Compare the energy, history and recorder data modules with the
handlers that produce them, and fix the mismatches.

History states omit attributes when the caller asks for a minimal
response, which both subscriptions do, so the field is optional and
the readers now guard it. Statistics omit the values that were not
requested, and the validation issues carry nullable placeholders.


Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

Co-authored-by: Claude <[email protected]>
2026-09-26 10:41:17 +02:00
Paulus SchoutsenandClaude a7eb100132 Correct entity domain and helper API types in the frontend (#54293)
Compare the entity domain and helper data modules with the domains
that produce the attributes, and fix the mismatches.

Add supported feature flags the domains define and the frontend did
not list, and add attributes the domains report. Remove attributes
that are service fields rather than state, and the light colour
temperature keys core replaced with the kelvin forms.

Correct the weather forecast, where the event carries the whole list
and the wind speed is a number, and correct the image update command,
which sent the wrong id.


Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

Co-authored-by: Claude <[email protected]>
2026-09-26 10:40:32 +02:00
237bf119e7 Keep zone occupants in one map bubble (#54307)
* Keep zone occupants in one map bubble

Several bubbles piled up on a zone marker. A person inside a zone whose
state did not name it (stale or router-based tracking) had no zone key
and showed as a loose marker under the bubble, or formed a second
bubble on the same spot. Occupants spread beyond the group radius fell
back to proximity clusters, and every cluster of same-zone members was
pinned above the zone marker, stacking bubbles. Zoomed out, each zone
kept its own bubble even when the zone markers overlapped.

Zone membership now also follows position: an entity inside a drawn
zone's circle joins that zone's bubble. The engine hands the builder
the group key, so only the zone's own group is pinned to its marker and
proximity clusters show where their members are. Proximity is measured
against every member of a group rather than only its first. Bubbles
whose rectangles would overlap on screen merge into one plain bubble,
keeping the zone's tail only when a single zone is involved.

The Leaflet fallback ignores group keys, so it no longer pins bubbles
to zones there.

* Fix map cluster test lint types

Co-authored-by: maartenla <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-09-26 09:56:02 +02:00
Balloob BotandPaulus Schoutsen 4a6765d886 Skip upstream-only scheduled workflows on forks (#54366)
Co-authored-by: Paulus Schoutsen <[email protected]>
2026-09-26 07:50:09 +00:00
Jan-Philipp BeneckeandClaude Opus 5 8c5c35ca06 Describe trace graph nodes for screen readers (#54358)
* Describe trace graph nodes for screen readers

The trace graph is drawn entirely in SVG. Its nodes and branches are
keyboard reachable, but carried no accessible name and no role, so a
screen reader announced nothing while tabbing through a run. Everything
the graph says about the outcome of a step — the error badge, the
strike-through, the dashed outline, the repeat count — was visual only.

Each focusable stop now carries the same step description the automation
editor shows, followed by what the run did with that step. The ARIA is
written at the call sites in hat-script-graph, which is the only place
that knows whether an element is a step or just layout: the branch heads,
the then/else arrows, the failed-condition cross and the spacers are
marked aria-hidden, while the branch that merely groups the triggers is
left alone so the triggers inside it stay in the accessibility tree.

The names themselves are built by buildTraceLabels, a pure function that
walks the trace tree and returns one string per node path, reusing the
same describers the editor uses. The trace panels call it because they
already own hass, and memoize it on the trace, so the graph takes a plain
record and stays a leaf: it subscribes to nothing, and entity state
changes no longer rerender it.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Process code review comments

Fix the memoization of the trace labels: `hass` is replaced on every
state update, so comparing it rebuilt every label on every state event,
which was worse than the rerendering the labels were hoisted out of the
graph to avoid. Compare everything but `hass`, and let an absent entity
registry stay undefined rather than allocating a new array each render.

Report whether a condition passed or failed instead of only that it ran.
That outcome is otherwise shown by the tracked path and by a cross on a
node that is aria-hidden, so it never reached a screen reader.

Drop `role="button"` from the nodes. Selection follows focus and nothing
handles clicks or key presses, so the role promised an activation that
does not exist. The branches keep `role="group"`, which makes no such
promise.

Pass the integration manifests through from both trace panels, so the
names match the ones the automation editor shows.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Process code review comments

Give the leaf nodes `role="img"`. Dropping `role="button"` left them with
the implicit generic role, on which ARIA prohibits an author-provided
name, so the labels risked being ignored and the nodes going back to
being unnamed focus stops. A node draws one step and slots only
decoration, so `img` names it without claiming it is a control. The
branches keep `role="group"`, since `img` would make their focusable
children presentational. `aria-disabled` goes with the button role: it is
unsupported on `img`, and the state is already part of the name.

Assert the nested steps in the label coverage test. It only checked the
building blocks and the choose options, so a regression in the recursion
through branch children would have gone unnoticed.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-25 20:25:04 +02:00
Yosi LevyandCopilot Autofix powered by AI a3cb6d8202 Automatic direction for alerts and notifications (#54342)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-25 16:52:45 +01:00
Dr.Blank f60a40de72 Show security rating scale in app rating dialog (#54345) 2026-09-25 14:53:07 +01:00
Aidan TimsonandCopilot Autofix powered by AI 465f4a8227 Add shared skeleton components (#54325)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-25 14:52:14 +01:00
Paulus SchoutsenandClaude 87763fb59d Load MDI icon chunks from the static path (#54347)
ha-icon fetched the MDI chunks from a fixed /static/mdi/ path. Use
__STATIC_PATH__ instead, like the translation and locale data fetches.
The value is /static/ in all current builds, so nothing changes today.
Builds that serve static files from another location, such as an embed
on another site, can now load icons.


Claude-Session: https://claude.ai/code/session_01HqnRKRicxMCBK3EuxYXimM

Co-authored-by: Claude <[email protected]>
2026-09-25 07:08:25 +02:00
Aidan TimsonandCopilot Autofix powered by AI f4bb4e242d Improve data table loading (#54322)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-24 18:24:20 +01:00
Aidan Timson eb91411cfe Fix bottom padding in device and area add to dialogs (#54337) 2026-09-24 18:05:37 +03:00
Aidan Timson 1767632811 Fix unstyled border router rows in Thread panel (#54340)
Import list item components in Thread panel
2026-09-24 18:04:19 +03:00
Aidan Timson 7c5dd1841b Stop agents asking for tests on visual components (#54343) 2026-09-24 15:58:22 +01:00
Petar PetrovandMindFreeze d8effd44b2 Wrap refresh token supporting text on narrow screens (#54338)
Co-authored-by: MindFreeze <[email protected]>
2026-09-24 11:38:09 +01:00
Copilotandtimmo001 182563d943 Wait for Start to be enabled in onboarding E2E tests (#54329)
Co-authored-by: timmo001 <[email protected]>
2026-09-24 09:58:46 +03:00
Bruno Pantaleão Gonçalves e5f1cb0b1f Hide menu button when external app provides the sidebar (#54321) 2026-09-23 15:44:07 +01:00
Paulus SchoutsenandClaude b31da04913 Fix heading spacing in linked devices card (#54324)
Co-authored-by: Claude <[email protected]>
2026-09-23 15:41:27 +01:00
Franck Nijhof d35c398bfd Bump js-yaml to 4.3.2 (#54320) 2026-09-23 13:46:57 +01:00
Aidan Timson 71f9285e70 Fix initial scroll position in log details (#54315) 2026-09-23 09:50:28 +03:00
Aidan TimsonandNorbert Rittel 117392d71e Add a bug report link to log details (#54305)
* Share GitHub issue URLs and type integration queries

* Share the documentation base URL

* Add a bug report link to log details

* Add horizontal divider

* Name the destination in the log report link text

* Move log reporting into the alert below the header

* Clarify log reporting guidance and alert spacing

* Update src/translations/en.json

Co-authored-by: Norbert Rittel <[email protected]>

* Prefill installation type in log reports

* Add serial comma to log reporting guidance

* Fix log report loading and large log handling

* Clarify custom Frontend modules in log reporting guidance

* Use version-aware documentation links in log reports

* Use contexts and limit health requests in log details

---------

Co-authored-by: Norbert Rittel <[email protected]>
2026-09-22 12:07:59 +02:00
Paulus SchoutsenandClaude 666f88c4da Correct automation, script and trace API types in the frontend (#54291)
Compare the automation, script, trace and blueprint data modules with
the schemas and handlers that produce them, and fix the mismatches.

Add trigger options the backend accepts and the frontend did not
declare, and widen the offsets and time values the schemas allow.
Device actions and their capabilities are often absent, so mark them
optional. Correct several declared results, including saving and
deleting a blueprint, and drop a trace field the backend never sets.


Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

Co-authored-by: Claude <[email protected]>
2026-09-21 18:34:07 +02:00
b12f78c652 Climate dashboard: add my link (#54299)
Co-authored-by: Aidan Timson <[email protected]>
Co-authored-by: Simon Lamon <[email protected]>
2026-09-21 17:30:33 +01:00
Jan-Philipp Benecke 8e10d53012 Render real trigger/condition/action icons and unfinished branch state in trace graph (#54275)
* Render real trigger/condition/action icons and unfinished branch state in trace graph

* Process review: repeat body tracking, service and action icons

* Infer empty repeat body entry from the repeat config

* Track repeat bodies only by their traced steps
2026-09-21 18:30:23 +02:00
Aidan Timson 1813f386de Add field IDs to the bug report form (#54303)
* Add stable field IDs for frontend issue prefill

* Remove issue template prefill comment

* Add IDs to remaining issue form fields

* Link the issue reporting guide in the bug report form
2026-09-21 18:26:46 +02:00
c0ffeeca7 80202cd645 Connectivity panel: add my link (#54296)
Add my link for Connectivity panel
2026-09-21 18:16:49 +02:00
c0ffeeca7andAidan Timson c786f7d2e6 Lights dashboard: add my link (#54297)
Co-authored-by: Aidan Timson <[email protected]>
2026-09-21 18:16:24 +02:00
Paulus SchoutsenandClaude 1ac4382dc5 Correct Supervisor API types in the frontend (#54284)
Compare the hassio and supervisor data modules with the Supervisor
handlers that build the responses, and fix the mismatches.

Add fields the API returns that were missing, including system_managed,
boot_config, dns, host_uts, ingress_port, udev, usb and video. Correct
two names that never matched the wire: services_role is services, and
auto_uart is uart. Drop installed, which belongs to the store model
rather than the app info payload, and drop repositories from the app
list, which the list handler does not return.

Mark the many fields the Supervisor can return as null, and replace the
placeholder issue and suggestion string arrays in the resolution types
with the objects the API sends.


Claude-Session: https://claude.ai/code/session_01YDqKNfAAvMV7zJJNodsHfK

Co-authored-by: Claude <[email protected]>
2026-09-21 18:13:19 +02:00
Sirakorn Lamyai d0220b6a72 No username in filter condition for eligible users, to allow Command Line auth provider (#54280)
* fix: no username in filter condition for eligible users

* fix: hide user.username in brackets if username is null

* fix: hide username/password row only when linked user has homeassistant credential

* fix: validate ability to login using credentials length
2026-09-21 12:18:08 +02:00
c0ffeeca7 bf21bfa777 Modbus panel: add my link (#54302) 2026-09-21 11:02:07 +01:00
c0ffeeca7 1fc565b602 Security dashboard: add my link (#54298) 2026-09-21 10:33:43 +01:00
7ac932ff7e Use the tool result field in the chat log (#54294)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Claude <[email protected]>
2026-09-21 09:57:30 +01:00
Petar Petrov 996ccd50d6 Filter config entry picker by requested subentry type (#54224) 2026-09-21 09:29:15 +01:00
Petar Petrov 24fde161c4 Fix calendar card refresh loop on browsers without Intl longOffset support (#54221) 2026-09-21 09:26:39 +01:00
Bruno Pantaleão Gonçalves d005f694e1 Let the map overview list scroll through the bottom safe area (#54282)
* Let the map sheet reach the screen edges

On a phone the map bleeds past the view's safe-area padding but the overview
sheet over it did not, so a strip of map stayed visible down the sheet's
trailing side and under it. The sheet now bleeds to the same edges.

Reaching the bottom of the screen means the list can scroll through the safe
area instead of stopping above it. The list keeps that much padding at its own
end, so the last row still clears the area once it is scrolled to.

* Drop the comments

* Drop the map card offsets, which never moved the sheet

On a phone the overview is a position: fixed dialog inside
ha-resizable-bottom-sheet, anchored to the viewport with its own bottom and
side insets, which this component already sets to zero. Offsetting the host
around it moved nothing, so the change was inert.

What is left is the part that runs inside the sheet: the list scrolling
through the panel's bottom padding instead of stopping above it.
2026-09-21 07:07:45 +02:00
karwosts 299e612646 Make helpers table robust to entity-id changes (#54261)
* Remove duplicate entityReg subscription in helpers

* initialize to undefined

* Make helpers table robust to entity-id changes
2026-09-20 11:04:50 +02:00
Jan-Philipp Benecke 5fa14d4173 Refresh trace graph primitives to match automation editor (#54253) 2026-09-20 11:04:37 +02:00
Petar Petrov a4d1cb0a57 Downsample the history timeline to the chart's pixel width (#54252)
* Extract the history timeline chart data transform

Move the body of state-history-chart-timeline's _generateData into
state-history-chart-timeline-data.ts, mirroring the line chart's
state-history-chart-line-data.ts. Environment inputs are passed in, so the
transform is a pure function that can be tested and benchmarked on its own.

No behaviour change.

* Downsample the history timeline to the chart's pixel width

The timeline emitted one rectangle per state change with no downsampling, so an
entity with tens of thousands of recorded changes produced tens of thousands of
rectangles and blocked the main thread for seconds inside ECharts' layout.

Bound the output by the chart's device-pixel width, the way ha-chart-base
already does for line series: segments at least one frame wide keep their exact
bounds, and runs of narrower ones resolve per frame to the state covering most
of that frame, merging with neighbours that resolve to the same state. Charts
whose state changes are all wider than a frame, which is the common case, keep
exactly the rectangles they had before.

The host also becomes a block box so it reports its own width; as an inline box
its clientWidth was always 0.

* Narrow the timeline data transform's hass parameter to the states it reads

* Pass entity states to the timeline data transform instead of hass
2026-09-20 10:49:25 +02:00
dependabot[bot] 43c3b51829 Bump the codeql-action group across 1 directory with 2 updates (#54274)
Bumps the codeql-action group with 2 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)

Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: codeql-action
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-20 09:04:49 +02:00
Jan-Philipp Benecke 66a454821a Show disabled automations as event chips instead of disabled bar (#54248) 2026-09-20 08:59:34 +03:00
Paulus SchoutsenandClaude Opus 5 4f713aa645 Fix card header line height when the title wraps (#54258)
* Tighten MCP card header line height

The shared ha-card header uses --ha-line-height-expanded (2), which leaves a
large gap between lines once "Model Context Protocol" wraps on narrow screens
or at a larger font scale. Use --ha-line-height-condensed for this header, the
same value the ZHA group pages already use.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cg5a2sBXVms8HCs2t96DNE

* Fix card header line height for all ha-card

The shared header used --ha-line-height-expanded (2), so at 24px every line
box was 48px tall. That leading doubled as the header's vertical spacing, so
a header that wraps got a 48px gap between its lines.

Separate the two concerns: --ha-line-height-condensed sets the leading, and
the padding carries the spacing the half-leading used to provide. A
single-line header goes from 76px to 73px, so existing cards keep their
look, while each extra line now adds 29px instead of 48px.

Drop the per-card override in mcp-pref, which the default now covers.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cg5a2sBXVms8HCs2t96DNE

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-20 08:57:03 +03:00
Rick van Hattem cedc2d5324 Add extended date range presets to Activity (#54273) 2026-09-19 18:55:08 -07:00
karwosts 15290231ea Remove duplicate entityReg subscription in helpers (#54257)
* Remove duplicate entityReg subscription in helpers

* initialize to undefined
2026-09-19 23:35:04 +02:00
Bruno Pantaleão Gonçalves 5960dfea0e Let the table rows reach the edges of the screen (#54267)
* Let the table rows reach the edges of the screen

The rows stopped at the safe area, so their dividers and the shading
behind a group header ended in a line down the middle of the screen. The
rows now span the full width while their content keeps the inset, so
nothing readable moves and nothing sits under the cutout.

* Bleed the row and group header backgrounds too

* Bleed the table itself so every row variant lines up
2026-09-19 23:10:14 +02:00
Bruno Pantaleão Gonçalves d830220eff Let the filters bar reach the edges of the screen (#54266)
* Let the filters bar reach the edges of the screen

The row of filter and sort controls stopped at the safe area, so on a
device with a horizontal inset it sat in a narrower strip than the list
below it, its bottom border stopping short of the edge. The bar now
spans the full width, its controls scroll under the inset, and a spacer
at the end keeps the last one clear of it by the inset plus the usual
16px. A scrolled flex row drops its end padding, so that space has to be
an item rather than padding.

The subpage keeps the inset as padding inside its scroller instead of an
outer margin, so the bar can bleed into it, and a narrow data table
gives the header row the full width rather than clipping it. The rows of
the table itself stay inside the safe area as before.

* Address review on the filters bar safe area
2026-09-19 22:55:22 +02:00
Bruno Pantaleão Gonçalves c6f72c9cf5 Let the map fill the screen on the map dashboard (#54263)
* Let the map fill the screen on the map dashboard

A map in a panel view stopped at the safe area, leaving a strip of empty
card beside it, and the drawer stopped there too. Map tiles carry no text
to read, so the map and the drawer now run to the edges of the screen,
while everything that is read or tapped stays inside the safe area: the
drawer's content, the card's buttons, and the map's own controls, which
already had insets for the drawer and now take the safe area as well.

The view container exposes the insets it applies as custom properties so
the card can cancel exactly those, and the bottom sheet takes its side
insets from properties that default to the safe area.

* Address review on the map full bleed
2026-09-19 22:37:43 +02:00
Bruno Pantaleão Gonçalves 60f7728d54 Let the settings cards reach the edges of the screen (#54269)
On a phone the cards on the settings page are full-width bands with a
border on top and bottom. They stopped at the safe area, so on a device
with a horizontal inset every band ended in a line down the middle of
the screen. The bands now span the full width and pad their contents by
the inset, so the rows inside them do not move.
2026-09-19 22:22:28 +02:00
Bruno Pantaleão Gonçalves 6014ee7744 Draw the header border across the safe area (#54265)
The header's background already reaches the edges of the screen, but the
row that carries the bottom border sits inside the header's safe area
padding, so on a device with a horizontal inset the border stopped short
of the edge. The row now spans that padding while its content stays
where it was.
2026-09-19 22:07:22 +02:00
Bruno Pantaleão Gonçalves f32833fcbe Keep the bottom tab bar inside the horizontal safe area (#54262)
On a device with a left or right inset the tabs ran underneath it, so the
last tab was clipped by the rounded corner. The bar keeps its full width,
so its background still reaches the edges of the screen, and only the
tabs inside it are inset.
2026-09-19 21:54:59 +02:00
Bruno Pantaleão Gonçalves a9295ac21b Centre toasts in the safe area (#54270)
Toasts were centred on the viewport, so on a device whose safe area is
not symmetric they sat off centre and ran under the cutout. They now
take the same centring offset the dialogs use, and the stack is capped
at the safe width so a wide toast cannot reach past the inset either.
2026-09-19 21:52:17 +02:00
Petar Petrov 66cc3f62c5 Refresh voice expose table when an entity alias changes (#54233) 2026-09-19 09:40:32 +02:00
Petar Petrov fb1a75edd4 Defer chart work while the chart is not visible (#54251)
* Defer chart work while the chart is not visible

ha-chart-base did its full update path no matter whether anyone could see
the chart: every data or options change re-ran the line downsampling and
chart.setOption, and the resulting animation kept repainting the canvas.
That applied to charts in a section hidden by a visibility condition, to
charts scrolled far off a long page, and to every chart in a background
tab, where live history charts kept paying it on each stream message.

Gate the work on rendered size, an IntersectionObserver with one viewport
of margin, and document.visibilityState. While invisible the chart records
which properties changed and replays them in a single setOption once it is
visible again. The initial setup is deferred the same way, so a chart that
first renders hidden is built at its real width, and a synced zoom that
arrives before that setup is replayed instead of dropped.

* Track chart visibility from the observers instead of measuring

Reading getBoundingClientRect() in willUpdate forced a synchronous layout
for every chart on every data or options change, right after the parent had
committed DOM. Keep the state the observers already report instead: whether
the resize entry has a non-zero content box, and whether the intersection
observer sees the element. Both start true so a chart on screen still
renders on its first update, and firstUpdated keeps one measurement so a
chart that first renders inside a hidden container defers its setup.

The observer margin is one screenful only on a phone; a desktop gets a fixed
band, where a whole viewport would cover most of the page.

A reset to the full range now clears a stored zoom rather than replaying it,
and the global reset no longer skips a chart that has not been built yet, so
a deferred chart cannot come back zoomed after everything else was reset.

* Queue a synced zoom while a chart rebuild is pending

* Use the observed chart width for the default height and downsampling

* Use MobileAwareMixin for the chart's mobile checks
2026-09-19 09:34:14 +02:00
Maarten Lakerveld 8f7184023a Improve zone editor (#54031)
* Show a zone's own icon and color on the zone dialog map

The location selector's icon option was never applied: the expression
parsed as (icon || radius) ? radius-icon : marker-icon, so the zone
dialog always showed the radius marker instead of the zone's icon. The
selector also gains a color option, and both zone dialogs pass the
zone's icon and its map color (the config panel hands the dialog the
zone's entity id for that), so the map in the dialog looks like the zone
does everywhere else, including the home zone and a live passive toggle.

* Show zone markers in the zone list

The zones list on the zone config page shows each zone as it looks on
the map: its color with its icon, or initials without one, instead of
a plain icon.

* Sort zones alphabetically with home first

The zone config page listed UI zones sorted and YAML zones after them in
state order; the map overview sorted all zones by name. Both now show the
home zone first and the rest alphabetically.

* Color the zone list and dialogs from the registry context

The zone list avatar and the zone dialog map take the registry entries; the
home zone dialog needs none, its color is fixed.

* Show zone initials in the editor and resolve color from registry

Fall back to the zone's initials (matching the list and map) when it has
no icon, and to a plain map-marker when there is no name yet, instead of
the map-marker-radius pin.

Resolve the zone's entity id reactively from the registry context the
dialog already consumes, so the marker color is correct even when the
registry loads after the dialog opens (e.g. direct /edit/ deep link).

* Preview the palette color a new zone will take

Creating a zone has no entity yet, so the marker fell back to the accent
color and then changed on save. Derive the prospective creation-order
color from the registry so the create preview matches the saved zone.

* Test the new zone's previewed color

Cover nextZoneColor: the next creation-order slot for an active zone (home
excluded) and the muted color for a passive one, so an off-by-one in the
slot count can't silently make the create preview differ from the saved zone.
2026-09-19 09:30:31 +02:00
Maarten Lakerveld f3aba8f142 Activity timeline dots colored by zone in map panel (#54030)
* Color activity timeline dots by zone

Zone changes in a person's or device's activity timeline show the dot in
that zone's color, the same color as its marker on the map and its row
in the zones tab; away and unknown stay grey. Arrivals and departures in
a zone's own timeline keep their green and grey.

* Color activity dots from the registry context

The zone color of a timeline entry takes the registry entries the overview
already consumes.
2026-09-19 08:23:36 +03:00
tzagimandYosi Levy 9c28c21792 Fix RTL bidi corruption of min/max temperature in more-info weather dialog (#54255)
* Fix RTL bidi corruption of min/max temperature in more-info weather dialog

* Fix direction also on attribution style

---------

Co-authored-by: Yosi Levy <[email protected]>
2026-09-19 08:15:50 +03:00
Jan-Philipp Benecke ccceddfd35 Add missing labels to previous and next tracked node in trace graph (#54244) 2026-09-19 08:13:19 +03:00
Jan-Philipp Benecke e633e5fb3e Introduce trace tree model for automation/script trace graphs (#54246)
* Introduce trace tree model for the automation/script trace graphs

* Process code review comments

* Process missed comments
2026-09-18 20:25:07 +02:00
WendelinandSimon Lamon 9a311b0518 Migrate md lists in 7 files (#54220)
* Fix network info secondary text size

* Migrate profile

* Migrate config-entries to list-base

* Revert wrapper a for ha-dropdown-item

* Revert wrapper a for ha-dropdown-item

* Copliot review

* Prettier

---------

Co-authored-by: Simon Lamon <[email protected]>
2026-09-18 16:20:11 +03:00
c07f421f74 Regenerate statistics chart data when the formatters change (#54232)
* Regenerate statistics chart data when the formatters change

statistics-chart resolves its series names once and caches them in
_chartData, and it rebuilt only when the fetched statistics changed. A
rename therefore left the legend showing the old name.

The formatters are replaced as a set whenever the registries change, so
comparing formatEntityName identity is enough to catch it. This covers
the statistics graph card and the more-info history dialog; the energy
dashboard cards cache their series the same way and are handled
separately.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Refresh statistics chart legend labels

Co-authored-by: MindFreeze <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: MindFreeze <[email protected]>
2026-09-18 09:25:57 +02:00
Maarten Lakerveld 62acda8c08 New Map Panel (#54029)
* Add people, devices, and zones overview to the map card in panel view

When the map card is the single card of a panel view it shows a
floating overview with People, Devices, and Zones tabs styled as an
animated segmented control; on mobile it becomes a bottom sheet drawer
that can be collapsed by tap or swipe. People list their zone or Away
state with the last update time, devices only appear when they have a
location, and zones show their occupant count while passive zones are
hidden in this view.

Selecting a row or map marker opens a detail view with a back button,
a name that opens the more info dialog, and a 24h activity timeline:
zone changes for a person or device, arrivals and departures per person
for a zone. Selecting focuses the map (street level for people, the
radius for zones, shown only while selected), marks the selected marker
with a thicker border, shows the accuracy circle when the position is
imprecise, and clicking the map deselects. In panel layout the overview
sits at the start side, so the zoom control and map buttons move to the
other side: ha-map gains a zoom-position property for that, and honours
--ha-map-bottom-inset so the attribution and scale stay clear of the
bottom sheet.

* Resubscribe the map card's colors when the connection changes

The card kept its entity color subscription on whichever connection it
first saw. It now remembers that connection and subscribes anew when
hass brings a different one, as ha-map already does.

* Pause auto-fit before a deferred fit, and never select an empty tab

An explicit fit that had to wait for the engine or for a size did not
pause auto-fit until it ran, so an auto-fit queued in between could take
its place. The pause comes first now.

The overview's selected tab could be an empty, disabled one, showing an
empty list while another tab had content and leaving aria-selected on a
disabled button; the selection falls back to the first tab with items,
which the tab stop already did.

* Reuse the cards' show-more-info label in the map overview

The overview added its own copy of a label the other cards already have
translated; it uses the shared key and the duplicate is gone.

* Keep a focused marker clear of the overview

Focusing a person or zone fitted the full viewport, so the marker could
land under the overview: the start side on desktop, the bottom sheet on
phones. Fits now take viewport padding, both engines apply it per fit,
and the card passes the overview's size as padding on the side it covers,
honoring right-to-left layouts.

* Report activity that could not load, and list only events inside the window

A failed history request, or an instance without the history integration,
read as no recent activity; the panel now says the activity could not be
loaded. The first history sample is the state at the window's start, not
a change inside it, so a person who has not moved for days no longer shows
that old state as recent activity: samples before the window only seed
the previous state, for zones and people alike.

* Take the map card and overview colors from the registry context

The card no longer runs its own color subscription, and the overview reads
the registry entries for its zone list.

* Keep automatic fits clear of the overview

Only a selection fit knew about the drawer; the first fit and every
auto-fit used the whole viewport, so markers could land under the drawer.
ha-map takes a fit padding that automatic fits apply, and refits when it
changes, so the map settles once the drawer reports its size.

* Let the activity timeline scroll inside the drawer

On phones the drawer body is capped at 60vh and clips its overflow for the
collapse animation, so activity entries beyond that were unreachable. The
activity box now scrolls within the drawer.

* Keep the scale ruler and attribution beside the drawer on wide layouts

The bottom inset that lifts the map controls above the drawer only applied
on phones, so on desktop a tall drawer covered the scale ruler. ha-map gains
left and right insets for its bottom controls, and the card reserves the
drawer's width on the side it occupies.

* Extract the activity timeline parsing and test it

The window seeding, unavailable skipping and zone transition rules moved
into pure functions with tests, so a regression in the People or Zones
timeline no longer needs manual checking.

* Show the activity timeline as logbook rows

The overview rendered its own timeline items. It now uses ha-logbook-entry
in its narrow layout, so activity reads like the logbook everywhere: the
person, the zone they are in, and when. Arrivals and departures on the zone
tab are the same rows for the person who moved. The card hands hass to the
overview only for these rows.

* Let the resizable bottom sheet stay open at a minimum height

A persistent sheet stops at a pixel minimum instead of closing when dragged
down, can open at its content height within a configurable share of the
viewport rather than at least 55%, reports its height after opening and
resizing, and lets a host shrink the grab area below the handle for content
that sits right under it. The map overview uses all of this on phones; the
automation editor keeps the previous behavior.

* Show the overview as a bottom sheet on phones

The overview had its own collapsible panel with a handle button and swipe
handling. On phones it now renders inside ha-resizable-bottom-sheet in its
persistent mode, so it resizes like the automation editor's sheet and stops
at a strip with the tabs instead of closing. The sheet reports its height
for the map's insets and fit padding; wide layouts keep the floating panel.

* Let only the newest activity load show its result

Comparing the selected entity after the fetch let an older load for the
same entity pass when the user selected it, moved away, and came back,
so a stale result or failure flag could overwrite the newer one. Number
the loads and let only the most recent one commit its result.

* Include people without a location in the map overview

show_all builds the map entity list from located entities only, so people
whose location is currently unknown never reached the overview's people
list (with its no-location rows) or its zone activity history. Build a
separate overview list that adds those people back, while the map markers
keep the location filter.

* Move focus with the map overview detail view

Selecting an item swapped the list for the detail view (and back) without
moving focus, so keyboard and screen-reader users lost their place on the
removed element. Focus the detail heading when it opens, and restore focus
to the originating item when returning to the list.

* Keep the bottom sheet's minimum height correct after opening

minHeight is a pixel value converted to a viewport percentage and cached
once the sheet opens. Recompute it when the viewport changes (e.g. rotation)
so the cached percentage can no longer clip the persistent peek content, and
emit bottom-sheet-resized once a raised minimum has grown the sheet, so the
host updates its overlay padding instead of holding a stale value until the
next drag.

* Address Copilot review on the map overview

- Keep locationless people in the map entities so a marker appears once
  they are located, not only after a rebuild
- Restore focus to the active tab when a back navigation's row is on
  another tab
- Only reserve overview padding in panel layout

* Draw the cluster bubble and its tail with one shadow

The bubble carried its own box-shadow while the tail sat behind it, so the
bubble's shadow fell across the tail and showed a seam. The bubble and tail now
share one drop-shadow on the wrapper, so the tail reads as part of the bubble.

* Bubble a lone person or device in a zone

A zone group only bubbled with more than one member, so a single person or
device in a zone showed as a plain marker instead of a bubble at the zone.
Keyed (zone) groups now bubble even with one member, pinned to the zone; a
marker that is not in a zone still shows plainly.

* Recover located-later device trackers in the show_all overview

show_all freezes the located entities at generation, so a standalone device
tracker that gains a location afterwards stayed out of the Devices tab until
reload. Recover eligible standalone trackers alongside people, skipping those
that belong to a person.
2026-09-17 22:28:18 +01:00
Paul Bottein 193cbcbfac Allow removing orphaned areas in vacuum segment mapping (#54179)
* Allow removing orphaned areas in vacuum segment mapping

* Type event handler and use RTL-safe padding in vacuum area mapper

* Include the area name in the remove mapping label
2026-09-17 20:09:26 +00:00
Wendelin d43f7e58b6 Onboarding: Improve translation loading (#54176)
* onboarding: Improve translation loading

* Fix generic picker auth check

* fix _translationsReady default
2026-09-17 20:42:39 +02:00
Bruno Pantaleão Gonçalves fb419538c7 Fix login page safe area insets (#54229)
Center the login page inside the safe area

The authorize page only applied the top safe-area inset, so on devices
with side insets the card, password field, forgot password link and
help link were centered on the full viewport and clipped by the right
inset. Add the left and right insets to the content wrapper padding so
the auto margins center the card inside the safe area, and pad the
bottom inset as well.
2026-09-17 15:57:30 +02:00
c0ffeeca7 7c7549349a Add my link for serial panel under Connectivity (#54225) 2026-09-17 14:05:14 +02:00
Jan-Philipp Benecke 051f51dd26 Hide trigger index in trigger references unless triggered-by is edited (#54228) 2026-09-17 14:00:50 +02:00
Maarten Lakerveld 9a9d747899 Redesign map markers (#54025)
* Redesign map markers with zone circles and avatar cluster bubbles

Zones are drawn as colored circles containing the zone icon, using the
entity's color with the zone radius and GPS accuracy circles matching
it. Marker clusters render as a bubble of up to three rounded square
avatars with a +N chip; when all members are in the same zone and the
bubble would overlap that zone's circle, it floats above the circle,
pinned to the zone's coordinate, with a tail pointing at it. Individual
markers are rounded squares, and while history trails are shown bubble
avatars get borders in their entity color so trails can be matched.
Avatars in bubbles are clickable and open the entity, and the whole
bubble zooms in on its members.

ha-map gains per-entity hide_radius, hide_accuracy, and selected
options for hosts that manage a selection; ha-entity-marker exposes its
background and border width via CSS variables and a selected state with
a thicker border. The OSMF vector tiles carry some places twice (node
and boundary centroid); towns and larger now require a population,
keeping the node, and smaller places get a collision padding.

* Frame person and device markers, ring the selected one

Markers get a card-colored frame with a soft shadow instead of a thin
border in the entity color, and the selected marker gets a primary-color
ring outside that frame. With history trails shown the frame still takes
the entity color, so a marker can be matched to its trail, and the
markers redraw when trails appear or disappear.

* Drop the editor's drag classes

The engine sets the move cursor on the elements it actually drags, so the
zone marker and the named icon no longer carry a class for it, and the
editor's element cache no longer varies with editability.

* Keep dragged values on the zone page until they are saved

The engine used to guess at the host's save state: after a drag it
skipped one update that matched the pre-drag values, taking it for a
re-render with data the save had not yet replaced. That guess is wrong
when a save fails, since the old values are then the truth and the
marker stayed at an unsaved position. The engine now applies every host
update except while a drag is in progress.

The zone page, which knows when it is saving, keeps the dragged values
as pending edits and shows them until the saved data carries them; a
failed save drops them and the marker returns.

* Subscribe to entity colors only for maps that draw entities

Every map with a connection subscribed to the entity registry for the
creation-order colors, including editor maps that never draw an entity.
Onboarding's location picker is one, and its mocked server rejects the
registry request, failing the onboarding end-to-end tests. The
subscription now starts when a map first draws entities.

* Address code review on the marker redesign

The selected ring's color came from an inline outline-color that beat the
rule's outline shorthand by precedence, which reads as if the shorthand
won; the inline style now sets a variable the rule consumes, with the
primary color as fallback. A map whose connection context changes
resubscribes to the entity colors instead of staying bound to the old
connection. The zone page's willUpdate called the wrong lifecycle hook on
its base class.

* Tell the user when a dragged zone edit fails to save

A failed save dropped the pending edit and rethrew, which no caller
awaited, leaving an unhandled rejection and a marker that silently moved
back. The page now shows the error in a dialog instead.

* Drop the numeric cluster badge styles, follow a replaced connection for colors

Clusters are avatar bubbles now, so the styles for the old count badge
had nothing left to style. The shared entity color subscription is a
module-level singleton keyed to whichever connection subscribed first; a
map arriving with a different connection now takes the stream over
instead of reading colors from the old one.

* Fall back to the palette color for entities without one, recolor zones on theme change

An entity object without a color reached the accuracy circle's paint
with an undefined color; the map's own palette color fills in. The zone
page's markers are memoized on their data, while their colors come from
theme variables, so a theme change now bumps the color version and
recolors them at once.

* Redraw markers on a theme change, and test the entity color assignment

Marker and trail colors are resolved from theme variables when drawn, but
a theme change only swapped the base style, so the old palette stayed on
the markers until something else redrew them. Any change to the themes
now redraws entities and trails.

The color assignment gets unit tests: creation order per domain, ties
broken by registry id, the home zone kept out of the palette, muted
passive zones, a stable fallback for entities outside the registry, and
one shared registry stream released with the last subscriber.

* Count entity color subscriptions from the listener set

The listener set deduplicated a reused callback while a separate counter
counted every call, so the two could disagree and the shared registry
stream could leak or be released early. Each subscription is now its own
listener, the count is the set's size, and unsubscribing twice is a no-op.

* Release the entity color subscription when a map stops drawing entities

A map whose entities were unset kept its registry subscription, holding
the shared stream open for nothing. It is released along with the
markers, and the three release sites share one helper.

* Address code review on the marker redesign, third round

The zone page's updated() override never called its base, so once
willUpdate stopped misusing super.updated the subscribe mixin had no hook
left to run hassSubscribe when hass arrives after connection; the override
calls super.updated now.

Saves for one zone run in order, each looking the entry up when it starts,
so a second response can replace what the first produced, and a failure
only drops the pending values its own request carried. A passive zone that
is not drawn no longer anchors a cluster bubble. A map whose entity list
empties releases the color subscription, not only one whose list is unset.

* Address code review: drop settled zone save queues

The per-zone save chain kept its last resolved promise for the life of the panel.

* Remove label dedupe

The doubled place labels are a tile issue, not part of the marker redesign,
and the population filter did nothing on the OSMF tiles, which fill in a
default population for every place. It moves to its own branch.

* Address code review: keep the label mode in cluster bubbles

Bubble avatars only carried the label text and picture, so an entity set to
the icon label mode showed initials once clustered and the attribute mode lost
its unit. The icon flag and unit now travel with the cluster data.

* Address code review: color map card entities from the shared palette

The card kept its own color dictionary, so an entity could have a different
color on every map. It now uses the palette that ha-map and the zone editor
already share, ordered by registry creation; a configured color still wins.

* Address code review: take entity colors from the registry context

The color module kept its own shared registry subscription with listener
counting and connection takeover. The lazy fullEntitiesContext already does
that for the whole app, so the module is now pure: it turns the registry
entries into a palette index, memoized per registry update. Maps ask for
the context only once they draw entities, so an editor's map, as in
onboarding, never requests the registry; the map card and the zone page
consume it directly.

* Address code review: one palette sequence for zones, persons and trackers

Per-domain sequences all started at slot 0, so the first person and the
first zone shared a color and a person could match the zone it was in.

* Address code review: recolor history trails when the registry changes

The trail colors are memoized with the registry entries as a key, like the
marker colors, so trails recolor with their markers when the registry
arrives or changes.

* Address code review: follow theme changes and keep bubble focus

The map card rebuilds its entity colors and trail colors when the theme
changes, ha-map redraws editable circles on a theme change, and the
locations editor rebuilds its cached marker elements. A focused cluster
bubble keeps focus on the bubble that replaces it, and a caller naming a
marker by aria-labelledby keeps that name.

* Address code review: recolor the map card from the themes context

The card consumed the theme through hass, whose update gate only lets a
dark mode flip through, so switching between two light or two dark themes
kept the old palette. It now consumes the themes from the UI context, like
ha-map, and rebuilds its entity and trail colors whenever they change.

* Address code review: keep the editor alert clear of the zoom control in RTL

The zoom control sits at the physical top-left in either text direction,
but the alert used logical insets, so in RTL its clearance moved to the
right and it covered the control.

* Fix the bubble tail covering the middle member

The tail is a rotated square whose upper half sits under the bubble. It was
painted on top, so in an open bubble it covered the bottom of the middle
member's frame and selected ring as a white triangle. Both tails now sit
behind their bubble.

* Narrow the locations editor to the themes context

ha-locations-editor consumed the whole uiContext but only reads themes, so
it rerendered on unrelated panel, sidebar, and UI-state changes. Transform
the context to Themes, following the pattern in hui-map-card.

* Keep focus when a cluster collapses to a single marker

Regrouping restored focus only to a replacement cluster icon, but a group
that becomes a single member is shown as a standalone marker with no icon,
so focus fell back to the document. Focus the member element in that case.
2026-09-17 12:26:11 +01:00
Bruno Pantaleão Gonçalves 5b99462fdf Fix notification drawer right safe area inset (#54230)
Apply the right safe-area inset to the full-width notification drawer

The drawer spans the full viewport whenever narrow is true (viewport
under 870px), but the right inset padding on the header and list was
only applied below a 450px media query. Between those widths the close
button ended up under the right inset. Reflect narrow as an attribute
and key the padding off it so the inset follows the same rule as the
drawer width.
2026-09-17 14:22:39 +03:00
Jan-Philipp BeneckeandCopilot Autofix powered by AI 14ef770c44 Overlay trace graph step navigation on the graph (#54227)
* Overlay trace graph step navigation on the graph

* Fix height problem

* Increase margin

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-17 14:20:00 +03:00
Przemysław Kłys 6a9fca2cb9 Fix logbook labels for restored button states (#54203)
* Fix logbook labels for unavailable timestamp entities

* Fix restored button context classification
2026-09-17 06:40:09 +00:00
Petar Petrov 55ba59074e Fix energy distribution home ring overflowing to 100% grid (#54191)
* Fix energy distribution home ring overflowing to 100% grid

Size the home circle from allocated used_solar, used_battery, and
used_grid instead of net used_total so misaligned hours cannot produce
a negative grid arc.

* Add gallery demo for energy distribution home ring

Mock the issue 54185 daily totals with realistic hourly PV, battery,
and grid statistics, including an export-lagged card that overflows
the old ring math.

* Remove gallery energy distribution demo from this PR

Keep the home-ring fix and its unit tests; drop the gallery page
that was only used for local browser verification.

* Keep a zero-consumption home ring as a plain border

When solar is configured but allocated flows are all zero, leave the
arcs unset so the card can show the home outline instead of zero-length
dashes on a borderless circle.

* Keep a defined zero low-carbon home arc

The energy distribution card mounts the home SVG when solar or
lowCarbon is defined. Omitting a 0 leftover hid grid and battery
arcs on a no-solar 100% high-carbon ring.
2026-09-16 15:49:29 +02:00
Maarten Lakerveld eeb674dd5a Show the selected light control on light group members (#54167)
* Show the selected light control on light group members

When a light group's more-info dialog is switched to color temperature, the
member tiles listed below now show a color temperature slider instead of
brightness, so the children can be adjusted on the same axis as the group.

The light control fires light-main-control-changed whenever its main control
changes, and more-info-content picks the member tile feature from that.
Members that do not support color temperature keep their brightness slider,
and the color mode keeps brightness since there is no tile feature for it.
Legacy group.* entities are unchanged.

* Hide member light control when group is in RGB color mode

There is no RGB tile feature, so showing a brightness slider on group
members while the group control is set to color is inconsistent. Show no
control in that case instead, per review feedback.
2026-09-16 15:44:11 +02:00
Jan-Philipp Benecke afe6e84e3c Make trace pages resizable two-pane layouts (#54216)
* Make trace pages resizable two-pane layouts

* Remove cast

* Remove cast
2026-09-16 16:06:56 +03:00
Bruno Pantaleão Gonçalves 3ddbc8f4e3 Communicate entity control to external bus (#54215)
* Communicate entity control to external bus

* Prefer target entity ids and report disconnecting calls

* Split and lowercase entity ids like Core does

* Keep entity control reporting best effort

* Assert wildcard entity ids are dropped
2026-09-16 15:25:32 +03:00
Jan-Philipp Benecke 216468cf50 Strip unreferenced duplicate trigger IDs (#54214) 2026-09-16 13:52:04 +02:00
Bram KragtenandClaude Opus 5 0ef3e9c71a Resolve statistic labels with structured entity names (#54202)
* Resolve statistic labels with structured entity names

getStatisticLabel resolved names through computeStateName, so every
statistic-shaped label — the energy dashboard cards, the sankey cards,
hui-statistic-card, chart series names and the energy configuration
dialogs — showed the flat friendly_name attribute while the rest of the
UI composed names from the device, area and floor.

It now asks hass.formatEntityName for the default composition, which
also makes the entity branch of computeEnergyLabel redundant.

The metadata fallback stays: external statistics have no entity to
resolve a name against.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Keep the entity name shape out of the core chunk

recorder.ts sits in the core entry chunk, so importing DEFAULT_ENTITY_NAME
from compute_entity_name_display dragged the registry-aware formatters and
their dependencies in with it and blew the core bundle budget by 4.1%.

The constant and the name types have no runtime dependencies, so they move
to their own module; compute_entity_name_display re-exports them so nothing
else has to change.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-16 09:59:12 +03:00
Bram KragtenandClaude Opus 5 1266b0c87a Remove unused element registration imports (#54206)
ESLint cannot judge side-effect imports like `import "../../components/ha-card";`,
so dead component registrations accumulate unnoticed. A repo-wide scan matching
every side-effect import against the tag its module registers found 308 imports
whose element is never referenced anywhere in the importing file.

This removes the 84 that carry no registration risk: no other file instantiates
the tag without directly importing the defining module (checked for `<tag>`,
createElement/dynamicElement/customElements.get/whenDefined, and `custom:<tag>`
in Lovelace configs), and every affected module keeps at least one other
importer.

hui-weather-entity-row got ha-state-icon transitively through the dropped
hui-generic-entity-row import, so it now imports ha-state-icon directly, which
is the element it actually renders.

The gauge gallery page is left alone even though its .ts never names the tag: a
gallery page exists to register what its sibling .markdown demos render, and
that import is the registration.

The remaining 224 are deliberately out of scope. Their component is rendered
somewhere else without its own import, so they need the matching import added in
the same change.

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-16 09:52:42 +03:00
Wendelin a695710beb Migrate md lists to new lists in 20 files - 2 (#54208)
* migrate to ha-list-base in 10 files

* migrate lists in 10 files
2026-09-15 19:23:46 +02:00
Wendelin f991efbc0a Migrate md lists to ha-list-base in 20 files (#54197)
* Migrated 10 files from md list to new lists

* migrate 10 files

* copilot review

* fix prettier
2026-09-15 19:06:53 +02:00
renovate[bot] 47306d1afd Update dependency intl-messageformat to v11.2.15 (#54213)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-15 16:33:19 +00:00
karwostsandCopilot Autofix powered by AI 1692067392 Fix create helper dialog (#54211)
* Fix create helper dialog

* Ensure loading state resets after import

Wrap import and dirty tracking in try-finally to ensure loading state is reset.

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-15 18:26:53 +02:00
Paul Bottein 546315ca5b Share entity display and search label helpers across pickers (#54192) 2026-09-15 15:45:04 +03:00
renovate[bot] 7c98912b73 Update formatjs (#54162)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-15 15:42:31 +03:00
Bram KragtenandClaude Opus 5 8c72e9c22d Remove unused Material Web wrappers (#54198)
`ha-outlined-button` and `ha-outlined-field` had no references anywhere
in the repository, so their custom elements were never registered at
runtime. `ha-sub-menu` was imported by five config panels, but no
template renders the tag.

Removes three `@material/web/**/internal/**` import sites; Material Web
is now only reached from chips, list, ripple and iconbutton.

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-15 15:30:00 +03:00
Lucas Mindêllo de Andrade 892514ed21 Show toggle for fan entity only if TURN_ON or TURN_OFF is supported (#54188)
* fix(fan): keep toggle only if on off is supported

* feat(lovelace): add fan entity row

* code review adjusts
2026-09-15 15:26:14 +03:00
Bruno Pantaleão GonçalvesandClaude 06be6f433d Add more info opened and closed external bus messages (#54187)
Co-authored-by: Claude <[email protected]>
2026-09-15 09:29:34 +02:00
renovate[bot] e9a6e2936d Update dependency nanoid to v6 (#54189) 2026-09-15 07:13:27 +00:00
d3b7d787b4 Add trigger ID auto-generation and selection (#54130)
* Add trigger ID auto-generation and selection

* Fix trigger list index and descriptions

* Potential fix for blueprint crash

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Split cleanup

* Process Wendelin code review comments

* Process Marcin code review comments

* Remove unused controller config option

* Swap

* Fix minor review comments

* Update src/panels/config/automation/condition/types/ha-automation-condition-trigger.ts

* Update src/panels/config/automation/condition/types/ha-automation-condition-trigger.ts

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Wendelin <[email protected]>
2026-09-15 09:07:03 +02:00
renovate[bot] 0662f8238f Update dependency hls.js to v1.7.3 (#54181)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-15 06:17:17 +02:00
Jonas PeterssonandJonas Petersson 8a59516d8f Support glass break binary sensors (#53989)
* feat(security): support glass break binary sensors

* fix: add glass_break translation for device class override dropdown

* fix: add glass_break to generated device classes list

* fix: add glass_break icon to entity component icons for demo/fake data

---------

Co-authored-by: Jonas Petersson <[email protected]>
2026-09-14 17:44:15 +02:00
Petar Petrov 0afe6bb136 Cap unsupported config warning height so YAML fallback stays visible (#54177) 2026-09-14 16:52:31 +02:00
Bram KragtenandClaude Opus 5 61b487f995 Rename "For" to "For at least" and let duration inputs fill the row (#54175)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-14 15:35:18 +02:00
91abff2d0c Hide "for" on state condition when matching an attribute (#52710)
* Hide "for" on state condition when matching an attribute

The legacy state condition measures the `for` duration against
`last_changed`, which only updates on state changes, not attribute
changes. So `for` together with `attribute` is unreliable and core is
moving to reject it. Omit the `for` field when an attribute is selected,
drop any lingering duration value, and explain why via a helper.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Keep "for" visible but disabled when matching an attribute

Removing the field left the explanation pointing at a control that was no
longer on screen. Keep "for" in the form, disable it while an attribute is
selected, and move the helper text under it.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-09-14 16:32:15 +03:00
Bram KragtenandClaude Opus 5 53d16c97fe Keep helper text readable on disabled fields (#54174)
Disabled fields dimmed their helper text to the disabled ink color, which
drops it to 2.6:1 contrast in light mode (5.7:1 when enabled). Helper text
is guidance about the control rather than part of its value, and it is often
the only thing explaining why a field is disabled, so keep it at its regular
contrast. The disabled state is still carried by the label, the value, and
the missing clear button.

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-14 16:17:43 +03:00
Bram KragtenandClaude Opus 5 7493bfc86c Honor configured name in bootstrap formatEntityName (#54172)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-14 14:39:26 +02:00
infernalK ca1eb4ed7d Fix TypeError when hass.panels changes while rebuild() is in flight (#54171)
_updateRoutes() awaits this.rebuild() and then reads
this.hass.panels[this._currentPage].component_name without checking that
the entry still exists. hass.panels can be replaced again while the
rebuild() await is pending (e.g. multiple integrations or HACS-managed
Lovelace resources updating panels around startup), leaving
this._currentPage pointing at a panel that is no longer present. The
resulting TypeError breaks rendering of the current dashboard.

Guard the access after the await and bail out when the panel is gone:
willUpdate already re-triggers _updateRoutes for the newer hass.panels
value in that race, so returning early is safe and avoids the crash.

Fixes #54006
2026-09-14 15:38:16 +03:00
Petar PetrovandCopilot Autofix powered by AI c1dd17c4f9 Show Energy Now view for water and gas flow without power sensors (#54100)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-14 14:34:38 +02:00
Stu Kabakoff 5c74a84d01 show up to 5 discrete buttons on fan cards (#54137)
show up to 5 discrete buttons to fan card
2026-09-14 14:14:41 +02:00
shbatmandPetar Petrov a51d255ec3 Show disabled entities when filtering entities by device or area (#53444)
* Show disabled entities when filtering entities by device or area

The device and area filters on the entities config page resolve their
selection through search/related, which omits disabled entities. Opt in
to the new include_disabled_entities option there, so that filtering by
a device or area no longer hides that device's disabled entities.

The option is only set on the entities page, so every other consumer of
findRelated keeps its current behaviour.

* Update src/panels/config/entities/ha-config-entities.ts

Co-authored-by: Petar Petrov <[email protected]>

* Update src/panels/config/entities/ha-config-entities.ts

Co-authored-by: Petar Petrov <[email protected]>

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-09-14 13:25:35 +02:00
Petar Petrov 8c0dec0d9a Align stacked statistics lines across recorder gaps (#54166)
ECharts stacks a time axis by data index, so a statistic with a gap or a
different range shifted every stacked line after it. Merge the stacked line
datasets onto one timeline, let ECharts sample them after stacking, and hide
the padded null rows in the tooltip.
2026-09-14 13:49:48 +03:00
renovate[bot] 2c4b3c9109 Update dependency @rsdoctor/rspack-plugin to v1.6.4 (#54170)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-14 13:34:56 +03:00
Petar Petrov c75bd2b5f0 Fix inconsistent grid labels in energy usage graph (#54168)
Make energy usage graph grid consumption label name-first
2026-09-14 12:07:18 +02:00
Wendelin 9b1665f5bf Refactor more-info update backup row (#54119)
* Extract and refactor update-backup

* run requests in parallel

* Separate fetches

* fix
2026-09-14 10:53:46 +02:00
Wendelin 603528bf47 Landing page: provide and use i18n context (#54128)
Migrate landing page to internationalization context
2026-09-14 10:45:08 +02:00
Wendelin 030b962e26 ha-auth use i18n context (#54127)
Use i18n context in ha-auth
2026-09-14 10:39:07 +02:00
Wendelin 85a34aeeee Onboarding: use localize context (#54126)
* Migrate onboarding to use localize context

* Load onboarding fragment translations after hass initialization.
2026-09-14 10:29:02 +02:00
iven 44dd2249b5 Fix calendar card collapsing with auto height (#54159)
* Fix calendar card collapsing with auto height

* Detect auto height from legacy layout_options
2026-09-14 09:52:04 +02:00
Yosi Levy f073a12cbd RTL chevron fixes (#53771)
* RTL chevron fixes

* Name changes

* Label fix

* Fix missing import
2026-09-14 09:43:41 +02:00
Yosi Levy 7dec4a57e8 Various RTL fixes (#54117)
* Various RTL fixes

* Fixes - no keyboard focus

* Fix style
2026-09-14 06:47:51 +02:00
Paulus SchoutsenandClaude aa78f368b1 Fix discovery list covering card corners on network page (#54157)
The ha-md-list inside the network discovery card draws its own surface
background. That square background hides the rounded bottom corners of
the card. Remove the list background so the card shows through.


Claude-Session: https://claude.ai/code/session_01PLf4NaCFm5tWguyUSmSAEx

Co-authored-by: Claude <[email protected]>
2026-09-14 06:47:01 +02:00
renovate[bot] 06901dedaa Update dependency lint-staged to v17.5.1 (#54155)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-14 06:45:23 +02:00
renovate[bot] 43f194dad2 Update dependency vite to v8.3.0 (#54156)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-14 06:45:04 +02:00
renovate[bot] e7acf97b1a Update babel monorepo to v8.0.5 (#54161)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-14 06:44:12 +02:00
Paulus SchoutsenandClaude Opus 5 9409db7fda Show YAML-configured Modbus hubs in the Modbus panel (#54134)
* Show YAML-configured Modbus hubs in the connections panel

The backend now lists a hub configured in YAML as a connection of its
own, flagged with its source. Render those rows with the hub name and
the units it addresses, marked as configured in YAML, since there is no
config entry to link to.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018gAhZ9auwjmQaTg91efAD4

* Demo the Modbus YAML hub on a TCP device

One serial port cannot carry two links, so a YAML hub sharing the
RS-485 port was not a state the panel can reach. Put the hub on the TCP
device an integration also talks to, where two sockets are real.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018gAhZ9auwjmQaTg91efAD4

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-13 07:08:44 +00:00
dependabot[bot] d917df359f Bump home-assistant/actions/helpers/verify-version from a7c616ce81ccda50150bf1595786c71b1883fabb to 58bff37c8947f690ace498be413a9b78d6f30f93 (#54138)
Bump home-assistant/actions/helpers/verify-version

Bumps [home-assistant/actions/helpers/verify-version](https://github.com/home-assistant/actions) from a7c616ce81ccda50150bf1595786c71b1883fabb to 58bff37c8947f690ace498be413a9b78d6f30f93.
- [Release notes](https://github.com/home-assistant/actions/releases)
- [Commits](https://github.com/home-assistant/actions/compare/a7c616ce81ccda50150bf1595786c71b1883fabb...58bff37c8947f690ace498be413a9b78d6f30f93)

---
updated-dependencies:
- dependency-name: home-assistant/actions/helpers/verify-version
  dependency-version: 58bff37c8947f690ace498be413a9b78d6f30f93
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-13 09:36:50 +03:00
Petar PetrovandCursor Agent 6dcca89185 Move history-graph card timeline names under the bars (#54102)
* Move history-graph card timeline names under the bars

Enable the same inside-labels layout as the History panel on the
Lovelace history-graph card. Custom entity names still override
the default Device ▸ Entity labels from computeHistory.

* Keep compact timeline rows when names are hidden

inside-labels only applies when the history-graph card is showing
names, and the timeline uses the taller row height only when those
under-bar labels are actually drawn.

* Match timeline row height to when inside labels are drawn

Use the same chunked || showNames condition as the axis options so
virtualized charts keep enough room for under-bar names. String YAML
names still apply when the entity is missing from current state;
structured names fall through to computeHistory instead of the entity ID.

* Preserve structured YAML names without a current state

formatEntityName still needs an entity id when the override is an
EntityNameItem. Use a stub state so device/text/entity name configs
apply even if the entity is missing from hass.states.

---------

Co-authored-by: Cursor Agent <[email protected]>
2026-09-12 13:28:53 +02:00
Wendelin 3f1b2ef65f Onboarding: lite internationalization context (#54125)
* Add internatinalization context to onboarding

* Use the context in welcome
2026-09-12 11:53:30 +02:00
Petar Petrov 34afbe37c3 Use ha-control-circular-slider in the light card (#54123)
Replace the legacy @thomasloven/round-slider brightness ring with the
in-house ha-control-circular-slider (already used by the thermostat and
humidifier cards). The card keeps its layout, center toggle button,
brightness readout, size, and all config options, so existing dashboards
are unaffected. The light card was the last consumer of round-slider, so
the dependency and its patch are dropped.
2026-09-12 11:53:05 +02:00
renovate[bot] 848e81313e Update dependency jszip to v3.10.2 (#54132)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-12 09:32:56 +03:00
Paul Bottein 24e7bd306a Sync My redirects with my.home-assistant.io (#53956) 2026-09-11 16:13:45 +02:00
3791548067 Show every selector on the gallery selector page (#54121)
* Show the serial port selector in the gallery

The selector page had no serial_port entry, so the picker could only be
exercised against a running instance with real hardware attached.

Add it to "One of each", backed by a scan mock with one port per section
the picker groups by. The entry carries a flow context, and the page now
forwards that to ha-selector, because the recommended and not recommended
grouping is keyed off the domain a config flow supplies.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NTxTXXEY4FnQryNFbtB5tf

* Answer the ingress panel list in the supervisor demo stub

The navigation picker waits for that collection before it enables itself,
so with the endpoint rejecting it stayed disabled for the whole demo and
gallery, with nothing on screen to say why.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NTxTXXEY4FnQryNFbtB5tf

* Show every selector on the gallery selector page

Twenty-nine of the sixty selectors had no entry, so they could only be
looked at inside a config flow or a blueprint that happened to use one.

Add the missing entries to "One of each", with the mocks the assist and
statistic pickers need to return a list. A few carry a value or a config
because they render their fallback without one: the meta selector reads
the first key of its value, the period selector offers its custom-period
editor, and the voice list is fetched per engine and language.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NTxTXXEY4FnQryNFbtB5tf

* Add new serial port configuration

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-11 17:11:41 +03:00
01cef9a99b Fix trigger 'for' choose (#53749)
* Fix trigger 'for' choose

* fix stub

* try something else

* merge duration-selector with create_duration_data

* handle negatives

* default ms to false for selector

* Handle hidden duration units in ha-duration-input

createDurationData grew three flags describing which fields the duration
input renders, but the input already owns enableDay, enableMillisecond,
enableSecond and allowNegative. Fold the units it does not render there
instead, so createDurationData keeps its single-argument signature.

This handles days and milliseconds symmetrically, and covers every
ha-duration-input consumer rather than only ha-selector-duration:
ha-form-positive_time_period_dict passes .data straight through without
enable-day and dropped days in exactly the same way.

A leading "-" negates the whole period in cv.time_period_str, so the
sign is now always distributed across all parts. The calendar trigger is
the only caller that can see a negative value and does its own sign
handling, so it takes the absolute value of every part instead of just
hours, and copies the duration first since createDurationData returns
dict values by reference.

Co-Authored-By: Claude Opus 5 <[email protected]>

* cleanup calendar trigger

* Refine duration type check for object values

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Bram Kragten <[email protected]>
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-11 16:34:29 +03:00
Bram Kragten 380e9b5a81 Bumped version to 20260826.7 2026-09-11 15:31:53 +02:00
Paulus SchoutsenandClaude de21f7ef43 Prevent closing the backup restore dialog by clicking outside (#54095)
Prevent scrim close on backup restore dialog

Clicking outside the restore dialog dismissed it unless the encryption
key field was dirty. Restoring a backup is destructive, so guard the
dialog at every step.


Claude-Session: https://claude.ai/code/session_017eZQ6BTz6MervuG3Zb8RLp

Co-authored-by: Claude <[email protected]>
2026-09-11 15:31:20 +02:00
Petar Petrov fa3c12050c Fix login form ignoring password-manager autofill (#54076) 2026-09-11 15:31:19 +02:00
Wendelin bee8497724 Fix update last backup description (#54066) 2026-09-11 15:31:18 +02:00
Wendelin 2de21fad27 Fix automation trigger/condition platform default behavior (#54062)
* Fix platform behavior default

* Fix race condition by updating target entity count and setting default behavior
2026-09-11 15:31:17 +02:00
Wendelin 72fcf19091 Fix add TCA mobile list width (#54054) 2026-09-11 15:31:16 +02:00
nokside efa322cc6b Fix and centralize selector initial value handling (#53729)
* Fix and centralize selector initial value handling

* Fix unsupported selector initial values

* Omit undefined choose child values

* Fix device class and object selector initial values
2026-09-11 15:31:15 +02:00
Steffen ProbstandClaude Fable 5 8eb179a0d9 Show pointer cursor on the whole track of the light card's round-slider (#53723)
The classic light card uses @thomasloven/round-slider, whose invisible
`.shadowpath` arc already accepts click/drag (nearest handle follows), but
only the handle dot showed a pointer cursor. Patch the dependency (same
mechanism as leaflet-draw/sortablejs) so the whole track shows the pointer,
and falls back to the default cursor when the slider is disabled or has no
handle. Adds a `--round-slider-path-cursor` override (defaults to
`--round-slider-handle-cursor`).

Co-authored-by: Claude Fable 5 <[email protected]>
2026-09-11 16:10:07 +03:00
pcan08andClaude Sonnet 4.6 34e9b50920 Redesign integration card and remove double navigation (#52828)
* Redesign integration card to align with apps card style

Replace ha-button navigation links with a plain count badge, remove the
ha-icon-next chevron, make the entire card clickable on all content, and match the apps card hover/separator/spacing patterns.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* Extract integration card footer into ha-integration-card-footer

Move footer rendering logic (count badge, custom/cloud/yaml icons) and
their computations into a dedicated component, mirroring the
ha-integration-header split.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* Rename `ha-integration-header` to `ha-integration-card-header`

* Fix count badge vertical centering in integration card footer

* Replace hardcoded pixel values with spacing tokens

* Remove redundant physical margin properties

* Use consistent <span> elements for footer icons

* Remove dead CSS properties

* Add align-items: flex-start to secondary row

* Push integration card footer to bottom regardless of title length

* Migrate to Lit contexts

* Remove idvider in app and integration card

---------

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
2026-09-11 15:16:09 +03:00
Paul Bottein 2ebe452334 Add idle state and stop action to lawn mower (#53957) 2026-09-11 09:58:49 +00:00
renovate[bot] 3052989e9d Update dependency @rspack/core to v2.2.3 (#54118) 2026-09-11 11:39:13 +02:00
Preethi Pantangi fcab4004b2 Reserve min-height for view header to prevent layout shift (#54115) 2026-09-11 09:55:18 +01:00
renovate[bot] 4610adb368 Update dependency marked to v18.0.12 (#54114)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-11 06:42:59 +02:00
renovate[bot] e0dba17b66 Update dependency typescript-eslint to v8.70.0 (#54112)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-11 06:42:41 +02:00
karwosts eee0f9447b Format media selector in object selector (#54107)
Format media selector in object title
2026-09-10 18:34:03 +02:00
Paul Bottein 8d149a914f Add parent device to entity ID format (#54060)
* Add parent device to entity ID format editor

* Explain entity ID format examples with their context

* Share the entity name type list with the entity ID format editor

* Keep filter chip padding stable without a leading icon

* Show one entity ID format example at a time in a separate card

* Shorten entity ID format example names
2026-09-10 16:52:04 +03:00
Paul Bottein b2bb3e9d9d Nest child devices under their parent in device trees (#54063)
* Nest child devices under their parent in the entity tree

* Resolve device entries through shared helpers in the automation target browser

* Nest child devices under their parent when browsing automation targets

* Nest child devices under their parent in target details

* Skip child device rows already nested under their parent in area targets

* Fix expanding the automation target tree to an entity attached to an area

* Skip labeled child device rows already nested under a labeled parent

* Extract target sub-row computation and test child device nesting

* Use the inherited area when hiding filtered child devices

* Keep a parent device as a group row when a child device matches

* Keep child devices at the top level when their parent is disabled

* Drop disabled-parent special cases, core disables children with their parent
2026-09-10 15:46:28 +02:00
karwostsandCopilot Autofix powered by AI 13ef9712bc Use 'image_proxy' endpoint for image entity backgrounds (#54038)
* Use 'image_proxy' endpoint for image entity backgrounds

* Update image source URL with hassUrl method

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* handle concurrent updates

* more robust

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-10 16:42:26 +03:00
Jump-333 40b27608c0 Add buttons style to target-humidity card feature (#53901)
* Add buttons style to target-humidity card feature

* Removed step configuration per-card

* Remove 'step' key from style list in translations

* Add target humidity step to humidity card feature

* Fixed a typo

* Updated style and style_list keys with localization keys.
2026-09-10 16:31:54 +03:00
Aidan Timson e0f03254b5 Show active alerts on Home dashboard (#53526)
* Show security alerts on Home

* Refresh Home security alerts

* Fix Home security alert state handling

* Fix Home alert fallback state

* Render Home alerts as individual cards

* Implement as summaries alerts and warnings in secondary for security
2026-09-10 16:03:49 +03:00
Petar Petrov 35dcba4f3f Fix login form ignoring password-manager autofill (#54076) 2026-09-10 14:31:57 +02:00
Paul Bottein ec4bfc9255 Add parent device to entity context (#53766)
* Add parent device to entity context

* Fix parent device context display edge cases

* Fix parent device context in suggestions and completions

* Order entity name parts by hierarchy

* Remove unused parent device missing string

* Add parent device to logbook entry context

* Show inherited area and parent device for device targets

* Test parent device search in the entity tree

* Show inherited area and parent device in the automation target header

* Move the device domain lookup out of target row item data

* Pass registries to memoized entity name lists

* Document parent device in logbook name detail
2026-09-10 13:38:39 +02:00
Maarten Lakerveld 3b9e026aff Edit zones and locations on the map engine instead of leaflet-draw (#54023)
* Edit zones and locations on the map engine instead of leaflet-draw

ha-locations-editor (zone config, the location selector, onboarding)
used raw Leaflet layers and leaflet-draw, which pinned it to the Leaflet
engine. Its interaction surface is three gestures - drag a marker, drag
a zone center, drag a zone radius handle - so no editing library is
needed.

MapEngine gains an optional editing capability (draggable markers and an
addEditableCircle primitive) plus panTo and containsLocation. Only the
MapLibre engine implements editing: the circle geometry plus a draggable
center marker and a draggable radius handle on the east edge, the radius
derived from the great-circle distance between them, redrawn per frame
while dragging. The handle has a touch-sized hit target and is a
keyboard-operable slider with an accessible name. The Leaflet engine
stays a viewing fallback: without WebGL2 an editor shows its locations
as static markers and a notice that this browser cannot edit on the map.

ha-map exposes editableLocations and fires
editable-location-moved/resized/clicked and editing-available-changed.
Locations are reconciled by id: position and radius changes move the
existing handles, while a changed icon, name, color, or editability
rebuilds the marker, so edits made in the form fields show up on the
map on either engine. ha-locations-editor becomes a thin layer over
that with its public contract unchanged, so its consumers need no
changes; it reads localize from the internationalization context instead
of taking hass.

The zone panel no longer zooms the map when a selection comes from the
map itself. Clicking or dragging a marker selects its list item, and
mwc-list reports that programmatic selection with the same "property"
request-selected event a click ends with. The two are told apart by
timing: a selection from the map has already set the active entry when
its event arrives, while a click's event arrives before the handler
sets it. Skipping the programmatic event also keeps the item selected,
which the shared request-selected helper would otherwise reset.

The layers property and the engine selector are removed along with the
leaflet-draw dependency and its patch: Leaflet is now purely the viewing
fallback, selected by WebGL2 support alone. The Leaflet engine keeps a
leafletMap field for the ha-map fit tests, which run on it in jsdom.

* Keep the retained circle data current while resizing

The engine keeps its source specifications to rebuild them after a style
swap; the editable circle's redraw updates that copy along with the map.

* Address code review on map editing

Editable markers, the circle center on both engines, and the static
fallback center activate on Enter and Space, as their button role
promises. Locations without a name get a localized one, since onboarding
and the location selector pass none. The resize handle's advertised
maximum follows the radius instead of being exceeded by it, and the
handle stays near the circle at high latitudes.

Clicking the active zone row zoomed to it again upstream but was
swallowed by the check that told a map-driven selection from a click; a
one-shot flag on selections made in code replaces that inference. The
engine rebuilds its sources from its own record on a style swap, so a
radius changed while the style was unloaded is not lost.

* Test the map editing path

The MapLibre engine's editable circle against the fake map: dragging the
center moves the circle and the handle and reports the drop, dragging the
handle resizes and snaps it back, arrow keys resize in steps committed on
release, the advertised maximum follows a larger radius, one update
echoing pre-drag values is ignored, the center activates by click, Enter
and Space but not after a drag, and removal clears markers, layers and
listeners.

ha-map's reconciliation of editable locations through a fake engine with
editing support: circles and markers are drawn, moved in place, rebuilt
when their appearance changes and removed when dropped, move, resize and
activation events carry the location id, and an engine without editing
support shows the locations statically.

* Leave zone row selection to the user

Clicking or dragging a zone on the map, and saving one in the dialog,
selected its row in code. That selection fires the same request-selected
event a click ends with, so the page had to tell the two apart, and the
row could not be shown selected and stay clickable at the same time: the
highlight never actually appeared. The list now only follows the user's
own clicks, which removes that bookkeeping along with the zoom that a
radius drag used to trigger.

* Hand marker elements back clean, and record sources before the style loads

MapLibre leaves its positioning class and transform on a marker element
after removal. Hosts like ha-locations-editor cache their elements and
hand them to whatever engine draws next: after a fatal WebGL failure that
is the Leaflet fallback, which shows the locations statically. A removed
element, and every element still on the map when the engine is destroyed,
is reset so it arrives as a plain element. The editable circle's center
gets the same treatment.

Custom sources and layers are now recorded when added and only inserted
into the map once the style has loaded. A circle moved while a swapped
style was still loading therefore reaches the record, and a swap in that
window carries it over; the deferred insert skips what the swap already
placed.

* Guard a keyboard resize against host updates like a drag

Arrow-key resizing changed the radius without arming the pre-edit guard
that pointer drags use, so a host re-render with the old radius while a
key was held, or its echo right after the commit, snapped the circle
back. A key resize now counts as a drag from the first key press until
the commit.

* Let the engine own the drag cursor, and tidy the fallback notice

The move cursor came from stylesheets keyed on whether a location may be
edited, so it showed on circles that cannot move and on the static
Leaflet fallback. The MapLibre engine now sets it on the elements it
actually made draggable and clears it when handing them back.

The fallback notice said the browser cannot edit locations, while
clicking the map to place one still works there; it now names what is
missing, dragging markers and resizing zones. The editor's
internationalization context is reactive, like its neighbours.

* Show the fallback notice only when a location is editable

The Leaflet fallback showed the notice for every editor, including ones
whose locations are all read-only, where nothing is missing.

* Drop the named icon's move cursor, and describe the fallback as a map state

The Leaflet fallback draws named location icons statically, but the
stylesheet still gave the ones marked editable a move cursor. The engine
sets that cursor on the elements it actually drags, so the rule goes.

The fallback notice blamed the browser, while MapLibre can also be
unavailable after a failed start or a lost WebGL context; it now
describes what the map offers. The resize handle's east point only guards
the pole itself, so its distance agrees with distanceMeters wherever a
zone can be.

* Announce the fallback notice, and let test frames redraw

The notice appears after the engine has been chosen, so helper text
would not reach a screen reader; it is an alert now. The engine test's
frame stub returned an id that landed in the engine's pending frame after
the callback had cleared it, so every redraw after the first was skipped.

* Show the fallback notice over the map, and keep handle clicks off the map

The notice followed a map that fills the editor's fixed height, so it
landed outside the box: clipped in onboarding, spilling into the form in
the location selector. It now sits over the top of the map, clear of the
zoom control.

The resize handle was the one marker whose click reached MapLibre's map
click, which a pin-on-click host takes as a request to move the location
there; the handle stops it like the other markers do.

* Share one circle geometry, and keep arrow keys on the handle

Drawing, fitting, and handle placement each converted meters to degrees
on their own, with different pole guards, so above 89.4 degrees the
resize handle left the drawn circle. They now share one conversion that
also agrees with distanceMeters; only the pole itself is guarded.

Arrow keys on the resize handle also reached MapLibre's keyboard handler
and panned the map while resizing; the handle keeps them.

* Drop the zone page's active entry

It only re-selected the row the user had just clicked, after the shared
request-selected helper had reset it, which fired the selection event a
second time and zoomed to the zone twice. The row highlight comes from
the list itself and nothing else read the value, so the list no longer
mirrors a selection at all.

* Make marker activation opt-in, and relabel handles on language change

Every editable marker was a focusable button whose activation fired an
event, whether or not the host did anything with it: the zone page and
the location selector do not. Activation is now opt-in per location; the
onboarding search results opt in, and a marker that does not act on it is
draggable without button semantics. The engine contract separates taking
pointer input from being a keyboard-focusable button for that.

Marker titles and handle labels are localized when drawn, so a language
change, or localization arriving after the first draw, redraws them.

* Own the accessibility attributes the engine sets, and use spherical circle geometry

setMarkerAccessibility only filled in what was missing and nothing removed
it, so a cached element rebuilt with a new title or a different role kept
the old attributes. The helper now records what it set, replaces exactly
that on a rebuild, and clears it when the element leaves the map, while a
caller's own attributes stay untouched.

The flat meters-to-degrees conversion broke down for large circles near
the poles, wrapping longitude and producing latitudes beyond 90. Handle
placement and the polygon now use the great-circle destination, and the
fitted bounds a spherical box that spans all longitudes once the circle
reaches a pole, so all three agree with distanceMeters everywhere.
2026-09-10 11:31:06 +02:00
Petar Petrov 569bcc01da Fix frozen solar-to-grid dot and phantom solar dot in energy distribution card (#54085) 2026-09-10 10:20:38 +01:00
Petar PetrovandCursor Agent 8ea28508c3 Move history timeline names under the bars (#54086)
Co-authored-by: Cursor Agent <[email protected]>
2026-09-10 09:58:48 +01:00
Dominik c3e341bdb3 Unify trend-graph and temperature-forecast card-features (#54037)
Unify trend-graph and temperature-forecast
2026-09-10 09:01:57 +03:00
Paulus SchoutsenandClaude 58de8df46a Prevent closing the backup restore dialog by clicking outside (#54095)
Prevent scrim close on backup restore dialog

Clicking outside the restore dialog dismissed it unless the encryption
key field was dirty. Restoring a backup is destructive, so guard the
dialog at every step.


Claude-Session: https://claude.ai/code/session_017eZQ6BTz6MervuG3Zb8RLp

Co-authored-by: Claude <[email protected]>
2026-09-10 08:15:47 +03:00
karwosts 3447e1d862 An empty placeholder for entity-filter-badge in edit mode (#54096) 2026-09-10 08:15:02 +03:00
renovate[bot] 105a2a2423 Update Node.js to v24.21.0 (#54097)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-10 07:00:24 +02:00
Larai 27efa82a89 Fix accessible names for analytics consent switches (#54083) 2026-09-09 18:23:13 +02:00
Josef Zweck 19cf7f2613 Allow shared translations for subentry abort (#53964)
* Allow shared translations for subentry abort

* load translation
2026-09-09 18:18:41 +02:00
Josef Zweck fcd25e41a0 Make sure we load shared translations in config flow (#54084)
* Make sure we load shared translations in config flow

* load translation for specified domain
2026-09-09 18:18:00 +02:00
Aidan TimsonandPetar Petrov f942a5afe5 Add visibility condition reordering (#53252)
Co-authored-by: Petar Petrov <[email protected]>
2026-09-09 14:49:01 +02:00
Aidan TimsonandCopilot Autofix powered by AI 89b745b851 Add contextual descriptions to rows in card condition editor (#52817)
* Add row targets UI to entity state and numeric state in card condition editor

* Use automation descriptions instead of target ui

* Type check

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Format condition editor

* Fix contextual condition descriptions

* Resolve state references in condition descriptions

* Share automation condition headers with visibility conditions

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-09 15:29:42 +03:00
Maarten LakerveldandCopilot Autofix powered by AI ac582cbfbb Run ha-map on a runtime-selected engine: MapLibre GL native or Leaflet (#54022)
* Run ha-map on a runtime-selected engine: MapLibre GL native or Leaflet

ha-map no longer drives Leaflet directly. All primitive operations -
camera, HTML element markers, meter-radius circles, history paths,
clustering with a pluggable icon builder, scale ruler, dark mode - go
through a MapEngine interface, and the engine is selected at runtime:

- MapLibreMapEngine renders the vector base map natively where WebGL2 is
  available, without Leaflet in the loop: continuous fractional zoom,
  DOM markers synced to the basemap every frame, GeoJSON zone and
  accuracy circles below the labels, GeoJSON history trails with hover
  popups, and a pixel-distance cluster grid recomputed when the camera
  settles. Dark mode swaps the style while carrying the custom layers
  over, and rotation and pitch stay disabled for north-up dashboards.
- LeafletMapEngine wraps the existing behavior unchanged (vector tiles
  through the maplibre adapter with the raster fallback, markercluster)
  for browsers without WebGL2 - the legacy floor includes iOS 12-14 and
  kiosk browsers without hardware acceleration - and for
  ha-locations-editor, which manages raw Leaflet layers with
  leaflet-draw and declares engine=leaflet.

A permanently lost WebGL context rebuilds the map on the Leaflet engine
instead of leaving a dead canvas. Zoom levels keep Leaflet semantics
across engines. MapLibre's stylesheet is shipped to /static/map for the
native engine's controls and popups.

* Enhance keyboard accessibility for icon click

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Fix dark mode style application logic

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Address code review on the map engine

A fatal engine event during setup was dropped because the in-flight
setup owned the loading flag; the fallback request is now recorded and
setup switches to Leaflet once init settles. Entity markers accept Enter
and Space, as both engines make them focusable buttons. History points
show their popup on tap as well as hover, since touch has no hover.

Tests cover the engine choice and fallback paths, including a fatal
event mid-setup, and the MapLibre engine itself against a fake map:
style swaps, queued layer work, custom layer carry-over, failed style
requests, token refusal recovery, context-loss grace, and clustering.

* Address second code review round on the map engine

A cluster whose members share a spot, or that sits at maximum zoom,
could never be opened: fitting its bounds changed nothing and the next
regroup recreated it. Activating such a cluster now opens it: all its
members are shown in a bubble with a tail pointing at their spot, each
reachable on its own, until the map moves again.

An engine whose init failed, or was abandoned by a disconnect or a fatal
event during setup, was never destroyed and could keep a WebGL context;
setup now destroys any engine that did not become the active one.

The Leaflet engine sizes the cluster element like MapLibre does, so
cluster bubbles no longer shrink to their text.

* Keep the engine's own record of its map sources and layers

Carrying zone circles and history paths over a style swap relied on
MapLibre serializing the outgoing style into transformStyle's previous
argument. The engine now keeps the source and layer specifications it
added and rebuilds them into the new style itself, so the carry-over no
longer depends on what MapLibre hands over, and a missing previous style
cannot drop them.

* Address review: setup teardown, marker input, cluster focus

An engine still setting up could not be torn down: ha-map only held it
once init resolved, so removing the element mid-load kept its WebGL
context alive and left the loading guard set, ignoring a reconnect. The
engine being set up is now tracked and destroyed on disconnect, a stale
setup notices it was superseded, and the MapLibre engine settles a
pending init when destroyed.

Non-interactive markers let pointer input through, as they do on
Leaflet. Opening a cluster from the keyboard moves focus to its first
member, and a member that has focus when the bubble closes hands it to
the icon that replaces it.

* Tear down an engine that fails while still setting up

A fatal event during setup only flagged the fallback and waited for
init to settle, which relied on MapLibre still firing style.load. The
engine being set up is destroyed instead, which settles its init, so the
setup hands over to Leaflet without depending on the failed engine.

* Make history point popups readable on MapLibre

MapLibre's stylesheet is linked into the map's shadow root and wins over
the component styles on equal specificity, property by property: its
white popup background applied while our white text color did too,
leaving the timestamp invisible. The popup rules now carry !important,
as the Leaflet tooltip rules already do for the same reason.

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-09 15:26:28 +03:00
Petar Petrov dab85a9239 Add show_values toggle to all Sankey cards (#54075) 2026-09-09 12:09:44 +01:00
Wendelin 29e0e9db87 Add paste to add automation element by target (#54052) 2026-09-09 11:08:37 +01:00
Wendelin 3ce90a7a68 Fix update last backup description (#54066) 2026-09-09 10:59:17 +02:00
dependabot[bot] d6260482e0 Bump svgo from 4.0.2 to 4.1.0 (#54078)
Signed-off-by: dependabot[bot] <[email protected]>
2026-09-09 08:49:27 +01:00
ca24b16702 Add show_values toggle to energy and power Sankey cards (#53925)
* Add show_values toggle to energy and power Sankey cards

Adds a boolean config option that renders each node's value directly
on its diagram label (e.g. "Solar\n3.4 kWh"), stripping HTML from the
valueFormatter output for ECharts plain-text labels.

Fix show_values label alignment on Sankey nodes

Collapse internal whitespace in valueFormatter output after stripping
HTML tags, so "7.7\n      kWh" becomes "7.7 kWh" on a single line.

* Address review feedback on show_values

Removes the HTML-tag-stripping regex from the label formatter (an
incomplete-sanitization pattern flagged by CodeQL); the value
formatter never returns HTML and the label renders as plain ECharts
canvas text, so no stripping is needed. Splits the vertical
label-sizing measurement on all whitespace instead of literal spaces,
so the newline-separated value line is measured correctly. Scopes
show_values to the energy and power Sankey card configs instead of
the shared Sankey base, and hides the option in the card editor for
water and water-flow cards, since those cards don't support it.

* Apply batched suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Format Sankey card templates with Prettier

Restore Prettier wrapping around the show_values template bindings so CI lint:prettier passes.

* Fix vertical Sankey value labels wrapping on thin nodes

Unicode isolates around show_values text were treated as wrap characters, and font sizing ignored ECharts minMargin, so short names like TV with small values split mid-word. Size labels to the inner wrap width and keep LTR with a mark instead of isolates.

* Reserve extra bottom space for vertical Sankey values

When show_values is on, node labels can be three lines (name, number, unit). Increase the vertical series bottom inset from the single-line 25px so the lowest row is not clipped.

* Keep locale grouping spaces in Sankey value labels

Trim formatter output without collapsing internal whitespace, so narrow no-break thousands separators are not turned into wrap points. Measure the longest word on regular spaces and newlines only.

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Cursor Agent <[email protected]>
2026-09-09 09:32:27 +03:00
Wendelin 380bcb8315 Fix automation trigger/condition platform default behavior (#54062)
* Fix platform behavior default

* Fix race condition by updating target entity count and setting default behavior
2026-09-09 08:28:23 +03:00
karwosts 9902924ffa Use heading elements for heading-card (#54068) 2026-09-09 08:27:45 +03:00
Paulus SchoutsenandClaude Opus 5 cb0c03ab8b Add a Modbus panel (#54036)
* Add a Modbus panel

The Modbus integration exposes the connections it keeps open over
`modbus/connections/list`. This surfaces them under Connectivity, mirroring the
Serial panel: one entry per physical device, grouped by whether the link is up,
naming the config entries holding units on it.

Because one device is shared by every integration talking to it, the panel is
where a shared RS-485 bus or gateway becomes visible — the two integrations on
`/dev/ttyUSB1` cannot be seen from either integration's own page.

The Serial panel gains the other half of that: a port carrying a Modbus
connection now points at the Modbus panel. The two are matched on the device
path, which Modbus stores as configured, so both the scanned and the resolved
path are compared. Reaching Modbus is not required for the Serial panel to
load.

Demo fixtures come with it, so the connections and the shared bus can be seen
without a Home Assistant instance. The RS-485 port the Serial demo already
lists gains the two integrations that hold units on it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FjmjZsxhdj9ekGmhFHXg3p

* Modbus: show link state as an indicator, not a verdict

A closed link is not a fault. The library opens one when an integration next
polls, and a device is free to drop an idle one in between, so grouping the
connections into Connected and Disconnected cards behind a warning icon
reported trouble where there was none.

One list now, ordered by address alone, with a per-row indicator. A link
opening or closing no longer moves a row between cards, and the summary is a
count rather than a health verdict.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FjmjZsxhdj9ekGmhFHXg3p

* Modbus: a serial port is open, not connected

Opening a serial port proves a device node exists; nothing on the wire has to
answer. Only a network connection performs a handshake, so "Connected" was
promising more than a serial row can know. Those rows read Open and Closed.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FjmjZsxhdj9ekGmhFHXg3p

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-09 07:08:22 +02:00
Aidan Timson 64cda9e0e7 Clarify companion skill selection before frontend review (#54067) 2026-09-08 20:21:56 +02:00
renovate[bot] 94fdea6f00 Update dependency vite to v8.2.2 (#54058)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-08 15:26:50 +02:00
Petar PetrovandAidan Timson 37de8c4b15 Delegate dashboard visibility conditions to core (#52904)
* Add dashboard visibility condition classifier, translator and splitter

Pure-logic foundation for delegating dashboard visibility conditions to
core (#52836).

- Add a VisibilityCondition type spanning the client-only lovelace
  conditions (screen, user, view_columns, location, time) and core
  automation conditions, alongside the existing lovelace Condition.
- translate.ts: classify conditions as client- or server-evaluated and
  translate server ones to core format (entity -> entity_id, state_not
  -> not-wrap, numeric bound coercion), preserving lovelace's
  not = not(AND) semantics.
- split.ts: split a tree into maximal server subtrees (one subscription
  each, sibling-grouped) plus a three-valued client combiner.

* Add reactive condition evaluator controller

Phase B of delegating dashboard visibility conditions to core (#52836).

- ConditionEvaluatorController opens one subscribe_condition per server
  subtree, evaluates client leaves locally, observes screen/time
  boundaries, and exposes a tri-state visible/hidden/unknown result plus
  error. It recomputes on push/listener/hass/context change, debounces
  re-subscription when the tree changes, and tears down on disconnect.
- Add observeConditionChanges to listeners.ts (notify-only, decoupled
  from checkConditionsMet) and widen extract.ts to the VisibilityCondition
  tree, factoring time-boundary scheduling into a shared helper.

* Harden condition translation for incomplete and odd numeric inputs

Follow-up to the adversarial review of the translator (#52836):

- Incomplete/garbage state conditions (no entity, no value, or an empty
  object) now translate to an always-false core condition instead of a
  schema-invalid `state`, matching checkConditionsMet and avoiding a
  broken grouped subscription.
- numeric_state bounds: coerce only finite numeric strings (incl. "" -> 0)
  to numbers, pass genuine entity-id references through, and drop junk or
  non-finite strings (matching lovelace's "NaN -> ignored" and never
  emitting a non-JSON-serializable Infinity).

* Fix condition evaluator controller lifecycle edge cases

Follow-up to the adversarial review of the controller (#52836):

- Key re-subscription on a structural signature of the condition tree
  rather than array reference identity, so a host re-deriving the array
  each render neither starves the debounce nor churns subscriptions.
- Reset the published result to `unknown` on host disconnect so a
  detached/reconnecting host never renders a stale, no-longer-live result.
- Read hass lazily in the time-boundary listeners so timezone changes are
  picked up on the next boundary instead of being pinned at subscribe time.

* Evaluate dashboard visibility through the reactive condition evaluator

Rework ConditionalListenerMixin to derive visibility from
ConditionEvaluatorController instead of evaluating checkConditionsMet
synchronously. Stateful conditions (state, numeric_state, template, sun,
zone, device, integration) are delegated to core via subscribe_condition;
client-only conditions (screen, user, view_columns, location, time) stay
local. The mixin re-feeds the evaluator on connect and on hass/config/
column changes, and drives _updateVisibility from its tri-state verdict.

Consumers (hui-card, hui-badge, hui-section, hui-heading-badge,
hui-view-sidebar, hui-conditional-base) now read the mixin's
_conditionsVisible(), which prefers the server-aware verdict and falls back
to an optimistic synchronous seed while a server subtree is pending — exact
for legacy lovelace conditions (no flash for existing dashboards) and hidden
for core-only conditions until the server reports.

- fold the host entity_id context into the evaluator path via
  addEntityToCondition, and read core-format entity_id in
  checkStateCondition / checkStateNumericCondition so seed and server agree
- addEntityToCondition no longer grafts a context entity onto an
  already-core condition that carries its own entity_id
- the conditional card/row now evaluates legacy {entity, state} conditions
- cache the entity-folded array so the evaluator's signature memo holds
  across hass updates, and drop the cached verdict when the tree changes by
  value so the seed is used for the new tree

* Add server condition types to the dashboard visibility editor

Let the visibility editor add and edit the core-format server condition
types (template, sun, zone, device) by embedding the automation condition
editors, which already speak core format. ha-card-condition-editor
dispatches these types to ha-automation-condition-editor; the existing
lovelace editors and the and/or/not containers are unchanged, and because
the logical editors nest ha-card-condition-editor, mixed trees dispatch
each child correctly.

- extend the add-condition menu with the new types (icons + labels)
- suppress the client-side live-test for server-class conditions (and any
  logical tree containing one); checkConditionsMet can't evaluate them, so
  the indicator stays neutral instead of showing a misleading failure

Server-backed live-test and read-both/write-new conversion of lovelace
state/numeric_state conditions are follow-ups.

* Evaluate the visibility condition editor live-test through the reactive evaluator

Drive the per-condition live-test indicator with the same
ConditionEvaluatorController the dashboard uses at runtime, so server-class
conditions (template/sun/zone/device and core-format state/numeric_state) get
a real subscribe_condition-backed verdict instead of a neutral indicator.
Client-only conditions stay evaluated locally and mixed logical trees combine
both via three-valued logic.

- Fold the card entity into the observed condition exactly as the runtime
  mixin does, and memoize the folded array so the evaluator's signature memo
  keeps hitting on hass-only updates.
- Map the evaluator verdict to the indicator: visible -> pass, hidden -> fail,
  pending -> unknown, server error -> invalid (raw error shown as the tooltip
  detail, localized label kept as the aria-label).
- Keep a client-side validity check for purely client trees so a malformed
  client-only config still surfaces as invalid.
- Recurse the no-entity (filter-mode) suppression so nested entity-less
  conditions are handled, and report an as-yet-unknown manual test as no
  result rather than a failure.
- Drop the now-unused invalid-config alert and its orphaned translation keys.

* Evaluate the visibility status banner server-side

Drive the card-level visibility summary banner with the same
ConditionEvaluatorController used by the per-condition live-test, so a set
containing server-class conditions reports its real visible/hidden verdict
instead of being flagged as an invalid configuration.

- Add a distinct "unknown" banner state for while a server result is still
  pending, separate from "invalid" (a genuine configuration error).
- Keep a client-side validity check for purely client trees, and fold the
  card entity into the observed conditions, matching the per-condition editor.
- Extract isPureClientCondition (every leaf client-side, as opposed to
  isClientCondition's any-leaf) so both consumers share one classifier.

* Edit dashboard state conditions via the core condition editors

Route `state` / `numeric_state` visibility conditions to the core automation
condition editors (outside entity-filter mode), so they share one editing
surface with the server-class types and are authored in core format.

- Read both: existing lovelace-format conditions (`entity`, `state_not`, …)
  are translated to core for display; a `state_not` shows as `not(state)`.
- Write new with touch-to-convert: opening a condition leaves it untouched;
  editing or adding one persists it in core format (`entity_id`, `state` list).
- Entity-filter mode keeps the lovelace no-entity syntax and editors.
- Register the core `state` / `numeric_state` editors (dynamicElement only
  renders a tag, it does not define the element) and widen the editor chain's
  condition arrays to the mixed visibility union.

* Remove the superseded client-only condition listeners

The dashboard now evaluates visibility through the reactive condition
evaluator (which uses `observeConditionChanges`), so the old synchronous
client-only listener path has no remaining callers.

- Delete `ConditionListenersController` and the `setupConditionListeners` /
  `setupMediaQueryListeners` / `setupTimeListeners` helpers.
- Keep `observeConditionChanges` and the shared time-boundary scheduler, and
  re-point their tests onto it so the scheduling edge cases stay covered.

* Pin the condition editor live-test for hidden and invalid configs

The per-row live-test set `invalid` (or hidden) directly but left its
evaluator callback unguarded, so the evaluator's torn-down `unknown`
result — fired ~500ms after observing `undefined` — clobbered the pinned
state until the next hass tick re-pinned it, causing a transient flicker.

Add the same `_override` guard the sibling visibility-status banner
already uses: the hidden / client-invalid branches set the result
directly and pin it, and the evaluator callback ignores results while
pinned.

* Remove the orphaned conditional-listener no-op methods

`addConditionalListener` / `clearConditionalListeners` became no-op
shims once the evaluator took over subscriptions and teardown; their only
callers were the listener-wiring removed in the migration. Drop both
methods, the mixin's now-redundant `disconnectedCallback` override, and
the stale `clearConditionalListeners()` call in hui-conditional-base.

* Accept server-evaluated conditions in validateConditionalConfig

The conditional card/row/element gate their config on
validateConditionalConfig, which only knew the client-side condition
types and rejected the server-evaluated ones (template, sun, zone,
device, and integration-provided conditions). Now that those are
authorable and delegated to core, accept them — core validates them —
so configuring one no longer throws "Invalid configuration".

* Evaluate conditional picture element visibility server-side

The picture-elements `conditional` element was the one visibility
consumer still evaluating fully client-side, so its stateful conditions
were not delegated to core (and server-class types it could not evaluate
fell through to a permanently-hidden result). Convert it to a
ReactiveElement driven by ConditionalListenerMixin, exactly like its
sibling hui-conditional-base, so the evaluator delegates stateful
conditions through subscribe_condition and evaluates the client-only
ones locally.

* Keep conditional cards mounted while hidden for server conditions

A conditional card gated on a server-evaluated condition (template, sun,
zone, device) never reappeared: hui-card removes a hidden child card from
the DOM, tearing down the evaluator, and the synchronous seed can revive a
client condition but not a server one, so the subscription was never
(re)opened and the server result that would show the card never arrived.

Set connectedWhileHidden so the conditional card/row stay mounted while
hidden and keep their subscriptions alive, like the other cards that must
keep working while hidden. The inner element is still unmounted when
hidden, so there is no extra render cost.

* Load config translations for the reused condition editors

The dashboard visibility editor reuses the automation condition editors
(state, numeric_state, template, sun, zone, device), which label their
form fields from the `config` translation fragment. The lovelace panel
never loads that fragment, so those labels rendered blank — e.g. the
numeric_state limit-type selectors and the above/below fields.

Load the `config` fragment when the conditions editor first renders, so
the embedded editors resolve their labels.

* Fold the card entity into entity-less conditions on read

A card with a host entity can carry entity-less state / numeric_state
visibility conditions that implicitly target that entity (folded in at
runtime). The editor translated them with an empty entity_id, so the
reused automation editor showed an empty, invalid entity field.

Fold the current-mode context entity into the displayed condition, and
recompute it when the entity context arrives (it can follow the
condition). Opening still does not rewrite the stored config; only
editing converts it to explicit core format.

* Demote the unused state/numeric_state condition editors to base classes

With the automation condition editors handling state / numeric_state in
the dashboard editor, the lovelace `ha-card-condition-state` and
`ha-card-condition-numeric_state` elements are no longer rendered. Their
only remaining role is as the base class for the entity-filter
`-no_entity` variants, so drop the now-dead custom-element registrations
(and the redundant side-effect imports) while keeping the shared logic.

* Format condition editors

* Fix condition editor indentation

* Invalidate the condition evaluator result as soon as the tree changes

When the observed tree changed by value, the controller kept the old
split and subscriptions alive until the debounced re-subscribe fired, so
it kept publishing (and the editor's Test action reported) the previous
tree's verdict, and a host that had already reset to unknown never got a
notification when the new tree settled on the same result.

Tear the old tree down when the signature changes and publish unknown
until the new subscription reports. Trees with nothing to subscribe to
re-evaluate immediately rather than waiting out the debounce.

Track a pending re-subscribe with its own flag: undefined is a valid
signature (observation cleared), so using it as the "nothing pending"
marker kept rescheduling the timer on every hass update and could leave
the previous subscription open indefinitely.

* Translate bound-less numeric_state conditions to a schema-valid core condition

Dropping a junk or non-finite bound could leave a numeric_state condition
with neither above nor below, which core's schema rejects; because sibling
server conditions are grouped into one subscription, that single invalid
leaf failed the whole group and hid the content. Lovelace merely ignored
such bounds and only required the value to be numeric, so express that
residual check as a template condition instead. An entity-less
numeric_state resolves to always-false, matching checkConditionsMet.

* Validate every visibility condition client-side and handle unsupported automation editor configs

validateConditionalConfig already accepts the server-evaluated types, so
gating it behind "every condition is client-only" only served to skip
validation as soon as a server condition was present; a malformed screen
condition next to a template condition was reported as hidden rather than
invalid. Run it for the whole set.

The embedded automation condition editors fire ui-mode-not-available when
an existing core config fails their UI struct. Fall back to YAML with the
struct warnings, as the automation condition row does, instead of
rendering a blank editor while still claiming UI support.

* Type dashboard visibility contracts as VisibilityCondition

Card, badge, section, view sidebar and heading badge visibility, plus the
conditional card, row and element conditions, still declared the
lovelace-only Condition type, so the newly supported template, sun, zone,
device and integration conditions were invalid at the config boundary and
needed casts throughout. Declare them as VisibilityCondition, widen
validateConditionalConfig accordingly and drop the casts that made
redundant. Entity-filter conditions stay lovelace-only.

* Subscribe when hass arrives after the conditions were observed

The subscribed signature was recorded before checking that hass was
available. A host that connected with its config set but received hass
later therefore never subscribed: the later observe saw the same
signature, found no split and stayed unknown for good. Only record the
signature once a subscription is actually opened.

* Seed pending visibility with a three-valued local evaluation

While a server result was pending, the mixin ran the whole tree through
the legacy client evaluator. Core-only leaves default to false there, so
not: [template] was inverted to visible until core replied, and core
state / numeric_state options such as for, match and value_template were
ignored, both contradicting the no-flash guarantee.

Evaluate locally only the leaves the legacy evaluator reproduces exactly
(client-only types, lovelace state / numeric_state, and core ones without
those options), keep every other leaf unknown through and / or / not, and
hide while the outcome still depends on an unknown leaf.

* Hide server-only condition types in entity-filter mode

The map and entity-filter cards still evaluate their conditions locally
with checkConditionsMet, where template / sun / zone / device fall through
to a failing state check and filter out every entity. Don't offer them in
the add menu for that mode.

* Leave conditions carrying enabled to the server in the local seed

Core treats a disabled condition as neutral (and enabled may be a
template), while the legacy evaluator ignores enabled altogether. A
pending not: [disabled failing state, ...] was therefore seeded visible
although core reports hidden. Treat any node carrying enabled as unknown.

* Reject filter-incompatible pasted conditions in entity-filter mode

The condition clipboard is shared across editors in the session, so a
template / sun / zone / device condition, or a core-format leaf pinned to
its own entity_id, could be pasted into a map or entity-filter editor,
where the local evaluator would filter out every entity or evaluate the
wrong one. Hide the paste entry and ignore the action for such clipboard
contents while in filter mode.

* Re-feed the section visibility evaluator after a strategy config resolves

_config is not reactive, and for a strategy section it is assigned after
the Lit update that last fed the evaluator, so _conditionsVisible kept
reading the verdict for the raw or previous config until the next hass
update. Re-run setupConditionalListeners right after assigning it.

* Hide content whenever a server condition subtree errors

An errored subtree was recorded as false and fed through the combinators,
so a client-side not inverted it and an invalid server condition could
show content; the runtime mixin only looks at the result, not the error.
Force the result to hidden while any subtree is in error.

* Honor enabled: false on visibility conditions

Core skips a disabled condition inside a compound: it neither passes nor
fails. Rebuilding logical conditions during translation dropped enabled
(and the other row metadata), so a disabled server-side group was
evaluated, and the mixed-tree split and the local seed ignored it as well.

Preserve the row metadata on translated logical conditions, skip disabled
nodes when splitting and when seeding, and leave a template-valued
enabled on a seeded node unknown since only core can render it.

* Type the conditional card conditions as VisibilityCondition

ConditionalCardConfig, the contract HuiConditionalBase actually consumes,
still declared the lovelace-only union, unlike the row and element
contracts.

* Keep a client-side node with a template-valued enabled unknown

Only core can render enabled: "{{ ... }}", and core never sees a mixed or
client-only node, so the split silently treated such a node as enabled
and let its children decide visibility. Keep it unknown instead, erring
toward hiding and matching the optimistic seed.

* Whitelist the condition types usable as entity filters

The filter-compatibility check only excluded the four built-in server
types, so an integration-provided condition copied from a visibility
editor could still be pasted into an entity-filter editor, where the
local evaluator cannot evaluate it and filters out every entity. Check
against the types checkConditionsMet supports instead.

* Fold the host entity into legacy entity-less conditions as well

A legacy condition such as { state: "on" } has no condition key, so
addEntityToCondition never stamped the card entity on it. That used to be
harmless because checkConditionsMet fell back to the evaluation context,
but the server translation has no context and turned the condition into
always-false once core reported. Treat the legacy shape as the state
condition it is, and make the helper generic over the visibility union so
callers no longer need casts.

* Keep the lovelace outcome for infinite numeric bounds

Number("1e400") is Infinity, which lovelace does not ignore: above +inf
or below -inf can never pass, while above -inf or below +inf always do.
Dropping such a bound could flip an untouched condition from hidden to
visible. Resolve the unsatisfiable cases to always-false and drop only the
vacuous ones. Infinity is not JSON-serializable, so neither is ever sent.

* Only leave a template-valued enabled unknown in the local seed

The check also matched enabled: true, so an explicitly enabled condition
was seeded unknown and the card hidden until core responded, exactly the
flash the seed is meant to avoid.

* Show no test chip while the condition evaluator reports an error

An invalid server condition evaluates to hidden plus an error; reading
only the result turned Test into a transient "not met" chip that
contradicted the invalid live indicator.

* Seed only core conditions the client compares identically

The optimistic seed still admitted core-format shapes the legacy evaluator
handles differently: an attribute comparison (core compares the raw value,
the client stringifies it) and an entity-valued numeric bound (core errors
when the entity is missing, the client ignores the bound). Leave those
unknown until core reports.

* Accept a single condition as the children of a logical condition

Core's LogicalCondition allows conditions to be one condition or a list,
but every traversal here assumed a list and crashed on the single shape.
Widen the type accordingly and route all traversals through one helper.

* Keep lovelace leaves with legacy-only semantics client-side

Core compares raw attribute values, only dereferences input_* comparison
values and errors on a missing bound entity, where lovelace stringifies
the attribute, resolves any existing entity and ignores the bound.
Delegating such existing conditions changed their visibility silently.

Classify a lovelace-format state / numeric_state leaf that relies on any
of those as client-side so it keeps its exact legacy evaluation; once the
user edits it, it is saved in core format and evaluated by core.

* Drop the pinned editor indicators when leaving an override branch

The empty and client-invalid branches pin the indicator and clear the
evaluator, which is then already unknown; when the condition becomes
valid the pending observation is unknown too, so no notification arrives
and the stale pinned state stayed visible until core first responded.

* Reject core's single-child logical shorthand as an entity filter

Filter consumers and the filter-mode editor expect the lovelace list
shape for logical children, so a pasted core condition using the
single-child shorthand caused a runtime error there. Require a list in
the filter-compatibility check and traverse defensively when looking for
no-entity conditions.

* Seed only core leaves whose entity is present and, for numeric_state, bounded

Core errors on a missing entity and rejects a bound-less numeric_state,
while the client evaluates a missing entity as unknown and passes any
numeric value, so both shapes could flash visible before the subscription
error arrived. Leave them unknown until core reports.

* Re-subscribe when the hass connection object is replaced

Subscriptions are bound to the connection they were opened on. An
unchanged tree observed with a hass carrying a different connection kept
the stale subscriptions; re-open them in that case while still not
churning on ordinary hass updates.

* Keep non-finite bounds distinguishable in the condition signature

JSON.stringify serializes Infinity, -Infinity and NaN alike as null, so
flipping a YAML .inf bound produced the same signature and the old
subscription stayed active.

* Seed lovelace leaves only while their target entity exists

Core reports an error for a condition on a missing entity, which hides the
tree, while the legacy evaluator compares against the literal unknown.
Seeding such a leaf optimistically could therefore flash the content
before the error arrived; leave it unknown instead.

* Do not seed a core state condition that compares against another entity

checkConditionsMet dereferences any existing entity used as a comparison
value, while core only dereferences input_* entities, so such a core leaf
could flash visible before the subscription reported false. Apply the
same entity-reference guard the legacy classification uses.

* Preserve row metadata when rebuilding lovelace leaves

Both the evaluation translation and the editor's display conversion
rebuilt lovelace state / numeric_state leaves without enabled, alias and
note, so editing a disabled legacy condition silently re-enabled it and a
template-valued enabled was dropped before reaching core.

* Surface template rendering errors from condition subscriptions

subscribe_condition events carry template_errors next to a result when a
template inside the condition failed to render. Forward them through the
evaluator's error so the editor flags the condition, without overriding
core's result the way a hard error does.

* Treat a null numeric bound as absent

Lovelace ignores a null bound (== null), but the translator only checked
for undefined and Number(null) turned it into an unintended 0. The editor
conversion now skips null bounds as well.

* Keep the and wrapper for a single-child not and row metadata on fallbacks

Core skips a disabled child, so a bare not over one child evaluates to
true where lovelace's not (¬ of the AND of its children) gives false; the
and wrapper restores that for any arity. The always-false and numeric
value fallbacks also dropped enabled, alias and note, so a template-disabled
leaf would have participated in its parent regardless.

* Treat an empty legacy entity as absent everywhere

checkStateCondition falls back to the host entity with entity || context,
so an existing condition with entity: "" targeted the card entity. The
entity fold, the optimistic seed, the editor conversion and the
translation used nullish checks instead, which kept the empty string and
turned such a condition into an error or an always-false leaf. Use the
same truthy fallback throughout.

* Append non-finite values to the condition signature instead of substituting

A marker string standing in for Infinity could in principle collide with
an equal user string. Keep plain JSON and append the ordered non-finite
values, which is unambiguous.

* Remove a stray brace rendered under every condition editor

A leftover interpolation terminator outside the template expression
rendered a literal "}" below the condition content. Also reject pasting a
condition pinned to an explicit entity into an entity filter, where the
fold-in would keep it and judge every candidate by the copied entity.

* Tidy the optimistic seed's leaf check

Condense its doc comment, take the states map rather than the whole hass
object, and simplify the bound checks.

* Tighten comments on dashboard condition evaluation.

---------

Co-authored-by: Aidan Timson <[email protected]>
2026-09-08 12:53:50 +00:00
841729af93 Upgrade vitest to v5 (#54011)
* Update vitest monorepo to v5

* Add required Vite peer dependency for Vitest 5

* Migrate benchmarks to the Vitest 5 context API

* Stub read-only jsdom globals in Vitest tests

* Revise benchmark reporting instructions in README

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Aidan Timson <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-08 14:29:24 +03:00
Clément NotinandCopilot Autofix powered by AI e3f92a6df3 Add 'timedelta_string' to documented Jinja completions (#54056)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-08 11:13:23 +02:00
Wendelin a781228706 Fix add TCA mobile list width (#54054) 2026-09-08 09:43:44 +01:00
renovate[bot] f9e02b628f Update dependency lint-staged to v17.5.0 (#54055) 2026-09-08 09:42:01 +01:00
Clément Notin af8a80f0fe Add timedelta_string template completion (#54050) 2026-09-08 10:32:44 +02:00
chaim-shwartz c01a140751 Fix crash when hass.auth is undefined in partial-panel-resolver (#53962) 2026-09-07 18:33:04 +00:00
e50eaaa865 Add more automation row details (#54018)
* Add for and offset to trigger and condition rows

* Add actions with timeout.

* fix separator

* Fix templated automation row durations

Co-authored-by: wendevlin <[email protected]>

* review

* Enhance duration validation with finite check

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Add behavior inrow

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-07 20:31:23 +02:00
renovate[bot] cd8b975a38 Update dependency @codemirror/state to v6.7.4 (#54045)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-07 18:26:07 +00:00
Aidan TimsonandCopilot Autofix powered by AI 5dd3a4b662 Add UI/UX readiness skill and strengthen review guidance (#54032)
* Create UX readyness skill

* Refine UI/UX review skill responsibilities

* Account for existing PR review feedback

* Clarify UI/UX readiness evidence

* Simplify UI/UX readiness routes

* Update review guidelines for pull requests

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Handle optional gallery artifacts

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-07 20:21:40 +02:00
renovate[bot] e5fa96465c Update dependency eslint to v10.10.0 (#54044)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-07 20:17:55 +02:00
renovate[bot] 79467b51b1 Update dependency browserslist to v4.28.9 (#54043)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-07 20:17:49 +02:00
Maarten Lakerveld c3cc2217bf Don't zoom the zone map when opening the home zone editor (#54033) 2026-09-07 14:34:17 +01:00
Marcin BauerandClaude Opus 5 6e6e4d4c4d Point at the sources pane from history and activity empty states (#54019)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-07 14:09:13 +02:00
Aidan Timson f6cbe49d81 Resolve Supervisor browser URLs against Home Assistant (#53944)
* Resolve browser URLs against Home Assistant

* Resolve Supervisor log download URLs against Home Assistant
2026-09-07 13:12:49 +02:00
Aidan Timson 1e9592a0b8 Resolve Supervisor URLs against HA context for icons (#53942)
Resolve Supervisor URLs against Home Assistant
2026-09-07 12:07:28 +01:00
Aidan Timson b2b0491c99 Centralize Supervisor app icons (#53941)
* Centralize Supervisor app icons

* Constrain app icons in combo boxes

* Preserve quick bar app icon styles

* Style colored app icons in combo box items

* Use fixed dimensions for colored app icons
2026-09-07 12:01:55 +01:00
Petar PetrovandCursor Agent 9bffae3ee4 Exit scene live mode when leaving the editor (#53837)
* Exit scene live mode when leaving the editor

Leaving the page previously only unsubscribed, so live-activated
device states stayed behind. Restore stored states unless the tab
is hidden for panel suspend.

* Drop extra unit tests for scene live-mode disconnect.

* Restore scene live states only on editor disconnect.

Back and delete already unmount the editor, which now exits live
mode, so a second applyScene was redundant.

* Resubscribe to scene live edits after hidden-tab suspend.

Existing scenes stayed in live mode when the panel was reattached,
but the state_changed subscription was not restored.

* Keep the scene live subscription across hidden-tab suspend.

Unsubscribing and resubscribing on reattach races the closed
websocket; leaving the subscription in place lets the library
restore it after reconnect.

* Tear down scene live mode on hidden-tab route changes.

document.hidden is not enough: saving a new scene remounts a
new editor. Skip teardown only when an ancestor was detached
(panel suspend). Reuse an existing live subscription on
reattach so new scenes do not get duplicate listeners.

Co-authored-by: Petar Petrov <[email protected]>

---------

Co-authored-by: Cursor Agent <[email protected]>
2026-09-07 12:08:46 +02:00
renovate[bot] a287aacd98 Update dependency @codemirror/state to v6.7.3 (#54020) 2026-09-07 11:05:14 +01:00
renovate[bot] b29b0bd083 Update dependency @codemirror/view to v6.43.11 (#54010) 2026-09-07 09:24:46 +01:00
ae8aa3813b Add Radio frequency to the demo (#53976)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Wendelin <[email protected]>
2026-09-07 08:27:43 +01:00
Petar Petrov 770caf62f7 Prompt for unsaved changes on history back navigation (#53919) 2026-09-07 09:17:19 +02:00
iven 8fed3ac0c8 Use a readable text color for calendar events (#54009) 2026-09-07 06:54:52 +00:00
98f5bdd703 Add Tags to the demo (#53977)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Claude <[email protected]>
Co-authored-by: Simon Lamon <[email protected]>
2026-09-07 08:39:04 +02:00
karwosts 8e13ba872d Fix 'select all with issues' (#54007) 2026-09-07 08:35:46 +02:00
Dominik 37433c787f Adjust clock and notification drawer backdrop (#54012) 2026-09-07 06:22:14 +00:00
Paulus SchoutsenandClaude Opus 5 dc7ee8dc5a Serial: send consumers to their own config panel (#54000)
* Serial: send consumers to their own config panel

A port used by Zigbee or Z-Wave led to that integration's entry on the
integration page, which is a device list — not where the radio on that port is
managed. Point those consumers at the integration's own panel instead.

Which panel that is was already decided in `ha-config-entry-row`, from the
panels an integration registers at runtime falling back to
`integrationsWithPanel`. That resolution moves to `getConfigPanelPath` so both
callers stay in step, and so a port picks up any panel the integration page
would already link to.

A consumer that is not running keeps its integration-page link: its panel is
not loaded to receive it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FjmjZsxhdj9ekGmhFHXg3p

* Serial: send the Thread radio to the Thread panel

A Thread radio is held by the Open Thread Border Router app rather than by a
config entry, so it never reached the panel resolution. Map the app to the
integration behind it and look the panel up from there.

The panel is only offered when its integration is loaded, which an app being
started does not imply.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FjmjZsxhdj9ekGmhFHXg3p

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-09-06 08:27:25 +02:00
karwosts ddc99501af Handle sequence: null in script. (#53999) 2026-09-06 08:25:35 +02:00
karwosts 5ec87269dc Show errors in blueprint editor (#53996) 2026-09-06 08:24:35 +02:00
renovate[bot] 53cf986491 Update dependency @lokalise/node-api to v16.4.1 (#53997)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-06 08:24:19 +02:00
renovate[bot] 0388cb8cd0 Update dependency hls.js to v1.7.2 (#53998)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-06 08:24:16 +02:00
dependabot[bot] cfefa39b84 Bump the codeql-action group across 1 directory with 2 updates (#54002)
Bumps the codeql-action group with 2 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.8 to 4.37.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938)

Updates `github/codeql-action/analyze` from 4.37.8 to 4.37.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-06 08:23:44 +02:00
Paulus SchoutsenandClaude Opus 5 5a907614af Add Thread to the demo (#53970)
* Add Bluetooth to the demo

Load the bluetooth integration and mock its scanner, advertisement and
connection subscriptions, so the Bluetooth panel, its adapter info,
monitors and network map render in the demo.

Also adds the scaffolding the other Settings > Connectivity panels build
on: a per-integration fixtures contract, registry builders, and the two
registries that collect components, WS command prefixes and registry data
from each integration. `addEntities` now carries `device_id` and
`platform` into the mocked display entity registry, which the panels use
to count entities per device and per integration.

Mocked subscriptions emit their first message from a timeout. Subscribing
is synchronous in the mock, so an immediate callback lands before the
subscriber is ready: `createCollection` overwrote it with its empty
initial fetch, and pages that ignore messages received before their first
render dropped it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Serve integration manifests for the demo's config entries

The integration page reads back the manifest it fetches without guarding,
so opening one for a domain the demo had no manifest for threw. Bluetooth
now ships its manifest through the connectivity fixtures, and manifest/get
falls back to a generated manifest rather than answering with undefined,
which also covers the entries that already lacked one.

Adds a demo E2E test that opens the Bluetooth panel and asserts its counts
are non-zero. The connectivity mocks reach the panel through lazy mock
registration and deferred first emissions, neither of which the demo suite
covered; without them the panel renders but stays empty.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Cover the Bluetooth scanner details subscription in the demo E2E test

The dashboard's adapter count comes from the config entries, so the test
passed even with the scanner details subscription broken, while the
adapter page and network map stayed incomplete.

The adapter page renders a settings button only for adapters that are not
remote scanners, which it knows from the scanner type in those details, so
asserting one button across the three adapters covers the subscription
without asserting on copy.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep connectivity entities when switching demos

Switching demos replaces the whole state map, and only the energy entities
were added back, so every connectivity state disappeared until a reload.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Add Thread to the demo

Load the thread and otbr integrations and mock router discovery, dataset
listing and border router info, so the Thread panel renders in the demo.
The preferred network holds Home Assistant's own border router alongside a
HomePod mini and a Nest Hub; an Amazon Echo forms the one other network.

Widens ThreadRouter's brand union with "amazon", which the backend
already returns. The union is still not exhaustive.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Mock the Thread actions and match the dataset casing

The extended PAN ID was lowercase while the TLV string carries it uppercase.
The dataset dialog looks for one inside the other with a case-sensitive
`includes`, so the preferred network's info showed neither the border
router's URL nor its active dataset.

The panel also offers adding a dataset, choosing the preferred network and
border router, resetting the border router and changing its channel, none of
which were mocked, so each rejected as unimplemented. They now change the
mocked data, and `otbr/set_channel` answers with the delay the panel reads
back.

`ThreadRouter["brand"]` is no longer a union. It only reaches `brandsUrl`,
and the backend resolves it from the border agent's vendor name, so every
new vendor meant another frontend change for no typing benefit.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Push Thread network changes to the discovery stream

The panel groups the routers it draws from `thread/discover_routers`, not
from `otbr/info`, so changing the network only in the info left the border
router drawn under its old network for good. The mock now keeps its
subscribers and announces the router again when it moves.

A reset also has to put the border router on a network of its own instead of
reusing the existing extended PAN ID, which the panel groups by, and it adds
that network rather than taking over the preferred one, so the way back onto
the original network stays available.

`ThreadRouter["brand"]` is null for a vendor the backend does not know, and
the panel now leaves out the icon in that case rather than requesting one
that cannot exist.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Build the Thread datasets from real TLVs

The pasted dataset TLV was malformed: an odd number of hex digits, a network
name field declaring ten bytes for nine, and a network key that ran into the
next type, so a decoder derailed partway through. Datasets are now assembled
from type/length/value triplets, which keeps the declared lengths honest and
each dataset's own extended PAN ID and network name inside its TLV.

Each dataset carries its own, so `thread/get_dataset_tlv` answers for the
dataset it was asked about and rejects an unknown one, and moving the border
router carries the active dataset with it rather than leaving the previous
network's behind, which would have hidden the URL again on the new network.

An imported dataset takes its extended PAN ID from the type 0x02 field
instead of the first sixteen characters, which were the timestamp, and a
reset generates eight hexadecimal bytes rather than a value starting
"RESET".

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Import Thread datasets from the credentials given

The import invented the channel, network name and PAN ID and stored a
rebuilt TLV, so importing real credentials showed a different network than
the one submitted and read back different credentials. It now takes all four
fields from the TLV and keeps that TLV verbatim.

Anything that does not decode is refused rather than falling back to a
generated ID, so the panel shows its error path for malformed credentials.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Treat a Thread import as a revision of the network it names

Datasets sharing an extended PAN ID are revisions of one network, so
importing credentials for a network that is already known updates it rather
than adding a second card for it, and only a newer active timestamp wins.
Re-importing the credentials the demo itself shows used to duplicate the
network.

The active timestamp is now required, as the backend requires it, and a
reset leaves the default router unset, since nominating one is its own
action in the panel.

A router without a brand no longer reserves the avatar column, so its name
is not left indented against an empty graphic.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep the Thread dataset, credentials and channel in step

Deleting a dataset left its credentials behind, so reading them back returned
a network the panel had already dropped. They go with it now.

Changing the channel only moved the border router's reported channel, leaving
the dataset and its active TLV on the old one, so the channel prompt and the
dataset dialog disagreed on the next read. A reset had the mirror problem,
installing a channel 15 network without moving the reported channel. Both
carry the dataset, its TLV and the channel together.

Network names are decoded as UTF-8 rather than one character per byte, so a
non-ASCII name reads correctly and a sequence the backend would refuse is
refused here.

Adds a demo test for the panel: the two networks it starts with, the reset
and rejoin that only show up if the discovery subscription is told, and
credentials being per dataset and going away with one. Checked that it bites
by dropping the announcement, which fails it on the card count after a reset.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Refuse repeated tags and a zero channel in a Thread dataset

A repeated type is malformed and the backend's parser refuses it, rather
than letting the later one win, and a channel field carrying zero is not a
channel it accepts. An absent channel is still fine.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Change the Thread channel without rewriting the credentials

Rebuilding the dataset TLV from its summary replaced the network key, PSKc,
mesh-local prefix, security policy and anything else this mock does not
model with fixture constants, so changing the channel on an imported network
silently swapped its credentials for someone else's. Only the channel
triplet is rewritten now, leaving the rest of the TLV as it was.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Drop the remaining comments from the Thread mock

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

---------

Co-authored-by: Claude <[email protected]>
2026-09-06 08:23:07 +02:00
Paulus SchoutsenandClaude Opus 5 c325392e79 Add Zigbee to the demo (#53971)
* Add Bluetooth to the demo

Load the bluetooth integration and mock its scanner, advertisement and
connection subscriptions, so the Bluetooth panel, its adapter info,
monitors and network map render in the demo.

Also adds the scaffolding the other Settings > Connectivity panels build
on: a per-integration fixtures contract, registry builders, and the two
registries that collect components, WS command prefixes and registry data
from each integration. `addEntities` now carries `device_id` and
`platform` into the mocked display entity registry, which the panels use
to count entities per device and per integration.

Mocked subscriptions emit their first message from a timeout. Subscribing
is synchronous in the mock, so an immediate callback lands before the
subscriber is ready: `createCollection` overwrote it with its empty
initial fetch, and pages that ignore messages received before their first
render dropped it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Serve integration manifests for the demo's config entries

The integration page reads back the manifest it fetches without guarding,
so opening one for a domain the demo had no manifest for threw. Bluetooth
now ships its manifest through the connectivity fixtures, and manifest/get
falls back to a generated manifest rather than answering with undefined,
which also covers the entries that already lacked one.

Adds a demo E2E test that opens the Bluetooth panel and asserts its counts
are non-zero. The connectivity mocks reach the panel through lazy mock
registration and deferred first emissions, neither of which the demo suite
covered; without them the panel renders but stays empty.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Cover the Bluetooth scanner details subscription in the demo E2E test

The dashboard's adapter count comes from the config entries, so the test
passed even with the scanner details subscription broken, while the
adapter page and network map stayed incomplete.

The adapter page renders a settings button only for adapters that are not
remote scanners, which it knows from the scanner type in those details, so
asserting one button across the three adapters covers the subscription
without asserting on copy.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep connectivity entities when switching demos

Switching demos replaces the whole state map, and only the energy entities
were added back, so every connectivity state disappeared until a reload.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Add Zigbee to the demo

Load the zha integration and mock its devices, groups, configuration and
network settings, so the Zigbee panel, its options, groups, network info
and network map render in the demo. Neighbor tables give the map a mesh of
routers and end devices.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Give the Zigbee temperature sensor a unique entity ID

sensor.bedroom_temperature already exists in the home demo config, whose
entities are added last and overwrote the display registry entry,
detaching it from its Zigbee device and undercounting the panel's
entities on that demo.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Label the Zigbee options and take the offline plug unavailable

The options page localizes every field through the backend translations and
falls back to the raw identifier, so the pages showed names like
alarm_master_code. Seed a key per schema field, for the global options as
well as the alarm ones.

The panel reports the TV plug as offline, so its entity has to agree.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Mock the Zigbee panel's write actions

Saving either options page, downloading a backup, changing the channel and
adding or removing a group or its members all rejected as unimplemented, so
every one of those visible controls failed. They now change the mocked state
that the panel refetches.

Saving merges into the stored configuration rather than replacing it, the
way the backend does, so saving one section leaves the rest alone.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Seed the ZHA unavailability timeouts and copy the configuration

The options page falls back to two hours when these keys are absent, so the
battery timeout showed 2 hours where ZHA's default is 6. Both are seeded
now.

The configuration response handed out the backing object, and both editors
mutate the fetched data as controls change, so an edit the user never saved
survived leaving the page. It is copied on the way out; only the update
command writes to the stored configuration.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* List the groupable Zigbee devices

The create group page and the add members dialog build their pickers from
this command, so returning nothing left both permanently empty and made the
group commands unreachable from the panel. The lights and plugs are listed
now.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep the Zigbee pairing page, backups and group rows honest

The add device page subscribes to the permit command as soon as it opens, so
with nothing registered it sat on its spinner for the full permit duration
behind a rejected subscription. A subscription that simply stays open is
enough, since nothing pairs in the demo.

A backup shared its network and node objects with the live settings, so
changing the channel afterwards rewrote the stored backup, which is the one
thing a backup must not do. They are copied now.

Group endpoints carried no entities, so both pickers labelled every light
and plug "No entities". Each now carries the entity the fixtures give it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Wire up the ZHA device pages in the demo

The ZHA info card and device actions look up the device's `zigbee`
connection and render nothing without it, so the demo devices only ever
showed the generic device page. Add the connection, and mock the two
commands that become reachable through it: the manage page's cluster
list (with each cluster's attributes and commands, so the attribute and
command tabs are usable), and the reconfiguration subscription, which
now walks the device's clusters and terminates instead of rejecting.

Written attributes are remembered, so reading one back agrees with what
the write button reported.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Carry the registry area on the ZHA device payloads

The group pickers read the area straight off the device payload rather
than resolving the device registry, so the plugs listed no area. The
backend fills it in from the registry; derive it from the registry
fixtures here for the same reason, so the two cannot drift apart.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Make the Zigbee bindings tab work

Both bind buttons ended in their error state: `zha/groups/bind` and
`zha/groups/unbind` were never registered. Registering them is not
enough on its own — group binding lists only a device's client side, so
with every mocked cluster on the server side the table read "No data"
and the button could never be enabled. The remotes now carry the `out`
clusters they would have on real hardware, and `zha/devices/bindable`
returns the routers, so the device half of the tab is no longer hidden.

Also drops the `any` from the configuration update payload, which
already has an exact type.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

---------

Co-authored-by: Claude <[email protected]>
2026-09-05 09:54:59 +02:00
Paulus SchoutsenandClaude Opus 5 241b8c5771 Add Z-Wave to the demo (#53972)
* Add Bluetooth to the demo

Load the bluetooth integration and mock its scanner, advertisement and
connection subscriptions, so the Bluetooth panel, its adapter info,
monitors and network map render in the demo.

Also adds the scaffolding the other Settings > Connectivity panels build
on: a per-integration fixtures contract, registry builders, and the two
registries that collect components, WS command prefixes and registry data
from each integration. `addEntities` now carries `device_id` and
`platform` into the mocked display entity registry, which the panels use
to count entities per device and per integration.

Mocked subscriptions emit their first message from a timeout. Subscribing
is synchronous in the mock, so an immediate callback lands before the
subscriber is ready: `createCollection` overwrote it with its empty
initial fetch, and pages that ignore messages received before their first
render dropped it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Serve integration manifests for the demo's config entries

The integration page reads back the manifest it fetches without guarding,
so opening one for a domain the demo had no manifest for threw. Bluetooth
now ships its manifest through the connectivity fixtures, and manifest/get
falls back to a generated manifest rather than answering with undefined,
which also covers the entries that already lacked one.

Adds a demo E2E test that opens the Bluetooth panel and asserts its counts
are non-zero. The connectivity mocks reach the panel through lazy mock
registration and deferred first emissions, neither of which the demo suite
covered; without them the panel renders but stays empty.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Cover the Bluetooth scanner details subscription in the demo E2E test

The dashboard's adapter count comes from the config entries, so the test
passed even with the scanner details subscription broken, while the
adapter page and network map stayed incomplete.

The adapter page renders a settings button only for adapters that are not
remote scanners, which it knows from the scanner type in those details, so
asserting one button across the three adapters covers the subscription
without asserting on copy.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep connectivity entities when switching demos

Switching demos replaces the whole state map, and only the energy entities
were added back, so every connectivity state disappeared until a reload.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Add Z-Wave to the demo

Load the zwave_js integration and mock its network status, provisioning
entries and node and controller statistics, so the Z-Wave panel, its
options, statistics, network info, provisioned devices and network map
render in the demo. Last working routes give the map a mesh with
repeaters, asleep and dead nodes.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Give the Z-Wave motion sensor a unique entity ID

binary_sensor.kitchen_motion already exists in the home demo config, whose
entities are added last and overwrote the display registry entry,
detaching it from its Z-Wave device and undercounting the panel's entities
on that demo.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

---------

Co-authored-by: Claude <[email protected]>
2026-09-04 16:20:53 +00:00
06e55141f5 Add MQTT to the demo (#53973)
* Add Bluetooth to the demo

Load the bluetooth integration and mock its scanner, advertisement and
connection subscriptions, so the Bluetooth panel, its adapter info,
monitors and network map render in the demo.

Also adds the scaffolding the other Settings > Connectivity panels build
on: a per-integration fixtures contract, registry builders, and the two
registries that collect components, WS command prefixes and registry data
from each integration. `addEntities` now carries `device_id` and
`platform` into the mocked display entity registry, which the panels use
to count entities per device and per integration.

Mocked subscriptions emit their first message from a timeout. Subscribing
is synchronous in the mock, so an immediate callback lands before the
subscriber is ready: `createCollection` overwrote it with its empty
initial fetch, and pages that ignore messages received before their first
render dropped it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Serve integration manifests for the demo's config entries

The integration page reads back the manifest it fetches without guarding,
so opening one for a domain the demo had no manifest for threw. Bluetooth
now ships its manifest through the connectivity fixtures, and manifest/get
falls back to a generated manifest rather than answering with undefined,
which also covers the entries that already lacked one.

Adds a demo E2E test that opens the Bluetooth panel and asserts its counts
are non-zero. The connectivity mocks reach the panel through lazy mock
registration and deferred first emissions, neither of which the demo suite
covered; without them the panel renders but stays empty.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Cover the Bluetooth scanner details subscription in the demo E2E test

The dashboard's adapter count comes from the config entries, so the test
passed even with the scanner details subscription broken, while the
adapter page and network map stayed incomplete.

The adapter page renders a settings button only for adapters that are not
remote scanners, which it knows from the scanner type in those details, so
asserting one button across the three adapters covers the subscription
without asserting on copy.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep connectivity entities when switching demos

Switching demos replaces the whole state map, and only the energy entities
were added back, so every connectivity state disappeared until a reload.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Add MQTT to the demo

Load the mqtt integration and mock topic subscriptions and device debug
info, so the MQTT panel renders in the demo and its listen card streams
messages on the topic you subscribe to.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Give the MQTT sensor entities unique entity IDs

sensor.kitchen_temperature already exists in the home demo config, whose
entities are added last and overwrote the display registry entry,
detaching it from its MQTT device and undercounting the panel's entities
on that demo.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Key the MQTT debug info by device and send real payloads

The debug info ignored the requested device, so the garage door's MQTT info
showed the fridge sensor's entity. Return the entities of the device that
was asked for, and nothing for one that is not MQTT.

The discovery payload is the config object, not a JSON string:
`mqtt-discovery-payload` dumps it as YAML, so a string rendered as one
quoted scalar. The frontend type said string while the component already
required an object; it now matches what the backend sends.

A subscription takes a topic filter, so echoing it back as the message topic
invented topics no broker could publish. Wildcard levels now resolve to a
concrete matching topic.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Allow an empty MQTT discovery payload

An entity with debug traffic but nothing discovered has no config, and the
backend sends an empty string, so narrowing the field to an object alone was
wrong in the other direction.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Simon Lamon <[email protected]>
2026-09-04 15:55:21 +00:00
Paulus SchoutsenandClaude Opus 5 f6751a8c44 Add Infrared to the demo (#53975)
* Add Bluetooth to the demo

Load the bluetooth integration and mock its scanner, advertisement and
connection subscriptions, so the Bluetooth panel, its adapter info,
monitors and network map render in the demo.

Also adds the scaffolding the other Settings > Connectivity panels build
on: a per-integration fixtures contract, registry builders, and the two
registries that collect components, WS command prefixes and registry data
from each integration. `addEntities` now carries `device_id` and
`platform` into the mocked display entity registry, which the panels use
to count entities per device and per integration.

Mocked subscriptions emit their first message from a timeout. Subscribing
is synchronous in the mock, so an immediate callback lands before the
subscriber is ready: `createCollection` overwrote it with its empty
initial fetch, and pages that ignore messages received before their first
render dropped it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Serve integration manifests for the demo's config entries

The integration page reads back the manifest it fetches without guarding,
so opening one for a domain the demo had no manifest for threw. Bluetooth
now ships its manifest through the connectivity fixtures, and manifest/get
falls back to a generated manifest rather than answering with undefined,
which also covers the entries that already lacked one.

Adds a demo E2E test that opens the Bluetooth panel and asserts its counts
are non-zero. The connectivity mocks reach the panel through lazy mock
registration and deferred first emissions, neither of which the demo suite
covered; without them the panel renders but stays empty.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Cover the Bluetooth scanner details subscription in the demo E2E test

The dashboard's adapter count comes from the config entries, so the test
passed even with the scanner details subscription broken, while the
adapter page and network map stayed incomplete.

The adapter page renders a settings button only for adapters that are not
remote scanners, which it knows from the scanner type in those details, so
asserting one button across the three adapters covers the subscription
without asserting on copy.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep connectivity entities when switching demos

Switching demos replaces the whole state map, and only the energy entities
were added back, so every connectivity state disappeared until a reload.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Add Infrared to the demo

Load the infrared integration and add the emitter and receiver proxy
entities it reads, so the Infrared panel and its device list render in the
demo. The panel is entity driven, so it needs no WebSocket mock.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

---------

Co-authored-by: Claude <[email protected]>
2026-09-04 17:48:40 +02:00
renovate[bot] 1fb138337a Update dependency @rspack/core to v2.2.2 (#53982)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-04 17:36:36 +02:00
Paulus SchoutsenandClaude Opus 5 50df620a01 Add Matter to the demo (#53968)
* Add Matter to the demo

Load the matter integration and mock its network topology, so the Matter
panel and its network map render in the demo, with a Thread and Wi-Fi
topology that includes a border router and an offline node.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Key Matter node diagnostics by device

The diagnostics and ping mocks ignored the requested device, so every
Matter device reported node 1 on Thread and available. The device page
gates its actions on that: the offline garden sensor offered actions that
need a live node, and the Wi-Fi plug offered a Thread network link.

Both are now derived from the topology the map already renders, so a
device's node ID, transport, node type and availability match it, and an
unknown device is rejected as the backend would.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Give Matter fixtures unique entity IDs and mock its device actions

lock.front_door and sensor.garden_temperature already exist in the home
demo config, whose entities are added last and overwrote the display
registry entries, detaching them from their Matter devices. The panel
counted 3 entities instead of 5 on that demo. Renamed to a side door lock
and a patio sensor, which no demo config uses.

The device page offers commissioning, fabric and credential actions for an
available node, none of which were mocked, so each failed with
command_not_mocked.

Adds a demo E2E test for the panel and its map. Emptying the topology
subscription fails it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Mock the Matter lock services and fix the commissioning codes

The lock device exposes "Manage lock", whose dialog reads back the response
of matter.get_lock_info and matter.get_lock_users; neither was mocked, so
it always showed its load-failed alert.

setup_pin_code carried the manual pairing code. The three commissioning
codes now agree on the Matter test payload for passcode 20202021.

Pinging an unknown device rejects like the diagnostics command, matching
the backend, which resolves the device before acting either way.

The E2E test now reads the diagnostics of a Thread, a Wi-Fi and an offline
device, so a regression back to one shared response fails it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Return a credential result and gate the Matter Thread action

`setMatterLockCredential` reads `user_index` off the per-entity response, so
the demo's empty object made saving a code throw. Return the indices the
dialog reads back, and drop the mock for a `clear_lock_credential` service
the frontend never calls.

The device action linking to the Thread panel did not check that the
integration is loaded, unlike the same link on the Matter dashboard, so it
could navigate to a panel that is not there.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep the mocked Matter lock users across changes

The manage dialog reloads the list after every add, edit and delete, so the
static response made each change look like it was reverted. Keep the users
per lock entity and mutate them, and hand back a copy so the dialog's
reactive state sees a new list.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

---------

Co-authored-by: Claude <[email protected]>
2026-09-04 17:34:09 +02:00
renovate[bot] e581172474 Update dependency globals to v17.12.0 (#53981)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-04 13:25:55 +02:00
Paulus SchoutsenandClaude Opus 5 59f16eeca2 Add Serial to the demo (#53974)
* Add Bluetooth to the demo

Load the bluetooth integration and mock its scanner, advertisement and
connection subscriptions, so the Bluetooth panel, its adapter info,
monitors and network map render in the demo.

Also adds the scaffolding the other Settings > Connectivity panels build
on: a per-integration fixtures contract, registry builders, and the two
registries that collect components, WS command prefixes and registry data
from each integration. `addEntities` now carries `device_id` and
`platform` into the mocked display entity registry, which the panels use
to count entities per device and per integration.

Mocked subscriptions emit their first message from a timeout. Subscribing
is synchronous in the mock, so an immediate callback lands before the
subscriber is ready: `createCollection` overwrote it with its empty
initial fetch, and pages that ignore messages received before their first
render dropped it.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Serve integration manifests for the demo's config entries

The integration page reads back the manifest it fetches without guarding,
so opening one for a domain the demo had no manifest for threw. Bluetooth
now ships its manifest through the connectivity fixtures, and manifest/get
falls back to a generated manifest rather than answering with undefined,
which also covers the entries that already lacked one.

Adds a demo E2E test that opens the Bluetooth panel and asserts its counts
are non-zero. The connectivity mocks reach the panel through lazy mock
registration and deferred first emissions, neither of which the demo suite
covered; without them the panel renders but stays empty.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Cover the Bluetooth scanner details subscription in the demo E2E test

The dashboard's adapter count comes from the config entries, so the test
passed even with the scanner details subscription broken, while the
adapter page and network map stayed incomplete.

The adapter page renders a settings button only for adapters that are not
remote scanners, which it knows from the scanner type in those details, so
asserting one button across the three adapters covers the subscription
without asserting on copy.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Keep connectivity entities when switching demos

Switching demos replaces the whole state map, and only the energy entities
were added back, so every connectivity state disappeared until a reload.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

* Add Serial to the demo

Load the usb integration and mock the serial port listing, so the Serial
panel renders in the demo with connected, available and disconnected
ports.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01C6PpwxkMaHCWkEFA27YnLE

---------

Co-authored-by: Claude <[email protected]>
2026-09-04 13:19:36 +02:00
Bram Kragten 18f79dfc91 Bumped version to 20260826.6 2026-09-04 12:40:08 +02:00
Paul Bottein 5861c7487c Only select ha-input-copy text on click when readonly (#53959) 2026-09-04 12:39:01 +02:00
Wendelin 9dbfa821d3 History: Fix "add targets" on empty state (#53953)
Fix history empty targets button only on closed filterbar
2026-09-04 12:38:59 +02:00
Bram KragtenandCopilot Autofix powered by AI 1821e8fd67 Check if failed import is from us, or from user, and check if chunck 404's (#53940)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-04 12:38:58 +02:00
Paul Bottein c8a3aa1d9a Hide empty labels row in more-info related view (#53939) 2026-09-04 12:38:57 +02:00
karwostsandCopilot Autofix powered by AI 6c606a4968 Fix websocket hang in picture card (#53930)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-04 12:38:56 +02:00
Stefan AgnerandCopilot Autofix powered by AI f59a4b4996 Clarify what uninstalling an app deletes (#53923)
* Clarify what uninstalling an app deletes

The uninstall dialog offered a single switch labeled "Also remove app
data". That named the wrong thing twice over: the switch sends
remove_config, which Supervisor applies to the app's configuration
folder, while the app's data folder is deleted on uninstall either way,
independent of the switch.

Relabel the switch after the folder it actually removes, and state in the
dialog that uninstalling permanently deletes the app's stored data, so
the unconditional part of the operation is no longer implied to be
optional.

Rename the local variable and the uninstallHassioAddon parameter to
removeConfig to match the API field they carry.

* Move the app name out of the uninstall dialog title

Dialog guidelines ask to keep user generated content out of titles, as
names can get long enough to be unreadable there. The name now carries
the sentence in the body, which already describes what is deleted.

* Scope the uninstall warning to the app's private data folder

Uninstalling deletes the app's data folder and, when the app maps it,
the public config folder. Files the app wrote through the share, media
or Home Assistant config mappings stay where they are, so promising
that all of its data goes away is wrong for those apps.

Name the folder the deletion is limited to, and say the configuration
folder is only deleted if the app uses one, matching how the Supervisor
API documents the field. Also switch the label to "delete" for
consistency with the sentence above it.

* Name what an app actually keeps in its data folder

Checked the 30 most installed apps for what they write there. It holds
databases (MariaDB, InfluxDB, Grafana, UniFi, Nginx Proxy Manager,
AdGuard), credentials and network identity (Matter fabrics, the Thread
network key, Tailscale node state, Z-Wave JS settings, Mosquitto
accounts) and internal state such as caches and SSH host keys.

"Any other files it created" reaches past all of that. ESPHome keeps
device configuration in the Home Assistant config folder, Node-RED sets
its user directory to /config, WireGuard writes its keys to /ssl, and
those survive an uninstall.

* Fix punctuation in uninstall dialog text

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-04 12:38:55 +02:00
Paulus SchoutsenandClaude Opus 5 1cda8ee42d Add Bluetooth to the demo (#53967)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Claude <[email protected]>
2026-09-04 12:30:33 +02:00
karwostsandCopilot Autofix powered by AI 87a4a70352 Fix websocket hang in picture card (#53930)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-04 12:23:16 +02:00
renovate[bot] 046cf4de14 Update dependency typescript-eslint to v8.69.0 (#53961)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-03 19:57:06 +02:00
renovate[bot] d0d5b93106 Update CodeMirror (#53960)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-03 19:56:25 +02:00
Paul Bottein 3f2c0dae1b Only select ha-input-copy text on click when readonly (#53959) 2026-09-03 19:43:22 +02:00
Aidan Timson 5dea28504e Improve config panels type safety (#53955)
* Improve config type safety

* Type config search event targets

* Type config event handler targets

* Restore
2026-09-03 15:46:28 +02:00
Jan BouwhuisandPaul Bottein 8e1c4e93cf Add reusable state class selector (#53880)
* Add state class selector

* Update src/components/ha-state-class-picker.ts

Co-authored-by: Paul Bottein <[email protected]>

* Fix linter issue

* Rename `state_classes_filter` to `state_classes` as suggested

* Update and rename stateClasses property

* Fis missed rename

* Add default values

---------

Co-authored-by: Paul Bottein <[email protected]>
2026-09-03 15:42:38 +02:00
Bram KragtenandCopilot Autofix powered by AI 5513abbe8f Check if failed import is from us, or from user, and check if chunck 404's (#53940)
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-03 15:15:46 +02:00
Stefan AgnerandCopilot Autofix powered by AI a9862a8f7c Clarify what uninstalling an app deletes (#53923)
* Clarify what uninstalling an app deletes

The uninstall dialog offered a single switch labeled "Also remove app
data". That named the wrong thing twice over: the switch sends
remove_config, which Supervisor applies to the app's configuration
folder, while the app's data folder is deleted on uninstall either way,
independent of the switch.

Relabel the switch after the folder it actually removes, and state in the
dialog that uninstalling permanently deletes the app's stored data, so
the unconditional part of the operation is no longer implied to be
optional.

Rename the local variable and the uninstallHassioAddon parameter to
removeConfig to match the API field they carry.

* Move the app name out of the uninstall dialog title

Dialog guidelines ask to keep user generated content out of titles, as
names can get long enough to be unreadable there. The name now carries
the sentence in the body, which already describes what is deleted.

* Scope the uninstall warning to the app's private data folder

Uninstalling deletes the app's data folder and, when the app maps it,
the public config folder. Files the app wrote through the share, media
or Home Assistant config mappings stay where they are, so promising
that all of its data goes away is wrong for those apps.

Name the folder the deletion is limited to, and say the configuration
folder is only deleted if the app uses one, matching how the Supervisor
API documents the field. Also switch the label to "delete" for
consistency with the sentence above it.

* Name what an app actually keeps in its data folder

Checked the 30 most installed apps for what they write there. It holds
databases (MariaDB, InfluxDB, Grafana, UniFi, Nginx Proxy Manager,
AdGuard), credentials and network identity (Matter fabrics, the Thread
network key, Tailscale node state, Z-Wave JS settings, Mosquitto
accounts) and internal state such as caches and SSH host keys.

"Any other files it created" reaches past all of that. ESPHome keeps
device configuration in the Home Assistant config folder, Node-RED sets
its user directory to /config, WireGuard writes its keys to /ssl, and
those survive an uninstall.

* Fix punctuation in uninstall dialog text

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-03 15:02:09 +02:00
Wendelin d23314f4ff History: Fix "add targets" on empty state (#53953)
Fix history empty targets button only on closed filterbar
2026-09-03 11:56:12 +02:00
dependabot[bot] fcc5b381d3 Bump fast-uri from 3.1.5 to 3.1.6 (#53946)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.5 to 3.1.6.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.5...v3.1.6)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-03 06:23:38 +02:00
renovate[bot] 564205a3f3 Update tsparticles to v4.4.0 (#53951)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-03 06:23:01 +02:00
renovate[bot] 86fb936d14 Update dependency @octokit/auth-oauth-device to v8.0.5 (#53950)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-03 06:22:44 +02:00
Jump-333andCopilot Autofix powered by AI 497b7fce49 Add offline devices count to Matter (#53949)
* Added offline devices count to Matter

* Change condition to check for unavailable nodes

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Improve offline devices error handling

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-09-03 06:22:26 +02:00
Paul Bottein 251aac7e2e Hide empty labels row in more-info related view (#53939) 2026-09-02 19:16:01 +02:00
renovate[bot] 8d2106ccc8 Update dependency @formatjs/intl-datetimeformat to v7.6.1 (#53945)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-02 18:24:09 +02:00
Paul Bottein 3de2637da7 Rename AI settings URL from /config/ai-tasks to /config/ai (#53933) 2026-09-02 18:05:59 +02:00
Jump-333 36d048c8ab Add select-slider card feature for select/input_select tile control (#53876)
* Add select-slider card feature for select/input_select tile control

* Modified select-slider card feature to become just a style of the preexistent select-options

* Modified name icons to segmented and removed suggestion

* Fixed issues with punctuation and spaces

* Renamed segmented to buttons
2026-09-02 12:52:54 +00:00
Paul Bottein 4d7d5231d6 Fix seek bar position jumps while dragging and seeking (#53924)
* Keep seek bar position while dragging

* Unify seek bar progress handling in a shared controller
2026-09-02 14:33:43 +03:00
Aidan Timson b5709a56b0 Wait for connectivity, serial, storage settings readiness (#53935)
* Wait for connectivity settings readiness

* Wait for serial settings readiness

* Wait for storage settings readiness

* Simplify delayed serial scenario

* Test delayed connectivity readiness
2026-09-02 14:25:27 +03:00
Bram Kragten 4c08607dfe Bumped version to 20260826.4 2026-09-02 12:32:22 +02:00
Paulus SchoutsenandClaude Opus 5 f082816d9c Group the connectivity panels behind a Connectivity settings page (#53905)
* Group the connectivity panels behind a Connectivity settings page

Move the connectivity panels (Matter, Zigbee, Z-Wave, KNX, MQTT, Thread,
Bluetooth, serial, infrared, radio frequency, Insteon, and tags) behind a new
Connectivity page. It sits with Voice assistants in the second settings group,
where those panels used to be listed individually.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y7Yy1BcbkMjCZEtkTEqyKm

* Update config panel e2e coverage for the Connectivity page

The connectivity panels moved off the settings root, so split the link smoke
cases and assert them on the Connectivity page instead. Add a route smoke case
for /config/connectivity.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y7Yy1BcbkMjCZEtkTEqyKm

---------

Co-authored-by: Claude <[email protected]>
2026-09-02 12:30:56 +02:00
Bram Kragten b503862853 Bumped version to 20260826.3 2026-09-02 10:50:44 +02:00
Bram Kragten 1afa83d244 Fix stale trigger/condition lists (#53932) 2026-09-02 10:50:23 +02:00
Petar Petrov 7b93dde3c6 Only pan sankey charts on touch devices once zoomed (#53931) 2026-09-02 10:50:22 +02:00
Paul Bottein f8cb27b7ab Migrate add-to action list to grouped list style (#53921) 2026-09-02 10:50:21 +02:00
Paul Bottein 62f1509be4 Split more-info related and details views (#53920)
* Split more-info related and details views

* Update the related view e2e smoke case
2026-09-02 10:50:20 +02:00
Bram Kragten 1b834303d0 Fix stale trigger/condition lists (#53932) 2026-09-02 10:44:43 +02:00
Petar Petrov b455a34998 Only pan sankey charts on touch devices once zoomed (#53931) 2026-09-02 10:36:09 +02:00
Paul Bottein d84ef6b1bb Fit the picker popover to its list and align style with the select menu (#53801)
* Fit the picker popover to its list and align it with the select menu

* Use styleMap for the popover custom properties

* Fix combo box list not rendering for direct embedders
2026-09-02 10:15:53 +02:00
Paulus SchoutsenandClaude Opus 5 10ae5c1dd6 Rename AI tasks settings to AI and add Model Context Protocol card (#53906)
* Rename AI tasks settings to AI and add Model Context Protocol card

The AI settings page now shows a second card for the Model Context
Protocol server. When no mcp_server config entry exists, a centered
button starts the config flow. When enabled, the card shows the server
URL, an alphabetical list of registered LLM APIs with copy buttons for
their URLs, a configure button that opens the options flow, and a
disable action that deletes the config entry.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Mock MCP server config entry and LLM APIs in demo

Lets the demo show the enabled state of the Model Context Protocol
card on the AI settings page.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Rename MCP server URL row and mock MCP in the demo

The row heading did not say what makes this endpoint different from the
per API endpoints below it. Call it "Your MCP URL" and show the config
entry title, so it is clear which APIs it serves.

Mock an MCP server config entry and the registered LLM APIs in the demo.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Simplify MCP card URLs to labeled copy buttons

Build the URLs from the origin Home Assistant is browsed on, so the
copied URL is reachable for whoever copies it.

Drop the URL text from the card and label the copy action, which was an
unlabeled icon that did not say it copies a URL. Name the API section
Individual MCP APIs so it is clear those are MCP endpoints too.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Move MCP disable action into a header overflow menu

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Align MCP card header actions and drop the disable icon

Put the help and overflow buttons in the header row so they line up with
each other and the title, instead of positioning them absolutely.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Rename MCP card row to Your MCP API

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Drop trailing word from MCP card description

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Put configure before copy and drop Calendar from the demo

Ordering the configure button first lines the copy buttons up across all
rows. Calendar is not an LLM API integrations register, so mock only
Assist and Music Assistant.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Always show the MCP configure button

The options flow is now in core, so the entry always supports options.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Tell users where to add the MCP URL

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Link the MCP docs from the card description

Point at the integration documentation for agent-specific instructions,
and call them AI agents.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Drop the MCP card help icon

The description links the documentation, so the header icon is a second
link to the same page.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Show MCP URLs in outlined rows

Give each URL its own outlined row with the URL under the name, and copy
with an icon button, so the URLs are visible before copying.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Use hassUrl for MCP URLs and show load errors

Build the URLs with the standard helper instead of the window location.

Catch a failing load and show an alert. Without it a failed load left
the card with neither the URLs nor the enable button.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

* Show a spinner while the MCP card loads

Without it the card showed only its description until the config entries
arrived.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RQUrBPMXN35UQ19ZYPRpEZ

---------

Co-authored-by: Claude <[email protected]>
2026-09-02 08:38:21 +03:00
renovate[bot] 74967ef6ee Update dependency generate-license-file to v4.2.5 (#53929)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-09-02 08:23:09 +03:00
Maarten Lakerveld 46de23727f Remove ES5 specific code (#53899)
* Remove web components polyfills and ES5 custom elements adapter

All supported browsers (legacy floor: Chrome 59, Safari/iOS 12, Firefox 94)
have native shadow DOM and custom elements, so the webcomponents bundle,
ShadyCSS branch, and lit polyfill-support are unreachable. The legacy build
now emits ES2017 classes, so custom-elements-es5-adapter and the
window.loadES5Adapter hook (no known third-party consumers) are removed.
Also stops shipping the never-loaded dialog-polyfill css and drops both
now-unused dependencies.

* Remove keyed-es5 Terser workaround

The custom keyed directive existed because Terser with ecma: 5 miscompiled
the destructured update() parameters (#28732). The legacy build now minifies
with ecma: 2017, so the stock lit-html keyed directive works in both builds.

* Remove old-browser JS shims and stale ES5 build references

Drops the IE-only navigator.msMaxTouchPoints check, replaces the
toggleAttribute helper with the native method (polyfilled automatically for
Chrome < 69 in the legacy build), and removes babel excludes for the
uninstalled proxy-polyfill and unfetch packages. Updates comments that
still described the legacy build as ES5.

* Remove vendor prefixes for no-longer-supported browsers

Deletes -ms- prefixes (IE/EdgeHTML only) and -webkit-/-moz- prefixed
declarations that every supported browser understands unprefixed, or that
Lightning CSS re-adds automatically from the unprefixed property in
production builds. Blocks that only had prefixed user-select now use the
standard property (previously Firefox got no user-select there at all).
Converts the four -webkit-linear-gradient() declarations - the sole
gradient syntax on those sliders - to standard linear-gradient().

* Remove dead html_url custom panel support

html_url pointed to an HTML Import, a Polymer-era feature removed from
Chrome in 2019 and never shipped elsewhere. The loader has not handled the
html type for years (it fell through to a rejection), and core's
panel_custom integration no longer accepts the option, so the branch was
unreachable. Also drops the ha-panel-${name} legacy tag naming that was
keyed on html_url.

* Repair list-plugins-and-polyfills script for Babel 8

The audit script died at startup since the Babel 8 update: preset-env no
longer exposes lib/debug.js (logPlugin is now inlined locally, built on the
public getInclusionReasons helper) and babel-plugin-polyfill-corejs3 v1 no
longer ships lib/shipped-proposals.js (list inlined).

Instead of invoking the preset with a hand-mocked plugin API - the part
that kept drifting - the plugin listing now runs a real transform of an
empty file with preset-env in debug mode, declaring the same caller
capabilities as babel-loader. The polyfill listing now passes the
configured core-js version to core-js-compat, mirroring the provider's own
filtering so the report cannot list modules the installed core-js lacks.
Output is byte-identical to the direct-invocation approach. Also documents
the script in the build-scripts README.

* Correct macOS floor for Safari 26 in companion app UA regex

Safari 26 ships for macOS 14 Sonoma and 15 Sequoia, not only macOS 26, so
the SAFARI_TO_MACOS entry breaking the minimum-supported-macOS pattern
would have sent updated macOS 14/15 companion apps to the legacy build
once the modern floor reaches Safari 26.

* Remove orphaned values left behind by vendor prefix removal

* Require macOS 14.6 for Safari 26 in companion app UA regex
2026-09-02 08:15:36 +03:00
Paul Bottein dc5d9f48bb Migrate add-to action list to grouped list style (#53921) 2026-09-01 16:28:30 +02:00
Paul Bottein 3d3cdabfe7 Split more-info related and details views (#53920)
* Split more-info related and details views

* Update the related view e2e smoke case
2026-09-01 16:17:37 +02:00
Paul Bottein 4b1f12c0ef Add seek support to the browser media player (#53917) 2026-09-01 14:44:21 +02:00
Bram Kragten efcf93191f Bumped version to 20260826.2 2026-09-01 10:34:13 +02:00
Maarten Lakerveld 577ededaf4 Fix log entry details collapsing to an ellipsis on narrow screens (#53881)
The secondary line of system log entries was made inline-block in #53575
to apply text direction. An inline-block is an atomic inline, so the
parent's text-overflow: ellipsis hid the whole line whenever it did not
fit, leaving only "…" on mobile. Use unicode-bidi: isolate instead so
direction still applies while the text truncates normally.

Fixes #53879
2026-09-01 10:33:46 +02:00
Paul Bottein 1cd16ad301 Always allow saving vacuum segment mapping (#53862) 2026-09-01 10:33:44 +02:00
Paul Bottein 2c2f733a82 Remove vacuum battery_level attribute unit (#53855) 2026-09-01 10:33:43 +02:00
Krisjanis Lejejs 22df9c704c Use the cloud auto-login flow in the voice satellite wizard (#53854)
Replace the wizard's own registration and sign-in screens with the cloud
panel's, extracted into cloud-register-card, so signing up mid-wizard gets
email-confirmation auto login instead of the legacy register plus login
polling. The wizard's copy of the login error ladder goes with it.

Drive the registration state from cloud/status rather than from the cloud
events, which carry nothing it does not already hold. The waiting view now
clears when the pending registration does, so a restart no longer leaves it
spinning on a registration the backend has forgotten.

Depends on the auto-login state fix in home-assistant/core#180423: without
it a retry loop that gives up before the register view stores its controller
leaves cloud/status reporting a pending registration with no reason, which
this no longer reads from the event instead.
2026-09-01 10:33:42 +02:00
Maarten Lakerveld d73341b2f8 Allow negative number entry on iOS when the number selector has no min (#53852)
The iOS workaround from #52925 only applied when the selector had an
explicit negative min. The numeric threshold selector used by the power
triggers passes a number selector without a min, so the digit-only keypad
(without a minus key) was still shown. Treat a missing min as allowing
negatives too.

Also leave inputmode unset instead of forcing "text": on a number input
iOS then shows the Numbers and Punctuation keyboard, which has a minus
key and fits numeric entry better than the full QWERTY keyboard.

Fixes #53747
2026-09-01 10:33:41 +02:00
Bram Kragten 907d15e7c1 Load the base map through core's tile proxy (#53845)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
(cherry picked from commit a9d7712fb2)
2026-09-01 10:32:08 +02:00
Maarten Lakerveld 662ac1dc57 Fix RTL map labels and add English names to non-Latin ones (#53856)
* Load MapLibre RTL text plugin so Hebrew and Arabic map labels read correctly

The vector base map never registered MapLibre's RTL text plugin, so
right-to-left scripts were shaped left to right and every label came out
reversed. Ship @mapbox/mapbox-gl-rtl-text from /static/map/ alongside the
glyphs (no third-party host) and register it once, lazily, before the
first vector layer is created.

Fixes #53851

* Add the English name to map labels in non-Latin scripts

Before the move to vector tiles the CARTO basemap showed English names
everywhere. The OSM style shows local names, which most users cannot
read in Cyrillic, Arabic, Hebrew or CJK regions. Keep the local name and
add the English one from the tiles under it - in parentheses for street
labels, which cannot break lines. Latin-script names are left alone, so
Köln stays Köln.

(cherry picked from commit 156840b6ff)
2026-09-01 10:32:02 +02:00
Paul Bottein 39e7a05258 Fix the History timeline labels and tooltip placement (#53843)
* Draw History timeline names in a label column again

* Keep the timeline tooltip level with the hovered row
2026-09-01 10:27:21 +02:00
Paul Bottein 5cb7de5ac6 Fix weather forecast tabs in the more info dialog (#53841) 2026-09-01 10:27:20 +02:00
Paulus Schoutsen 0c7d3c8483 Render camera favorites as camera tiles (#53814) 2026-09-01 10:27:18 +02:00
lalexdotcom c92e5aa134 Report the fallback camera preview as loaded in ha-camera-stream (#53810)
`ha-camera-stream` declares a `load` event and both of its video players fire it through `fireEvent(this, "load")`, but the MJPEG and snapshot fallback `<img>` never does. Every camera without a working stream therefore goes through the one path that stays silent.

`hui-image` listens for that event to record `_lastImageHeight`, and that value is what drops the `.ratio` class so the container can size to its content. Without it the container keeps the 16:9 padding box it falls back to before anything is measured, while the picture is drawn at its own ratio and overflows. Measured against a 600x410 camera in a 600px wide card: the container stays 337.5px tall while the picture is drawn 410px tall, and it is still so ten seconds after the card is built.

Firing the event from the fallback image settles it: the container becomes 410px, matching the picture, and the 16:9 fallback goes back to being a placeholder for the first frame instead of a permanent state. Cameras that do have a stream are unaffected — they already fire `load` from their player.
2026-09-01 10:27:17 +02:00
a9d7712fb2 Load the base map through core's tile proxy (#53845)
Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-09-01 10:26:18 +02:00
Krisjanis Lejejs a03efc1c5d Use the cloud auto-login flow in the voice satellite wizard (#53854)
Replace the wizard's own registration and sign-in screens with the cloud
panel's, extracted into cloud-register-card, so signing up mid-wizard gets
email-confirmation auto login instead of the legacy register plus login
polling. The wizard's copy of the login error ladder goes with it.

Drive the registration state from cloud/status rather than from the cloud
events, which carry nothing it does not already hold. The waiting view now
clears when the pending registration does, so a restart no longer leaves it
spinning on a registration the backend has forgotten.

Depends on the auto-login state fix in home-assistant/core#180423: without
it a retry loop that gives up before the register view stores its controller
leaves cloud/status reporting a pending registration with no reason, which
this no longer reads from the event instead.
2026-09-01 10:04:56 +03:00
Paulus SchoutsenandClaude Opus 5 9f7c353ad0 Group the connectivity panels behind a Connectivity settings page (#53905)
* Group the connectivity panels behind a Connectivity settings page

Move the connectivity panels (Matter, Zigbee, Z-Wave, KNX, MQTT, Thread,
Bluetooth, serial, infrared, radio frequency, Insteon, and tags) behind a new
Connectivity page. It sits with Voice assistants in the second settings group,
where those panels used to be listed individually.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y7Yy1BcbkMjCZEtkTEqyKm

* Update config panel e2e coverage for the Connectivity page

The connectivity panels moved off the settings root, so split the link smoke
cases and assert them on the Connectivity page instead. Add a route smoke case
for /config/connectivity.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Y7Yy1BcbkMjCZEtkTEqyKm

---------

Co-authored-by: Claude <[email protected]>
2026-09-01 08:37:57 +03:00
lalexdotcom 350fae4107 Report the fallback camera preview as loaded in ha-camera-stream (#53810)
`ha-camera-stream` declares a `load` event and both of its video players fire it through `fireEvent(this, "load")`, but the MJPEG and snapshot fallback `<img>` never does. Every camera without a working stream therefore goes through the one path that stays silent.

`hui-image` listens for that event to record `_lastImageHeight`, and that value is what drops the `.ratio` class so the container can size to its content. Without it the container keeps the 16:9 padding box it falls back to before anything is measured, while the picture is drawn at its own ratio and overflows. Measured against a 600x410 camera in a 600px wide card: the container stays 337.5px tall while the picture is drawn 410px tall, and it is still so ten seconds after the card is built.

Firing the event from the fallback image settles it: the container becomes 410px, matching the picture, and the 16:9 fallback goes back to being a placeholder for the first frame instead of a permanent state. Cameras that do have a stream are unaffected — they already fire `load` from their player.
2026-08-31 13:36:48 +00:00
Maarten LakerveldandCopilot Autofix powered by AI e09c4084b7 Timer UI enhancements (#53793)
* Add timer data helpers for formatter-based display and duration serialization

Refactor computeDisplayTimer to take formatEntityState instead of hass so
context-migrated components can reuse it, add finishes_at to TimerEntity,
and add durationDataToTimerString for serializing duration input values.

* Modernize timer more-info dialog with state header and live countdown

Use ha-more-info-state-header with a ticking remaining-time display and
the standard more-info control layout. Adds timer to
DOMAINS_WITH_NEW_MORE_INFO, replacing the legacy state-card row.

* Add timer-actions and timer-presets card features

timer-actions shows start/pause/cancel/finish buttons (finish opt-in)
with state-aware disabling; start becomes restart while active.
timer-presets shows configurable one-tap durations that call timer.start.
Timer tile suggestions default to the timer-actions feature.

* Pulse timer red when it finishes

When a timer runs out or timer.finish is called, the tile icon and the
more-info countdown pulse red twice. Cancelling does not pulse: the new
timerJustFinished helper distinguishes the transitions via the
last_transition attribute. Honors prefers-reduced-motion.

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* Send normalized duration for timer presets

Presets are parsed leniently by createDurationData like other duration
inputs, but the raw config value was sent to timer.start. A malformed
preset such as 1:nope:00 rendered as 1 h yet was rejected by core. Store
the normalized seconds so the label and the service call always match.

* Store timer presets on the entity instead of the card config

Review feedback: presets belong to the timer entity, like cover favorite
positions and light favorite colors. They now live in the entity registry
options and are edited in the more info dialog through the shared favorites
UI, which also brings reset and copy to other timers. The tile feature keeps
its style option but reads the presets from the registry.

* Reject a zero duration when adding or editing a timer preset

A zero duration passed the form's required check but was then treated as a
cancel, so saving the prefilled 0:00:00 silently did nothing. Form dialogs
now take an optional submit-time validate hook that blocks the submit and
shows a field error, and the preset dialog uses it to require at least one
second.

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-08-31 14:12:26 +03:00
nokside 946722daa2 Optimize update entities computation in hui-updates-card (#53878) 2026-08-31 12:28:18 +03:00
karwostsandPetar Petrov 3b038d5372 Support multiple for media selector (#53815)
* Support multiple for media selector

* Update src/components/ha-selector/ha-selector-media.ts

Co-authored-by: Petar Petrov <[email protected]>

* add to UI

* merge fix

* add helper

* Modify media item picker for clearable and image upload

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-08-31 12:02:03 +03:00
Paul Bottein 6b7d387175 Fix weather forecast tabs in the more info dialog (#53841) 2026-08-30 19:52:50 +02:00
renovate[bot] 8a4202ea19 Update dependency lint-staged to v17.4.1 (#53887)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-30 16:47:46 +02:00
renovate[bot] 2eaf1112f2 Update dependency @rspack/core to v2.2.1 (#53886)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-30 16:47:26 +02:00
dependabot[bot] d30ff07394 Bump the codeql-action group across 1 directory with 2 updates (#53884)
Bumps the codeql-action group with 2 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.7 to 4.37.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28)

Updates `github/codeql-action/analyze` from 4.37.7 to 4.37.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-30 09:59:04 +03:00
renovate[bot] 5616b52979 Update dependency js-yaml to v5.4.1 (#53883)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-30 07:55:36 +03:00
Maarten Lakerveld 4219288701 Fix log entry details collapsing to an ellipsis on narrow screens (#53881)
The secondary line of system log entries was made inline-block in #53575
to apply text direction. An inline-block is an atomic inline, so the
parent's text-overflow: ellipsis hid the whole line whenever it did not
fit, leaving only "…" on mobile. Use unicode-bidi: isolate instead so
direction still applies while the text truncates normally.

Fixes #53879
2026-08-29 21:54:56 +02:00
nokside 09b221cf45 Fix date, datetime, and color temperature initial values (#53863) 2026-08-29 16:21:44 +03:00
renovate[bot] 89a467cac7 Update dependency @rspack/core to v2.2.0 (#53872)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 07:15:53 +00:00
Brandon c29b693038 Make the media selector clear button follow image_upload (#53866) 2026-08-29 09:14:05 +02:00
renovate[bot] 7ab178d045 Update Node.js to v24.20.0 (#53871)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 09:08:01 +02:00
renovate[bot] 538523c58b Update dependency generate-license-file to v4.2.4 (#53868)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-29 09:07:39 +02:00
136cf0c8bf Revamp user settings page & navigation (#52070)
* refactor(profile): split general section into subpages with dashboard navigation

Replace the two-tab profile layout (general/security) with a dashboard-first
navigation structure. The general section is split into three focused subpages
(preferences, localization, browser), each wrapping the original row components
unchanged. A new dashboard page provides a user card (name, owner badge, logout)
and a navigation list linking to all four subpages.

Add ha-navigation-list as a reusable component for page navigation lists.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor: remove orphan translation keys after general section split

Drop tabs.general and current_user, which were only used in the now-deleted
ha-profile-section-general.ts and the old profileSections tab config.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor(profile): align dashboard layout with Bluetooth panel pattern

Replace .content with .container (padding on wrapper, max-width/margin on
cards) to match the layout convention used in protocol panels like Bluetooth.
Always show the chevron in ha-navigation-list, removing the narrow condition.
Drop the unused narrow prop from ha-navigation-list.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor: move ha-config-navigation-list to src/components

Makes the component available outside the config panel. Update import
paths in the two existing config consumers and use it in the profile
dashboard. Remove the now-unused ha-navigation-list (which relied on
ha-md-list/ha-md-list-item).

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* fix: security subpage width and card spacing

Use .container > * instead of ha-card to apply max-width and margin,
since the security cards are custom elements whose inner ha-card lives
in their own shadow DOM and is unreachable from the parent stylesheet.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor(profile): move language setting to localization subpage

Language is a regional/cultural preference, consistent with the other
settings in localization (time zone, date and time formats).

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor(profile): rename profile subpage labels

- "User preferences" -> "Appearance"
- "Browser settings" -> "This browser"
- "Mobile app settings" -> "This mobile app"

* feat(profile): surface theme picker on dashboard page

Move ha-pick-theme-row from the Appearance subpage to the profile
dashboard, between the user card and the navigation list. Theme and
dark mode are now accessible directly without navigating to a subpage.

Update Appearance description to reflect its new scope.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor(profile): restructure theme row layout and labels

Split dark mode and color pickers into separate ha-settings-row elements
with headings. Move reset button outside the color-row to keep the label
vertically stable when the button appears. Add padding to reset row.
Rename "Reset" to "Reset colors" for clarity.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* add title to theme settings card

* refactor(profile): apply theme row layout improvements to ha-theme-settings

Migrate the dark mode and color pickers layout from ha-pick-theme-row into
ha-theme-settings: use separate ha-settings-row elements with headings for
dark mode and custom colors, move reset button outside as a sibling element.
Add colors label to ThemeSettingsLabels interface.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor(profile): migrate theme settings to ha-list-item-base layout

Replace ha-settings-row elements in ha-theme-settings with ha-list-item-base
inside ha-list-base for a more compact appearance. Split color pickers into
individual rows (one per color). Reduce vertical padding to --ha-space-2.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* refactor(profile): combine color pickers into single row with label

Merge primary and accent color pickers into one ha-list-item-base row
under a "Custom colors" headline. Restore labels on individual pickers
and increase their min-width to 150px.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* fix(profile): stack theme settings rows vertically in narrow mode

Reflect narrow prop on host and use ::part(base/end) to stack all
ha-list-item-base rows in column layout on narrow screens, preventing
headline truncation from oversized end slot controls.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* Fix test:e2e:demo

* fix broken links

* Add my links

* Use s instead of smal for ha-button size

Co-authored-by: Maarten Lakerveld <[email protected]>

---------

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
Co-authored-by: Maarten Lakerveld <[email protected]>
2026-08-28 21:57:59 +02:00
renovate[bot] 920c858056 Update dependency @lokalise/node-api to v16.4.0 (#53865)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-28 21:57:46 +02:00
renovate[bot] 3d2a4bfa04 Update dependency generate-license-file to v4.2.3 (#53864)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-28 21:57:43 +02:00
Paul Bottein e2c9b2cb79 Always allow saving vacuum segment mapping (#53862) 2026-08-28 17:21:14 +02:00
Maarten Lakerveld d38ee185bf Allow negative number entry on iOS when the number selector has no min (#53852)
The iOS workaround from #52925 only applied when the selector had an
explicit negative min. The numeric threshold selector used by the power
triggers passes a number selector without a min, so the digit-only keypad
(without a minus key) was still shown. Treat a missing min as allowing
negatives too.

Also leave inputmode unset instead of forcing "text": on a number input
iOS then shows the Numbers and Punctuation keyboard, which has a minus
key and fits numeric entry better than the full QWERTY keyboard.

Fixes #53747
2026-08-28 16:50:01 +02:00
Rishab MehtaandPetar Petrov 7e10f50419 Prefer neighbor relationship over raw LQI in ZHA network graph fallback (#53764)
* Prefer neighbor relationship over raw LQI in ZHA network graph fallback

* Create zha-network-data.test.ts

* Fix relative import paths and test connectivity via BFS instead of exact edges

* Add test coverage for extended relationship priority

* Apply suggestions from code review

Co-authored-by: Petar Petrov <[email protected]>

* Just capitalizing relationshipPriority → RELATIONSHIP_PRIORITY in those two spots — nothing else changes.

* Update zha-network-data.ts

* Update zha-network-data.test.ts

* Update zha-network-data.ts

* Update zha-network-data.ts

* Update zha-network-data.test.ts

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-08-28 15:47:00 +03:00
nokside 070fd96d6c Fix and centralize selector initial value handling (#53729)
* Fix and centralize selector initial value handling

* Fix unsupported selector initial values

* Omit undefined choose child values

* Fix device class and object selector initial values
2026-08-28 15:45:57 +03:00
Maarten Lakerveld 156840b6ff Fix RTL map labels and add English names to non-Latin ones (#53856)
* Load MapLibre RTL text plugin so Hebrew and Arabic map labels read correctly

The vector base map never registered MapLibre's RTL text plugin, so
right-to-left scripts were shaped left to right and every label came out
reversed. Ship @mapbox/mapbox-gl-rtl-text from /static/map/ alongside the
glyphs (no third-party host) and register it once, lazily, before the
first vector layer is created.

Fixes #53851

* Add the English name to map labels in non-Latin scripts

Before the move to vector tiles the CARTO basemap showed English names
everywhere. The OSM style shows local names, which most users cannot
read in Cyrillic, Arabic, Hebrew or CJK regions. Keep the local name and
add the English one from the tiles under it - in parentheses for street
labels, which cannot break lines. Latin-script names are left alone, so
Köln stays Köln.
2026-08-28 14:44:43 +03:00
5ff7a05ec5 feat: option to show add event button in calendar card (#53055)
* feat: option to show add event button in calendar card

* fix: remove translation file

* refactor: rename show_addfab to show_add_event

* fix: css calendar height

* feat: add event styling options

* Delete translations/backend/en.json

* fix: translation file

* fix: translations file

* fix: no box shadow when button below calendar

* fix: inconsistent narrow mode calculation

* fix: screen reader compability

Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* fix: margin-inline-start for rtl layout support

* fix: use literal union instead of string in editor

* fix: use sentence case

* Apply suggestions from code review

Co-authored-by: Petar Petrov <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>

* fix: remove unused class

* feat: use visible parameter to toggle editor elements

* refactor: split add-fab into mulitple attributes for ha-full-calendar

* fix: lint type error

* fix: editor defaults

---------

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Petar Petrov <[email protected]>
2026-08-28 14:39:17 +03:00
MartinandPetar Petrov c3643555ab Respect gas entity display precision in energy dashboard (#53712)
* Respect gas display precision in gas graph

The gas graph previously formatted the total gas consumption using the generic number formatter, which could ignore the display precision  configured on the selected gas entity.

Use the configured gas entity's display precision for both the visible total chip and the total consumption tooltip.

This keeps the gas graph consistent with the entity configuration. For example, a gas entity configured with 3 decimal places will display 0.009 m³ instead of being rounded to 0.01 m³.

* Use configured gas entity display precision in energy distribution card

The energy distribution card previously formatted gas usage with the generic
energy formatter, which could ignore the display precision configured on the
selected gas entity.

Use the display precision of the configured gas consumption entity when
formatting the gas value in the energy distribution card.

This keeps the displayed value consistent with the entity configuration. For
example, a gas entity configured with 3 decimal places will now display
0.009 m³ instead of being rounded to 0.01 m³.

* Respect gas display precision in energy sources table

The energy sources table previously formatted gas values using the generic number formatter, which could ignore the display precision configured on the selected gas entity.

Use the configured gas entity's display precision for both individual gas source rows and the gas total row.

This keeps gas values consistent with the entity configuration. For example, a gas entity configured with 3 decimal places will display 0.009 m³ instead of being rounded to 0.01 m³.

* Use highest gas display precision for energy distribution

The energy distribution card previously used the display precision of the first configured gas source for the aggregated gas value.

Use the highest configured display precision across all gas sources instead of special-casing the first source.

This avoids making source 0 authoritative for an aggregate value and preserves the greatest configured precision when multiple gas sources are present.

* Use highest gas display precision for energy distribution

The energy distribution card previously used the display precision of the first configured gas source for the aggregated gas value.

Use the highest configured display precision across all gas sources instead of special-casing the first source.

This avoids making source 0 authoritative for an aggregate value and preserves the greatest configured precision when multiple gas sources are present.

* Use highest gas display precision in gas graph

The gas graph previously used the display precision of the first configured gas source for its aggregated total.

Use the highest configured display precision across all gas sources instead of special-casing source 0.

This keeps the graph total and tooltip consistent with the greatest configured precision when multiple gas sources are present.

* Use display_precision for entity precision

Replace dp with display_precision when reading precision from hass.entities, matching the EntityRegistryDisplayEntry type used by the frontend.

* Use display_precision for entity precision

Replace dp with display_precision when reading precision from hass.entities, matching the EntityRegistryDisplayEntry type used by the frontend.

* Use display_precision for entity precision

Replace dp with display_precision when reading precision from hass.entities, matching the EntityRegistryDisplayEntry type used by the frontend.

* Use display_precision for entity precision

Replace dp with display_precision when reading precision from hass.entities, matching the EntityRegistryDisplayEntry type used by the frontend.

* Use display_precision for entity precision

Replace dp with display_precision when reading precision from hass.entities, matching the EntityRegistryDisplayEntry type used by the frontend.

* Use display_precision for entity precision

Replace dp with display_precision when reading precision from hass.entities, matching the EntityRegistryDisplayEntry type used by the frontend.

* Restore consumption formatting in energy distribution card

* Respect gas display precision in energy sources table

* Respect gas display precision in energy graph

* Respect display precision in formatConsumptionShort

* Pass gas display precision to consumption formatter

Add logic to calculate gas display precision based on available sources.

* Use gas display precision for graph y-axis

* Update distribution card on gas precision changes

* Update sources table on gas precision changes

* Update gas graph when display precision changes

Refresh the gas graph when a gas entity's display precision or unit of measurement changes, ensuring the configured precision is applied without waiting for new energy data.

* Update distribution card on gas unit changes

Refactor gas source display precision check and update unit of measurement comparison.

* Derive gas display precision with a getter

* Fix hass change handling in energy sources table

* Fix hass change handling in gas graph

* Fix hass change handling in energy distribution

* Fix gas unit narrowing in energy distribution

* Fix formatting in gas graph card

Refactor gasDisplayPrecisions assignment for better readability.

* Fix formatting in energy sources table

* Fix Prettier formatting in energy gas cards

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-08-28 11:15:12 +00:00
Paul Bottein ae2c296272 Remove vacuum battery_level attribute unit (#53855) 2026-08-28 12:42:38 +02:00
noksideandMaarten Lakerveld 1db1c8024e Improve low battery entity lookup (#53850)
* Improve low battery entity lookup

* Apply suggestions from code review

Co-authored-by: Maarten Lakerveld <[email protected]>

* Fix formatting

---------

Co-authored-by: Maarten Lakerveld <[email protected]>
2026-08-28 10:47:44 +02:00
renovate[bot] 2f003ca999 Update dependency js-yaml to v5.4.0 (#53853) 2026-08-28 08:58:36 +01:00
Maarten Lakerveld b1d8a21aaa Don't close drawer when a nested tooltip hides (#53809)
wa-after-hide from a tooltip inside the drawer (e.g. the exact time
tooltip on a persistent notification) bubbled to the wa-drawer listener
and was treated as the drawer closing. Only handle the drawer's own event.

Fixes #52901
2026-08-28 08:45:28 +01:00
renovate[bot] cde2e66229 Update dependency typescript-eslint to v8.68.0 (#53848)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-28 06:45:08 +02:00
Paulus Schoutsen 71d5500ed8 Render camera favorites as camera tiles (#53814) 2026-08-28 00:05:02 +02:00
renovate[bot] 462321a3c8 Update dependency eslint to v10.9.1 (#53846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-27 22:02:51 +02:00
renovate[bot] afc0c36dd9 Update dependency marked to v18.0.11 (#53847)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-27 22:02:43 +02:00
Bram Kragten 7f86074e07 Revert "Load the base map through core's tile proxy"
This reverts commit 4b9e47079c.
2026-08-27 19:15:16 +02:00
Bram KragtenandClaude Opus 5 4b9e47079c Load the base map through core's tile proxy
Core now proxies both vector and raster tiles, which is what lets them be
requested with an application User-Agent and without a referrer - a
browser can set neither. So the frontend stops talking to OpenStreetMap
and CARTO directly and goes through /api/map_tiles.

The proxy is token gated, so `ha-map` fetches one over the WebSocket
before setting up, following the brands token pattern: cached at module
level, refreshed well inside its lifetime so a dashboard left open for
days keeps working. The blocking wait is kept to about a second - a
backend without the proxy must not hold the map hostage - and the
remaining retries run in the background to ride through the window after
a restart where the WebSocket is up but the handler is not registered
yet.

Two things that are not obvious and cost a measurement each:

MapLibre's `transformRequest` has to return absolute URLs. Tiles are
fetched from a worker, which has no document to resolve a relative URL
against, and the TileJSON that core serves has relative `tiles`. Measured
with a relative TileJSON on one origin: with absolute URLs the style
loads and 8,456 features render; without them exactly one request is made
- the style - and nothing else loads, with no error reported anywhere.

Leaflet bakes its URL template at layer creation and throws while
building a tile URL if a template variable is undefined. So the raster
layer takes the token as an option Leaflet substitutes per request, which
also means a refreshed token is picked up without recreating the layer,
and an absent one is empty rather than missing: the tiles 403 and the
markers still draw.

The asset pipeline shrinks to generating two styles. Glyphs and sprites
come from the proxy, so the 48 MB build-time download, the digest
verification, the glyph range filtering and the bold-range guard are all
gone, along with 5.4 MB from the wheel. `localIdeographFontFamily` goes
too: the complete glyph set is reachable now, so CJK renders in Noto
rather than a device font.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-27 18:14:59 +02:00
Paul Bottein e3b9c6e143 Fix the History timeline labels and tooltip placement (#53843)
* Draw History timeline names in a label column again

* Keep the timeline tooltip level with the hovered row
2026-08-27 17:36:06 +02:00
Bram Kragten 8f73718a35 Bumped version to 20260826.1 2026-08-27 17:07:22 +02:00
Paul Bottein 4bf2acdb43 Show serial port info in a bottom sheet on mobile (#53839) 2026-08-27 17:06:48 +02:00
Shay Redmond f622e5eeb9 Small copy improvements for Cloud feature list (#53833) 2026-08-27 17:06:47 +02:00
Paul Bottein 595068597f Keep the row config when changing a device automation type (#53832) 2026-08-27 17:06:46 +02:00
Aidan Timson c708f35ab6 Fix MQTT subscribe controls layout (#53831) 2026-08-27 17:06:45 +02:00
Aidan Timson 205874c800 Show app icons for serial port consumers (#53827) 2026-08-27 17:06:44 +02:00
Petar Petrov 47ddcbe2e5 Fix editor state leaking when switching automations, scripts, or scenes (#53826)
* Fix editor state leaking when switching automations, scripts, or scenes

Recreate the page when the item id in the route changes so YAML mode,
undo history, and scene live state cannot carry over to the next item.

* Declare itemId on editor routes instead of guessing from the path

Path-shape matching remounted nested config routers, Lovelace, and
developer tools. Recreate only where edit/show routes opt in.

* Do not restore scene live states when the editor is torn down

A remounted editor starts in review; disconnect only needs to drop
the subscription, not undo device changes from live mode.

* Use the normal create path when remounting itemId pages

Clear the current page instead of calling _createPanel directly so
load and the loading screen still run. Drop the redundant cache delete.

* Fix dialog-form tests leaking focus restore after jsdom teardown

Nested submit/cancel schedules a nextRender callback that ran after
Vitest tore down HTMLElement, failing CI with an unhandled rejection.
2026-08-27 17:06:43 +02:00
Petar Petrov c43b8bfbe0 Do not show empty Grid legend item on energy usage graph (#53822)
Do not add empty combined Grid series on energy usage graph
2026-08-27 17:06:41 +02:00
Bram KragtenandClaude Opus 5 e349b00b15 Replace CARTO raster tiles with OpenStreetMap vector tiles (#53816)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-08-27 17:06:40 +02:00
Paul Bottein 0bb8bdc98a Clarify the replaced device state in pickers and target rows (#53807) 2026-08-27 17:06:39 +02:00
Petar Petrov bbc5385843 Fix more-info dialog rewriting the URL after navigation (#53806) 2026-08-27 17:06:37 +02:00
Paul Bottein 43dc5651d3 Keep the automation config when replacing a device in device automations (#53805) 2026-08-27 17:06:36 +02:00
Aidan Timson 18dcf7abc0 Refine entity details context section (#53797) 2026-08-27 17:06:35 +02:00
221f184cb1 Remove no-op User-Agent header from Nominatim requests (#53834)
* Remove no-op User-Agent header from Nominatim requests

`User-Agent` is a forbidden header name for browser fetch/XHR, so the
option passed to both Nominatim calls was silently dropped and the
browser's own User-Agent went out instead. Verified in Chromium against
a local echo server: the header never took effect, the outgoing UA was
the browser default, and zero preflights were received — had it been
applied, the non-safelisted header would have forced an OPTIONS
preflight that Nominatim does not answer.

Identification towards Nominatim is done by the `email` query parameter
both calls already send, which is what the Nominatim usage policy
accepts, so nothing changes on the wire. Drop the misleading dead code
and note in a comment why the header cannot be set from a browser.

`hass` is still needed by both functions for `hass.locale.language`, so
the signatures are unchanged.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Apply suggestions from code review

Co-authored-by: Maarten Lakerveld <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Maarten Lakerveld <[email protected]>
Co-authored-by: Maarten Lakerveld <[email protected]>
2026-08-27 15:04:28 +00:00
Petar Petrov 27cbbdb83f Fix editor state leaking when switching automations, scripts, or scenes (#53826)
* Fix editor state leaking when switching automations, scripts, or scenes

Recreate the page when the item id in the route changes so YAML mode,
undo history, and scene live state cannot carry over to the next item.

* Declare itemId on editor routes instead of guessing from the path

Path-shape matching remounted nested config routers, Lovelace, and
developer tools. Recreate only where edit/show routes opt in.

* Do not restore scene live states when the editor is torn down

A remounted editor starts in review; disconnect only needs to drop
the subscription, not undo device changes from live mode.

* Use the normal create path when remounting itemId pages

Clear the current page instead of calling _createPanel directly so
load and the loading screen still run. Drop the redundant cache delete.

* Fix dialog-form tests leaking focus restore after jsdom teardown

Nested submit/cancel schedules a nextRender callback that ran after
Vitest tore down HTMLElement, failing CI with an unhandled rejection.
2026-08-27 17:04:18 +02:00
Bram KragtenandClaude Opus 5 337e88560e Replace CARTO raster tiles with OpenStreetMap vector tiles (#53816)
Co-authored-by: Claude Opus 5 <[email protected]>
2026-08-27 16:35:43 +02:00
Paul Bottein 9c96c56558 Show serial port info in a bottom sheet on mobile (#53839) 2026-08-27 16:33:47 +02:00
Aidan Timson 27e0c4492c Refine entity details context section (#53797) 2026-08-27 15:21:26 +01:00
Paul Bottein 80889c3cea Keep the row config when changing a device automation type (#53832) 2026-08-27 16:16:25 +02:00
Paul Bottein cbbaf51e75 Keep the automation config when replacing a device in device automations (#53805) 2026-08-27 16:14:47 +02:00
Petar Petrov 9778a54305 Stop a percentage Y axis expanding past 100 (#53824)
A percentage has a real ceiling the way zero is a real floor, but the gap that
keeps series off the plot edges did not know that: a battery reading 20-100%
rounded out to an axis labelled up to 120%, and one sitting flat at 100% — a
device left on the charger — reached 160%.

Recognise the unit at the two line-chart call sites and hold the axis at 100,
mirroring the existing zero clamp. Only while the data stays under it, since
power factor is also reported in % and is signed.
2026-08-27 17:14:04 +03:00
Petar Petrov b9125537c0 Show Z-Wave neighbor connections in the network visualization (#53677)
* Show Z-Wave neighbor connections in the network visualization

* Fetch neighbors in bulk and hide them behind a toggle

* Warn that loading neighbor data turns off the adapter
2026-08-27 15:59:52 +03:00
Petar Petrov fd6017a963 Guarantee a Y-axis gap on history and statistics charts (#53821)
* Guarantee a Y-axis gap on history and statistics charts

ECharts floors the axis minimum and ceils the maximum to a tick multiple,
so quantized states that land exactly on a tick leave the data flush against
the plot edge — which collapses the climate and humidifier action bands to
zero height, since an area fill is based at the axis minimum.

Widen the auto-scaled extent by a fraction of the span so that same rounding
always has something to round away, keeping the axis anchored at zero for
single-signed data and preserving the window ECharts gives a constant series.

* Widen the Y-axis gap threshold to 2% of the span

A nudge only large enough to break an exact tie left the gap unchanged
whenever the data sat just above a tick rather than on it, so a chart could
still render with a hairline of headroom.

Because ECharts rounds out to a whole tick afterwards, this constant does not
set the size of the resulting gap — it decides which axes count as too flat to
leave alone. At 2% the worst case over the tick cycle goes from nothing to
around 3% of the plot, while every measured chart keeps the framing it had.
2026-08-27 15:57:50 +03:00
Shay Redmond e0f5d6d6b3 Small copy improvements for Cloud feature list (#53833) 2026-08-27 08:54:57 -04:00
noksideandPetar Petrov 193ab1b424 Deduplicate in-flight requests (#53786)
* Deduplicate in-flight requests

* Use callWS for in-flight request ownership

* Avoid mutating shared request results

* Deep-freeze shared in-flight request results

Centralize immutability in shareInFlightRequest using deep-freeze so
callers do not need readonly types on shared API shapes.

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-08-27 12:48:59 +00:00
Maarten Lakerveld 4a3b6db411 Make digital clock card font size themeable (#53808)
The digital clock hardcoded 1.5rem/3rem/4rem, which ignored
--ha-font-size-scale and could not be overridden from a theme. Use
--ha-clock-card-digital-font-size-{small,medium,large} with defaults based
on the font size scale (24px/48px/64px).

Fixes #51602
2026-08-27 12:05:11 +00:00
Aidan Timson 46271d0435 Show app icons for serial port consumers (#53827) 2026-08-27 13:26:19 +02:00
Aidan Timson d4bc02c86b Fix MQTT subscribe controls layout (#53831) 2026-08-27 13:25:40 +02:00
Marcin BauerandClaude Opus 5 a12ae9a8ed Expand tree nodes on double-click in the automation editor (#53830)
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-27 11:52:25 +01:00
Maarten Lakerveld 6095787294 Derive energy CSV time columns from exported rows (#53828)
The CSV header used the timestamps of every statistic in the energy
collection. Since the power sources chart (#27501) that includes the
power statistics, which are fetched at a finer period than the energy
statistics (hourly for a month view, where energy is daily), adding
empty hourly columns between the daily energy values. Collect the rows
first and build the time columns only from the data that is actually
exported.

Fixes #52381
2026-08-27 12:51:33 +02:00
Petar Petrov 127702b96f Fix more-info dialog rewriting the URL after navigation (#53806) 2026-08-27 09:51:29 +01:00
Petar Petrov 56a6c5d9fb Do not show empty Grid legend item on energy usage graph (#53822)
Do not add empty combined Grid series on energy usage graph
2026-08-27 11:49:22 +03:00
Petar Petrov 3b686dc3b9 Prompt for unsaved changes on programmatic navigation (#53804)
* Prompt for unsaved changes on programmatic navigation

* Tidy unsaved-changes guard tests

* Drop navigations superseded while an unsaved-changes prompt is open
2026-08-27 11:09:09 +03:00
Aidan Timson c5e8dea750 Fix centering for no history found in graph card feature (#53795)
* Fix centering for no history found in graph card feature

* Drop classMap
2026-08-27 11:08:18 +03:00
renovate[bot] 29cd46eb9e Update dependency minify-literals to v2.2.0 (#53812)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-26 20:24:56 +02:00
Paul Bottein 92b3081896 Clarify the replaced device state in pickers and target rows (#53807) 2026-08-26 19:48:52 +02:00
Shay Redmond 527319ab5e Remove the unnecessary spacing around the ha-alert components (#53799)
Remove the unnecessary spacing around the subscription ha-alert components
2026-08-26 14:01:38 +00:00
Maarten Lakerveld 8d3877c388 Fix Expose page crash when filtered by assistant (#53803)
The assistants URL filter can skip creating a row for entities that are
only exposed via Cloud (Alexa/Google) manual config, but the sortable key
was still assigned to the missing row, throwing a TypeError and leaving
the page on an infinite spinner. Only assign the key when the row exists.

Fixes #53689
2026-08-26 13:43:50 +00:00
Aidan Timson 66b9fbd4bf Fix view background config reference (#53802) 2026-08-26 15:40:31 +02:00
Bram Kragten a406abfdcd Merge branch 'rc' into dev 2026-08-26 14:48:07 +02:00
Bram Kragten fddc6e5506 Bumped version to 20260826.0 2026-08-26 14:47:19 +02:00
Petar Petrov 69518334bb Keep the frame minimum when a gap marker shares the frame (#53580)
The chart data modules push a null y value to break the line where an
entity was unavailable. downSampleLineData read it with Number(), and
Number(null) is 0, which is not NaN, so the isNaN guard did not fire.
The marker then competed as a real value of 0 and won its frame's
minimum slot whenever the readings were positive, discarding the
frame's actual minimum and widening the rendered gap.

Keep markers out of the min/max comparisons entirely and hold at most
one per frame in its own slot. It is emitted, after the frame's values,
only when no kept value follows it: a marker followed by a value in its
own frame is a gap that closed within one frame, which is about one
device pixel wide and too narrow to show. That check runs per frame at
emit time, so the per-point path stays as it was. Keeping every marker
instead would blow up the output on series that are mostly null, such
as the climate heating dataset, which went from 823 to 14525 points
before this was bounded.

Skipping markers before the numeric work also makes gapped series
faster: 16% on a series with a few gaps, 27% on one that is mostly
gaps. Both now have benchmark coverage, which the gap path lacked.

Mean mode no longer averages markers in as zero.
2026-08-26 15:29:12 +03:00
Petar Petrov 7a387004d6 Cache media source resolutions for view backgrounds (#53615)
Cache resolved media source URLs for view backgrounds
2026-08-26 15:28:34 +03:00
Paul Bottein 1e9993785d Add reusable device class picker (#53798) 2026-08-26 13:26:32 +02:00
renovate[bot] 1a3a93e3b9 Update dependency cropperjs to v1.6.3 (#53796) 2026-08-26 11:33:32 +01:00
Jan Bouwhuis c6dd741bb5 Add device class selector (#53672)
* Add sesnor device class selector

* Remove unused constants

* Remove stale test case and import

* Fix CI tests

* Add domain and make selector generic

* Follow up comments

* Use import
2026-08-26 12:23:26 +02:00
Krisjanis Lejejs 24f522b7ae Improve cloud login/sign up pages, add auto login (#53790)
* Improve cloud login/sign up pages, add auto login

* Improve trual button text

* Improve event subscription, fix email wrapping
2026-08-26 05:17:59 -04:00
Petar Petrov 0594229a45 Fix choose-view dialog showing another dashboard's views (#53792)
* Show the selected dashboard's views in the choose-view dialog

* Block the choose-view action while the dashboard config loads
2026-08-26 12:08:06 +03:00
Josef Zweck 615fd58324 Allow cross domain translations for config entry setup errors (#53791) 2026-08-26 09:35:48 +01:00
Paul Bottein fb35194041 Share favorites editor and security entity filter (#53785) 2026-08-26 09:11:48 +03:00
Paul Bottein d4e3ec858e Remove pulse from security dashboard alerts (#53784) 2026-08-26 08:24:31 +03:00
renovate[bot] 6516b8de68 Update dependency @bundle-stats/plugin-webpack-filter to v4.22.3 (#53783)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-25 18:10:10 +02:00
Paul Bottein edb2f98d03 Show targets in automation traces (#53718) 2026-08-25 18:50:04 +03:00
Aidan Timson 5ae95a1ea2 Add favorites to Security dashboard (#53512)
* Add favorites to security dashboard

* Use contexts in favorites editor

* Update src/translations/en.json

Co-authored-by: Paul Bottein <[email protected]>

* Address security favorites review

---------

Co-authored-by: Paul Bottein <[email protected]>
2026-08-25 17:46:03 +02:00
Aidan Timson d0371e506f Add active alerts to Security dashboard (#53031)
* Add security dashboard alerts

* Fix security alerts editor and card defaults

* Use consistent security editor icons

* Fix security dashboard alert state

* Fix lint

* Render security alerts as individual cards

* Use context data in security alerts editor

* Add pulse for alerts

Co-authored-by: Paul Bottein <[email protected]>

* Use explicit cover and lock alert states

* Fix test

* Remove security panel rendering tests

* Use complete states

Co-authored-by: Paul Bottein <[email protected]>

* Remove camera

Co-authored-by: Paul Bottein <[email protected]>

* open state only

Co-authored-by: Paul Bottein <[email protected]>

* Remove security entity filter cache

* Format

* Update security alert visibility tests

---------

Co-authored-by: Paul Bottein <[email protected]>
2026-08-25 17:28:46 +02:00
Paul Bottein 872205c352 Remove template and default-value tests (#53779) 2026-08-25 17:14:00 +03:00
tormazs bf939babfd Fix ha-control-select losing its value when activated by a screen reader (#53777)
The option handlers read the value from ev.target, which is whichever
element the click landed on. Real pointer events are retargeted to the
outer role="radio" element by .option .content { pointer-events: none },
but a screen reader's synthetic activation click is not hit-tested, so it
lands on the inner content element, which has no value.

ev.currentTarget is always the element the listener is bound to, so it
always carries the value.
2026-08-25 15:39:05 +03:00
nokside d41b21b9d6 Fix timeCachePromiseFunc cache handling (#53773)
Fix promise cache result handling
2026-08-25 15:31:08 +03:00
Jan Bouwhuis 7e495f38d2 Expand sensor entity constants and add device classes (#53748)
* Expand sensor entity constants and add device classes

* Updated constants

* Fix typo

* Fix name

* Restore part original generated script comment

* Add convertible units and fix null type

* Fix type

* Update constants

* Fix import SENSOR_NUMERIC_DEVICE_CLASSES
2026-08-25 14:28:13 +02:00
Petar Petrov 5cff0cb4c9 Focus nested form-dialog fields when a nested level is pushed (#53757)
* Focus nested form-dialog fields after a nested level is pushed.

Host focus on ha-form does not pierce selector shadows, so keyboard
focus stayed on the opener instead of the nested controls.

* Simplify nested form-dialog focus and fix CI types.

Wait one render and focus the first real control instead of waiting for
custom-element upgrades or walking a general focusable tree.

* Wait for lazy selector upgrades before nested form focus.

nextRender is not enough on a cold selector chunk; wait for undefined
custom elements so nested focus does not depend on network timing.
2026-08-25 15:14:33 +03:00
Paul Bottein dbe2e2c079 Reflect the active filters in the target picker counts (#53716) 2026-08-25 13:53:26 +02:00
Paul Bottein e22b770252 Clarify when agents should add tests (#53775) 2026-08-25 12:28:47 +01:00
Paul Bottein fd388d99bf Show area and disable pulse by default in alert card (#53774) 2026-08-25 12:17:52 +01:00
Aidan Timson f9bfc66d5b Add alert card (#53758)
* Add security alerts card

* Fix security alert cards

* Validate security alert card configuration

* Keep a single generic alert card

* Use entity context in alert card
2026-08-25 10:45:53 +01:00
renovate[bot] c4ab017aed Update dependency @rspack/dev-server to v2.2.1 (#53772) 2026-08-25 09:27:59 +01:00
Paul Bottein e22ef3e1f3 Merge the domain and device class filters into a type filter (#53710)
* Merge the domain and device class filters into a type filter

* Only scan the entities while the type filter panel is open
2026-08-25 08:12:00 +02:00
renovate[bot] 7a3764790b Update dependency @types/luxon to v3.7.5 (#53770)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-25 08:40:20 +03:00
karwosts c499c2e030 Fix more-info setting dirty state tracking (#53762) 2026-08-25 07:02:41 +02:00
Raman GuptaandClaude Opus 5 13ec52ddbe Fix Z-Wave add node security strategy selection not sticking (#53769)
The security strategy step rendered ha-form with a data object built
from a @state field that was never assigned, so the form was always
bound to an undefined strategy. ha-form's own optimistic data update
made the radio look selected after a click, but the next re-render of
the step (triggered by any hass update) re-committed the undefined
value and cleared the selection.

Make the step a controlled component: the dialog already owns
_inclusionStrategy and resets it when navigating back, so pass it down
as a property instead of keeping a second, unused copy in the child.


Claude-Session: https://claude.ai/code/session_011MGgDoAUxzf9KBexn6uiPc

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-25 07:01:47 +02:00
wollewandkarwosts d288cfd30a Add supported_speeds parameter for cover movement actions (#53572)
add supported_speeds for cover service actions

Co-authored-by: karwosts <[email protected]>
2026-08-24 20:10:19 +02:00
karwosts 643e8934b4 Allow media selector to optionally select a media directory (#27873)
Allow media browser to select a directory
2026-08-24 20:05:21 +02:00
renovate[bot] 9f3ca39738 Update dependency eslint to v10.9.0 (#53765)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-24 17:03:14 +03:00
renovate[bot] 8cee5155e6 Update dependency @rsdoctor/rspack-plugin to v1.6.3 (#53761) 2026-08-24 14:37:06 +01:00
Paul Bottein 15341a0aad Show climate summary card with only temperature sensors (#53760) 2026-08-24 14:51:04 +02:00
Petar Petrov 9f8a2253ac Add keyboard and screen reader navigation to the energy device charts (#53754)
* Sonify value-first charts now that the extension reads them

* Announce device names instead of statistic ids in sonified charts
2026-08-24 14:45:43 +02:00
Maarten Lakerveld 97df5a5bf0 Key more-info details memoize on attribute name formatter (#53755)
_getDetailData caches on stateObj alone while formatting via this.hass,
so results go stale when translation-based format functions reload (e.g.
backend translations finishing after open, or a language switch) until
the entity next changes state. Pass hass.formatEntityAttributeName as an
extra memoize argument so the cache invalidates when format functions
are recreated.
2026-08-24 11:59:22 +02:00
Petar Petrov 19cd06bb8c Fix energy period rollover overnight and in the first hour (#53717)
* Fix energy dashboard staying on yesterday after midnight.

* Catch up the energy live day before subscribe fetches.

* Keep energy day math in the server timezone so DST cannot skip a live day.

Browser-local addDays can jump a calendar day on a 23-hour DST fallback.
Assert against tz-internal endOfDay/addDays under Europe/Berlin so UTC CI
catches a regression, and prove the 01:00 timer and catch-up refresh fetch
the live day rather than only updating collection.start.

* Don't follow the live day from midnightRollover alone.

A stored non-today preset would otherwise be discarded on the first subscribe. Drop tautological UTC DST tests that cannot fail.
2026-08-24 10:16:00 +02:00
nokside fcca87b368 Fix editing nested multiple object selector items (#53709)
* Fix editing nested multiple object selectors

* Fix nested form dialog close and focus restoration

Cancel all pending nested form levels when the physical dialog closes, and restore focus to the opener after nested submit or cancel.

Add regression coverage for both behaviors.

* Fix selector object test types
2026-08-24 09:41:58 +03:00
puddly 2eb3b025d8 Add a serial panel (#53699)
* WIP: Initial attempt

* Arrange into sections

* Clean up UI

* Add descriptions

* Align with Core changes

* Address review feedback and add an info dialog

* Combine websocket commands into one

* Drop unnecessary info dialog rows

* Add a status bar

* Expose `resolved_device` as well
2026-08-24 06:58:23 +02:00
DawnWang 43628c5d69 Fix error badge creation on cold load (#53752) 2026-08-24 04:53:53 +00:00
renovate[bot] 0f52c00821 Update dependency echarts-extension-chart2music to v0.1.1 (#53753)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-24 06:48:24 +02:00
dependabot[bot] 20f70cde7a Bump the codeql-action group across 1 directory with 2 updates (#53744)
Bumps the codeql-action group with 2 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.6 to 4.37.7
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd)

Updates `github/codeql-action/analyze` from 4.37.6 to 4.37.7
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-23 09:55:54 +02:00
renovate[bot] b38d7bcb26 Update dependency hls.js to v1.7.1 (#53741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-22 22:20:30 +02:00
Petar Petrov 0572d71699 Replace a remembered yesterday energy period when picking now (#53735) 2026-08-22 17:36:40 +02:00
renovate[bot] bcd13fcaf7 Update vitest monorepo to v4.1.11 (#53732)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-21 21:35:37 +02:00
renovate[bot] 308eac97ee Update dependency marked to v18.0.10 (#53725)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-21 06:37:46 +02:00
Paul Bottein 6da851219d Fix stacked toasts when a dashboard is updated in another session (#53719) 2026-08-20 21:34:08 +02:00
renovate[bot] 970be43c3d Update dependency intl-messageformat to v11.2.14 (#53722)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-20 21:01:27 +02:00
karwosts 8bb718a486 Cleanup some attributes code (#53713) 2026-08-20 20:54:59 +02:00
Josef Zweck 0e0bc389f8 Show result of action for button presses (#53645)
* Show result of action on button feature

* Add button entity

* Add to button entities

* add to tile icon

* Delay for spinner

* Remove result indicator from tile icon
2026-08-20 16:49:55 +02:00
Petar Petrov 70a482e0ed Add keyboard and screen reader navigation to charts (#53533)
* Add keyboard and screen reader navigation to charts via Chart2Music

* Mark charts as busy while the sonification chunk loads

* Skip chart sonification when there is nothing to navigate

* Drop the direct chart2music dependency

* Exclude legend-hidden series when judging chart sonifiability

* Push statistics chart times as numbers so sonification reads real dates
2026-08-20 16:55:11 +03:00
Maarten Lakerveld 5a0db4a796 Show Assist greeting in the assistant's language (#53707)
The greeting sits in the assistant's chat bubble, so render it in the pipeline's language instead of the interface language. Falls back to the interface language when no translation is available (issue #53703).
2026-08-20 12:49:40 +02:00
622f3e97e6 Add RepairsFlow as a next_flow from a RepairsFlow (#51744)
* fix flowType in config subentry flows/next_flow

* suggested changes

* Repair Flow Next Flow Repair

* Add repair flow support a new repair flow as the next_flow

* Add support for the next_flow being another repair flow

* fix lint errors

* Reviewer response and fix linter error

* Revert to generics to avoid multiple casts

* Move show-dialog-repair-flows to dialogs

* Update src/dialogs/config-flow/dialog-data-entry-flow.ts

* Apply suggestions from code review

* Apply suggestion from @MindFreeze

* format

---------

Co-authored-by: Petar Petrov <[email protected]>
Co-authored-by: Paulus Schoutsen <[email protected]>
2026-08-20 11:24:23 +03:00
renovate[bot] 3091362040 Update dependency @html-eslint/eslint-plugin to v0.65.0 (#53714)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-20 11:08:20 +03:00
Paul Bottein 3c7560a4e2 Add indeterminate and controlled selection to lists (#53706) 2026-08-19 23:26:40 +02:00
Petar PetrovandSimon Lamon a9e178cb0e Show per-mount storage usage on the storage page (#53683)
* Show per-mount storage usage on the storage page

Each active mount now fetches its own usage from the Supervisor and renders
a bar with a used-of-total line under its address. The requests are not
awaited, so a slow or unreachable server cannot hold up the rows, and a
failed one simply leaves that row without usage.

fetchHostDisksUsage now takes a disk and an optional max_depth. The data
disk callers keep their depth of 3; mounts send no depth at all, since
walking one costs a round trip per directory and the Supervisor already
has a sensible per-target default.

* Vertically align ha-bar

---------

Co-authored-by: Simon Lamon <[email protected]>
2026-08-19 21:18:37 +02:00
23b83fbd27 Update browserlist (#53691)
* update browserlist for better packaging

* add results of bundle changes

* update browserlist, budgets and ecma terser rewrite level

* remove results.md used for testing

* Apply suggestion from @silamon

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: Simon Lamon <[email protected]>
2026-08-19 18:45:22 +00:00
Marcin BauerandClaude Opus 5 62849e2630 Fix outlined button border colors (#53704)
The brand outline pointed at a token that doesn't exist, so CSS fell back
to the neutral border and brand outlined buttons drew a gray ring.

Disabled outlined buttons only reset their background and label, keeping
the variant-coloured border.

Also add outlined to the gallery: it has always been a valid appearance
but was missing from the documented list the gallery grid is built from,
which is why both bugs went unnoticed.

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-08-19 20:37:09 +02:00
renovate[bot] aa3e11f6e9 Update CodeMirror (#53705)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-19 20:34:12 +02:00
Paul BotteinandPetar Petrov 82ed13b7fc Fix filter pane expand animation and use a bottom sheet in narrow mode (#53684)
* Fix filter pane expand animation and use a bottom sheet in narrow mode

* Update src/common/controllers/filter-panel-controller.ts

Co-authored-by: Petar Petrov <[email protected]>

* Apply suggestion from @MindFreeze

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-08-19 16:18:40 +03:00
Petar Petrov 089592e7e3 Ignore stale History statistics fetches after the selection changes (#53700)
* Ignore stale History statistics fetches after the selection changes.

A slower fetchStatistics call could finish after a newer sources or date-range request and replace the charts the user is looking at.

* Update src/panels/history/ha-panel-history.ts

---------

Co-authored-by: Paul Bottein <[email protected]>
2026-08-19 12:00:43 +02:00
Paul Bottein 4bc9b2be7b Remove the unused compact mode from the target picker (#53685) 2026-08-19 11:48:43 +03:00
renovate[bot] 1778b7abff Update dependency barcode-detector to v3.2.2 (#53702)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-19 11:39:58 +03:00
90567a491a Redesign History and Activity filtering into a sources pane (#53630)
* Redesign History and Activity filtering into a sources pane

Give both panels the toolbar + left pane layout of the data tables, and
merge target picking and filtering into one "Sources" surface, per the UX
discussion.

- ha-filter-pane: pane on wide screens, bottom sheet on narrow ones,
  mirroring the filter pane of hass-tabs-subpage-data-table
- ha-sources-picker: target picker plus domain, device class and
  integration filters, shared by both panels
- ha-filter-device-classes: new filter panel, labelled with the backend
  device class names
- ha-filter-pane-chip and ha-empty-state: the chip with a filter count
  badge and the centered placeholder both panels need
- ha-date-range-nav: the date range picker as one pill with previous and
  next steppers, for the toolbar
- History draws timeline names above their bar (inside-labels), which
  gives long names the full width
- Activity keeps a floating date header while scrolling, and reset moved
  into the overflow menu next to refresh and download
- Drop the now unused compact and add-on-top modes of ha-target-picker,
  including ha-target-picker-value-chip
- Right-align the clear button in the domains filter header, matching the
  other filter panels

Co-Authored-By: Claude Opus 5 <[email protected]>

* Remove dead code breaking the type check

* Fix stuck loading state when the selection resolves to no entity

* Keep the target picker out of the redesign

* Remember the source filters across visits

* Truncate timeline names that do not fit the plot

* Show device class icons in the sources filter

* Open the sources pane by default on wide screens

* Show the entity count in the sources chip

* Count the same entities in the sources chip and the target picker

* Fix sources resolution, fetching and filter badge in History and Activity

* Update src/panels/history/ha-panel-history.ts

Co-authored-by: Petar Petrov <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
Co-authored-by: Paul Bottein <[email protected]>
Co-authored-by: Petar Petrov <[email protected]>
2026-08-19 11:31:10 +03:00
Paul Bottein 409e2b315f Skip entities assigned to another area when resolving area targets (#53693) 2026-08-19 08:46:45 +03:00
Petar Petrov eb1f8c1fab Add Matter network topology visualization page (#53247)
* Add Matter network topology visualization page

* Add central Home Assistant node to Matter network graph

* Refine Matter graph HA node: theme-aware memoization, drop dead branch

* Render Matter 'unknown' link strength as a present, neutral link

* Pass devices to getDeviceArea so bridged nodes inherit their area

* Distinguish position-unknown Matter graph anchors and name border routers

Anchors to a hubless component only mean the node is reachable, so draw
them dotted instead of reusing the solid line that marks a real path
through a border router or access point.

Also prefer the border router mDNS host name over vendor and model,
which several vendors report identically on every unit.

* Name Matter access points by SSID and show their radio address

Access points were labelled with a BSSID, and the same address was
repeated as the node context. Prefer the SSID for the label and keep the
radio address as context only when it differs, so the radios of one mesh
stay distinguishable without repeating the label.

Falls back to today's BSSID against servers that do not send an SSID.

* Colour Matter graph links by transport and float unknown neighbours

Unknown Thread neighbours are not commissioned on our fabric, so Home
Assistant has no operational path to them. A group made only of unknown
devices no longer draws an anchor to the Home Assistant node and floats
instead of claiming a connection that does not exist.

Link colour now encodes the transport, purple for Thread and pink for
Wi-Fi, with the signal level left on the line width and spelled out in
the tooltip. A dead link keeps the disabled colour, which is the only
thing separating it from a healthy weak one now that both are width 1.
The edge tooltip names the network, since the graph legend describes
nodes only and cannot carry a link entry.

* Float Matter nodes whose route to Home Assistant is unknown

Only border routers and access points get an edge to the Home Assistant
node, because only those are a path we can actually see. A node in a
group with neither was previously anchored to Home Assistant with a
dotted line, which reads as a physical connection that was never
observed.

Removing the anchor makes the component walk that picked a
representative dead code, so it goes too.

* Match the dashboard's line semantics for Matter graph links

Dash an edge whose endpoint is inferred rather than commissioned, or is
offline, which is the same pair of conditions the matter.js dashboard
dashes on. Stop drawing a link whose every direction is dead: the
summary strength is the strongest direction, so none means a stale
neighbour entry, and the dashboard never draws one either.

That also retires the grey dead-link colour, since such links no longer
reach the graph.

* Carry the transport colour onto the Home Assistant edges

An edge from Home Assistant to a hub now takes the colour of the network
behind it, so one transport reads as one colour the whole way back
instead of changing hue at the hub.

Wi-Fi moves from pink to orange: pink sat close to the error red used
for offline nodes, while orange is far from both that red and the Thread
purple.

* Give the Wi-Fi access point node its transport colour

The access point wore indigo while everything else on its network was
orange. Deriving the category colour from the same helper the links use
keeps a hub and its links one hue, and gives the Wi-Fi colour a legend
entry it did not have before.

* Give the border router node its transport colour too

Both hub categories now derive their colour from the same helper as the
links, so a network is one hue from Home Assistant through its hub to
the devices, and each legend swatch keys the links of that transport.

The border router also gains contrast: the shared Thread purple is
legible on both the light and the dark card background, where the deep
purple it replaces was not.
2026-08-19 08:02:49 +03:00
Paul Bottein 29cf30fc1a Fix check for updates toasts stacking (#53696) 2026-08-19 06:45:52 +02:00
renovate[bot] f88535c446 Lock file maintenance (#53698)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-19 06:43:45 +02:00
Jan Bouwhuis b9fd639bb7 Add improved mqtt panel to config section (#53653)
* Add mqtt config dashboard shortcut

* Improve MQTT subscribe panel formatting and add copy button

* Standardize MQTT options flow button to a nav card style

* Refactor MQTT dashboard

* Improve style

* Add link to broker connection settings

* Test the effect of not exporting the SVG data

* Move MQTT svg icon to separate file
2026-08-18 19:00:28 +02:00
Paul Bottein 2925dfc14e Show entity name in template autocomplete info panel (#53695) 2026-08-18 18:54:03 +02:00
Yosi Levy bb7ec34532 Addons RTL fix (#53692)
Addon RTL fix
2026-08-18 17:01:41 +02:00
Stefan AgnerandClaude Fable 5 89015bc135 Fix backup progress segment order to match backend execution order (#53652)
* Fix backup progress segment order to match backend execution order

The segmented backup progress bar showed Apps, Media, Home Assistant,
but Supervisor backs up Home Assistant first since 2024 (supervisor#5203),
then add-ons, then folders. The Home Assistant segment activated first
while Apps/Media incorrectly showed as completed, and the bar regressed
once the apps stage started.

Also move the await-addon-restart stages into the last creation group,
since Supervisor awaits add-on restarts after the backup file is
finished, keeping the progress bar monotonic.

Co-Authored-By: Claude Fable 5 <[email protected]>

* Keep await restart stages out of MEDIA_STAGES

Give them their own constant and merge them into the last creation
group only where the ordering constraint applies.

Co-Authored-By: Claude Fable 5 <[email protected]>

* Group backup setup stages with the first progress segment

addon_repositories/app_repositories (and docker_config on older
Supervisors) are emitted while the backup is initialized, before the
home_assistant stage, so grouping them with the apps segment made the
bar regress at the start of a backup.

Co-Authored-By: Claude Fable 5 <[email protected]>

---------

Co-authored-by: Claude Fable 5 <[email protected]>
2026-08-18 13:52:07 +03:00
Petar Petrov 343f1e840a Fix Z-Wave network visualization showing wrong route edges (#53676)
Fix repeater mapping and route direction in Z-Wave network graph
2026-08-18 08:07:24 +03:00
G Johansson 1369f80eb0 Allow using description in create_entry for repair flows (#53671) 2026-08-17 22:08:57 +02:00
Paul Bottein cd52f7b193 Fix the clear button alignment in the domains filter (#53687) 2026-08-17 17:47:35 +00:00
renovate[bot] 86dea86b6c Update dependency js-yaml to v5.3.0 (#53679)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-17 17:16:53 +00:00
Paul Bottein 04035016b0 Extract the data table filter chip into ha-filter-pane-chip (#53682) 2026-08-17 19:16:46 +02:00
Petar Petrov 52b0b46991 Group sankey devices by count as well as by value (#53680)
* Group sankey devices by count as well as by value

The 0.1%-of-total value threshold only catches devices that are a
negligible share of the home total. A breaker panel with dozens of
similar-sized circuit clamps sits entirely above it, so nothing groups and
every node collapses toward the 1px minimum with labels shrinking to match.

Cap the number of named children per parent too, defaulting to 20 (the
readable capacity of the default 400px card). Over-cap devices are grouped
into the same per-parent "Other" node the value threshold already produces,
so the flow arithmetic is unchanged, and the cap is configurable per card
via max_devices.

* Clarify the max_devices label is per upstream device, not per floor or area

* Make max_devices budget named devices, not nodes

A cap of 20 rendered 19 devices because a slot was reserved for the Other
node, and a cap of 1 rendered none. The option now means what its name and
its namesake on the devices graph mean: at most this many devices are shown
by name, with Other as overhead on top.

* Extract the sankey device cap into findDevicesOverCap

Moves the count-cap logic out of buildSankeyDeviceNodes into an exported
function that takes the graph it needs, so it can be unit tested directly,
and trims the commentary to the two non-obvious rules (why the whole subtree
is grouped, and why at least two devices are).
2026-08-17 19:14:48 +02:00
Stefan AgnerandClaude Fable 5 d5389b5bef Fall back to option key for untranslated repair menu options (#53681)
Repair fix flows build their menu from the suggestions the backend
reports. A suggestion this frontend has no translation for yet (e.g. a
newer Supervisor offering a new repair suggestion) rendered as an
empty, unlabeled menu entry. Show the raw option key instead, matching
the fallback the form step header already uses.

Co-authored-by: Claude Fable 5 <[email protected]>
2026-08-17 15:23:02 +02:00
Logan RosenandCopilot App f828c636a2 Fix Energy configuration back navigation (#53574)
* Fix Energy configuration back navigation

Co-authored-by: Copilot App <[email protected]>

* Align app E2E navigation with production

Co-authored-by: Copilot App <[email protected]>

---------

Co-authored-by: Copilot App <[email protected]>
2026-08-17 12:45:08 +03:00
Petar Petrov e91337b320 Log console error when a dashboard resource fails to load (#53675)
* Log console error when a dashboard resource fails to load

* Include the rejection reason in the resource load error
2026-08-17 10:04:51 +02:00
karwosts 8ab7c118a9 Fix custom weather icons (#53667) 2026-08-17 06:52:16 +02:00
karwosts 0eafb1f4b4 Add themes to yaml reload menu (#53673) 2026-08-17 06:03:12 +02:00
neyzandkarwosts 9a7722a02e Remove weather card pointer cursor when it has no action (#53654)
* Remove weather card pointer cursor when it has no action

* use hasAnyAction helper

---------

Co-authored-by: karwosts <[email protected]>
2026-08-16 09:38:05 -07:00
renovate[bot] 3e184eeb39 Update dependency @rspack/core to v2.1.10 (#53663)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-16 12:37:16 +02:00
renovate[bot] 61be4e2952 Update dependency @rsdoctor/rspack-plugin to v1.6.2 (#53662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-16 12:13:08 +02:00
Paul Bottein 315cf97e56 Prevent the sidebar from scrolling the dashboard (#53644) 2026-08-16 06:27:47 +00:00
karwosts 771a8aa4c9 Fix negative button of duration selector (#53646) 2026-08-16 06:27:17 +00:00
G JohanssonandSimon Lamon d9aa649854 Remove deprecated battery props from vacuum (#53005)
Co-authored-by: Simon Lamon <[email protected]>
2026-08-16 06:26:54 +00:00
karwostsandSimon Lamon 7a087cd6d0 Ability to link a person to an existing user (#53550)
* Support linking a person to an existing user

* Don't delete preexisting user on cancel submit

* retry ci

* Don't show choice when no floating users exist

* collapse to single dialog

---------

Co-authored-by: Simon Lamon <[email protected]>
2026-08-16 06:25:03 +00:00
renovate[bot] 32a30468bb Update dependency globals to v17.10.0 (#53647)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-16 06:24:56 +00:00
karwosts 0ace3cedfb Add disabled to button group (#53651) 2026-08-16 06:24:33 +00:00
karwosts aba7478e26 Fix choose selector minor issues (#53648) 2026-08-16 06:24:28 +00:00
renovate[bot] c8b2e5160a Update dependency hls.js to v1.6.18 (#53649)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-16 06:21:52 +00:00
dependabot[bot] 4c46ca0918 Bump the codeql-action group across 1 directory with 2 updates (#53661)
Bumps the codeql-action group with 2 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

Updates `github/codeql-action/analyze` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: codeql-action
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-16 06:20:49 +00:00
Logan RosenandCopilot App 0483106f61 Restore bundle size budget headroom (#53659)
Co-authored-by: Copilot App <[email protected]>
2026-08-16 08:16:29 +02:00
Paul Bottein 7e0c572f69 Replace automation state color with a badge (#53627)
* Replace state color with a badge in automation picker

* Fix data table spacing and text truncation on mobile
2026-08-14 15:31:14 +02:00
renovate[bot] e4438a20cb Update dependency @rspack/core to v2.1.9 (#53642) 2026-08-14 14:13:06 +01:00
Aidan Timson ec418498a7 Make date picker navigation arrows themeable (#53639) 2026-08-14 16:05:46 +03:00
8122baca00 Add more deep links to more-info dialogs (#53628)
* Add deep links to more-info dialogs

* Fix

* Preserve existing URL hash in createMoreInfoUrl and removeMoreInfoUrl

Co-authored-by: timmo001 <[email protected]>

* Preserve explicit empty hash and move more-info restoration to app owner

Co-authored-by: timmo001 <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-08-14 16:02:58 +03:00
Paul Bottein 79738dd257 Add activity detail dialog (#53362)
* Add activity detail dialog

* Apply review fixes to activity detail dialog

* Resolve previous state from history in logbook detail dialog

* Disable text selection on clickable logbook rows

* Document run discovery as a fallback for missing context ids

* Scope the detail chain to the subject's cause path

* Replace clickable logbook rows with explicit detail affordances

* Show the cause badge on automation and integration rows

* Map scheduled and Home Assistant causes to their trigger icons

* Replace logbook detail affordances with full-width rows

* Frame the activity detail dialog with ha-grouped-list

* Add missing import

* Fix milliseconds placement in activity chain times
2026-08-14 15:57:03 +03:00
Bram Kragten f23c8f0e23 Fix sub device tree indicator (#53638) 2026-08-14 09:18:06 +01:00
Bram Kragten 91c28c2f58 Bumped version to 20260729.7 2026-08-14 09:59:26 +02:00
Paul Bottein 1f299d98e0 Fix clipped focus ring on media player playback buttons (#53632) 2026-08-14 09:58:33 +02:00
Petar Petrov a74926aef6 Fix sensor card graph footers not receiving hass on lazy upgrade (#53576) 2026-08-14 09:58:32 +02:00
Bram Kragten 437a4cedf9 Check for wheel on PyPI simple index instead of JSON API (#53549) 2026-08-14 09:58:31 +02:00
Bram Kragten 55913d7505 Fix panels missing updates (#53548) 2026-08-14 09:58:30 +02:00
Paulus SchoutsenandClaude 0bb654c70c Mock entity ID format WS commands in the demo (#53520)
Co-authored-by: Claude <[email protected]>
2026-08-14 09:58:30 +02:00
Petar Petrov f578cb0526 Guard registry lookups in the target picker item row (#53637) 2026-08-14 09:55:54 +02:00
renovate[bot] 78878897cc Update dependency typescript-eslint to v8.67.0 (#53634)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-14 06:46:42 +02:00
Petar PetrovandSimon Lamon 9472d8ad12 Add device context to energy individual device names (#53603)
Add device context to energy individual device labels

Co-authored-by: Simon Lamon <[email protected]>
2026-08-13 18:52:28 +02:00
Paul Bottein 94cbe4467b Lay out inline features in two columns (#53631)
* Lay out inline features in two columns

* Detect stacked features from the slot

* Rename tile container layout classes

* Rename the below features in the layout helper

* Keep area card features below at full width

* Stretch the area card features below the inline one

* Keep area card features compact outside the compact type

* Revert "Keep area card features compact outside the compact type"

This reverts commit 48268cb4e2.

* Reapply "Keep area card features compact outside the compact type"

This reverts commit e10bb27e2f.

* Keep the inline feature compact on condensed cards
2026-08-13 18:00:47 +03:00
Paul Bottein 043abb69af Keep control select in the tab order without a selection (#53633) 2026-08-13 15:54:59 +01:00
Paul Bottein b6b8fe641f Fix clipped focus ring on media player playback buttons (#53632) 2026-08-13 15:54:49 +01:00
Bram KragtenandClaude Opus 4.8 70bb08b101 Child devices UI (#53619)
* Add child devices UI

Surface child devices throughout the config UI so they read as first-class
devices nested under their parent:

- Device page: a "Sub-devices" card lists a device's children, and a child's
  page shows a "Part of <parent>" link (hardware/model/config-entry are
  already inherited from the parent by the registry resolver).
- Integration page: children are nested and indented under their parent
  device in the config-entry and subentry device lists.
- Device picker: children are ordered and indented under their parent with a
  tree connector, mirroring the area/floor picker.
- Naming: the device picker's secondary label and search now include the
  parent device name for children, so they stay identifiable in flat views.

Follow-up to the child devices data layer (#53617).

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Add child devices to demo and gallery mock data

A power strip parent with two outlet children in the demo device stubs and
the ha-selector gallery demo, so child device rendering (nesting, tree
indentation, parent-context naming, inherited area) can be exercised without
a running backend.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Refine child devices UI and target resolution

Follow-up polish so child devices behave like a normal device everywhere:

- Targets & filters: a parent device qualifies for and resolves to its
  children's entities (getDevices filter, deviceMeetsFilter,
  deviceMeetsTargetSelector, resolveEntityIDs and the target-chip "split into
  entities" expand), matching core's server-side target resolution. Selecting a
  parent excludes its children from the picker.
- Pickers: keep a parent visible when a child matches the search (device and
  target pickers), fix the target picker's nested order (unsorted search +
  recomputed last-child flag), and render the sub-device tree in the target
  picker's device group.
- Area/naming: the area field shows only the (inherited) area again; the parent
  name remains a search term.
- Integration page: correct the tree end connector and align it in narrow mode.
- A parent-disabled child can no longer be enabled from the settings dialog.
- Devices dashboard: show "Part of <parent>" under a sub-device's name and add a
  hidden-by-default, searchable and groupable Parent device column that groups a
  parent together with its children.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Address review on child devices UI

Align target resolution with core and fix picker/table details:

- Only a directly targeted device expands to its child devices. Labels are
  never inherited by children (core's target helper is explicit about this) and
  areas resolve by effective-area membership, so deviceMeetsFilter and
  deviceMeetsTargetSelector evaluate a device's own entities again.
- Add devicesInEffectiveArea, mirroring core's dr.async_entries_for_area: an
  area contains its devices plus children that inherit the area, but not a child
  with a different explicit area. Used for area expansion, area matching and the
  area chip's split action.
- Device picker: add a searchFn that restores the nested parent/child order
  after the fuzzy search and recomputes the last visible child, so a child can
  no longer be ranked above its parent and connectors stay correct.
- Devices dashboard: derive the family group name from the family's parent
  device with the same fallback for parents and children, so an unnamed parent
  cannot end up in a different group than its children.
- Child devices card: pass the device registry so a child shows its inherited
  area.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Fix formatting in device picker row renderer

Reindent the row renderer template after it gained a block body, so Prettier
is satisfied.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Make the child device tree connector span the full row

The connector was a fixed 48px box centred in a taller two-line row, and its
SVG was letterboxed by the default preserveAspectRatio, so the dashed line
stopped short of the row edges and consecutive children never visually
connected.

Let the indicator stretch (preserveAspectRatio="none") and give it the full row
height, so the line runs edge to edge with the elbow at the vertical centre.
non-scaling-stroke keeps the line width and dash pattern identical however far
it is stretched; existing 48x48 usages render unchanged.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-13 17:45:31 +03:00
JulianHockandClaude Opus 5 4259ddee24 Show remaining tile card features below when position is inline (#53310)
* Show remaining tile card features below when position is inline

Previously the tile card silently dropped every feature after the first
one when "features_position" was set to "inline". The first feature is
now rendered next to the name as before, and any additional features are
stacked underneath, the same way they are in "bottom" position.

The tile container gained a "features-bottom" slot for this, and the
card size and grid options now account for the extra rows.

* Add tests for hui-tile-card size and grid options calculations

* Enhance hui-tile-card to support inline feature layout and improve feature counting logic

* reduce vertical gap for inline features

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-08-13 15:45:00 +02:00
6c5ac1ea84 Add background editor to dashboard detail editor (#51644)
* Setup

* Use same slot layout

* Fill tabs

* Move content rendering to dedicated function

* Self review

* Save dashboard details before background

Co-authored-by: timmo001 <[email protected]>

* Protect strategy dashboard config

* Apply dashboard background review fixes

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-08-13 16:27:34 +03:00
Petar Petrov 5224fa2048 Seed selector values when enabling optional service fields (#53629) 2026-08-13 15:27:07 +02:00
Bram KragtenandClaude Opus 4.8 22ca986cce Skip source maps in the gallery build for e2e (#53625)
The gallery build is the only e2e build that still emits source maps: unlike
demo and the e2e test app, `bundle.config.gallery` never accepted
`isTestBuild`, so the production build always used `nosources-source-map` —
even though the artifact is only ever loaded by Playwright.

The e2e run's gallery artifact contains 693 `.map` files (14 MB of a 105 MB
dist); the demo artifact, which already passes `is-test`, contains none.

Thread `isTestBuild` through the gallery config and set `is-test: true` for the
e2e gallery build, so those maps are no longer generated. The design
deployment and preview workflows do not set `IS_TEST`, so they keep their
source maps.

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-13 13:11:23 +03:00
7f8bf69424 List running automations & scripts in restart dialog (#53523)
* List running automations & scripts in restart dialog

* Don't need a new dialog

* Update src/translations/en.json

Co-authored-by: Norbert Rittel <[email protected]>

* Show running automations in quick bar restart confirmation

---------

Co-authored-by: Petar Petrov <[email protected]>
Co-authored-by: Norbert Rittel <[email protected]>
2026-08-13 09:10:23 +00:00
Aidan Timson 92224411e1 Add context to entity details (#53624)
* Add context to entity details

* Include entity context in YAML details

* Remove category from entity details

* Only link integrations with config entries
2026-08-13 12:04:12 +03:00
b52d58eccb Always group updates page entities by integration (#53480)
* Always group updates page entities by integration

Every integration now gets its own card on the updates page, titled with
the integration name, even when it only has a single update entity. The
catch-all Integrations card is removed. The Update all button is only
shown for cards with more than one entity.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DTuGyvS1i7w1B1xEGCEVhs

* Show update button on cards with a single update

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: Paul Bottein <[email protected]>
2026-08-13 08:59:25 +00:00
Bram KragtenandClaude Opus 4.8 a9cc47888a Add child devices to the device registry (#53617)
* Add child devices to the device registry

Child devices arrive over the WebSocket as stripped entries in the flat
config/device_registry/list response (discriminated by the absence of
full-device fields). Resolve them into complete DeviceRegistryEntry
objects at ingestion so hass.devices only ever holds full entries and the
~200 downstream consumers stay unchanged:

- config-entry association comes from the child's own config_entry_id, so
  children still appear under their integration;
- hardware/display fields are inherited from the parent device;
- connections/via_device_id are not inherited.

Adds parent_device_id and the new "device" disabled_by value to the types.

Frontend data layer for home-assistant/core#178666.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Resolve child device effective area in the UI

A child device without an area of its own inherits its parent's area,
mirroring core's async_get_effective_area_id. getDeviceArea now takes the
devices map and falls back to the parent, so children show in the parent's
area everywhere a normal device would: the device dashboard (area column,
grouping and filtering via computeDeviceAreaLabel) and the device page
header.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Address review on child devices data layer

- Discriminate stripped child entries on `connections` (present on every full
  device, never on a stripped child) instead of the deprecated `config_entries`
  compatibility field that core plans to remove.
- Make getDeviceArea's `devices` argument required and update all callers, so a
  child device's effective (inherited) area is resolved consistently everywhere,
  including the device picker's selected-value renderer and the integration
  device rows.
- Lock the enable switch in the device settings dialog when a device is disabled
  by its parent (disabled_by "device"); core ignores enabling a child while its
  parent is disabled.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Inherit the parent device area when resolving entity areas

Extract getDeviceAreaId so an entity on a child device resolves to the child's
effective area (the parent's area when the child has none), matching core's
entity area resolution. Applies to both getEntityAreaId and
getEntityEntryContext, which previously read device.area_id directly.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-13 11:57:28 +03:00
Paul Bottein ea0ceecbfc Add ha-grouped-list component (#53618) 2026-08-13 08:47:14 +01:00
Bram KragtenandClaude Opus 4.8 5f007a1575 Run the frontend build in parallel with lint and tests (#53623)
* Run the frontend build in parallel with lint and tests

The build job waited for lint and test because a full build was expensive
enough that we did not want to spend it on a PR that fails its checks. With
the rspack persistent cache it now takes ~3 min instead of ~5, and it is the
longest job in the run, so serialising it behind the others dominates CI
wall-clock: 8s + max(lint 86s, test 123s) + build 194s.

Depend only on prepare-dependencies so all three run together, which brings a
successful run down from ~5.5 min to ~3.5 min — the build itself becomes the
floor.

To avoid finishing an expensive build for a PR that is already broken, each of
the three jobs cancels the whole run when it fails. The cancel step needs
`actions: write`; on pull requests from forks the token stays read-only, so it
is a no-op there and the jobs just run to completion.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* Keep the Actions write scope away from pull request code

The cancellation needed `actions: write`, and granting it at workflow scope
handed it to every job — including the ones that check out the pull request
and pass GITHUB_TOKEN into the gulp build, so PR-controlled code (or a
compromised dependency) would have had write access to Actions.

Move the cancellation into its own job that holds `actions: write` on its own
and never checks out the repository, so the elevated token is never exposed to
PR code. It cannot simply `needs` the checks — a dependent job only starts once
they have all finished, which is too late to cancel anything — so it polls the
run's job statuses and cancels on the first failure.

Costs one extra (idle) runner slot for the duration of the run.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-13 08:48:24 +03:00
Bram Kragten f360a22927 Wait for analytics data during onboarding (#53621) 2026-08-13 06:56:16 +02:00
Paul Bottein a67111e41f Render state and numeric state entities as row targets (#53610)
* Render state and numeric state entities as row targets

* Add tests for entity-less trigger and condition descriptions
2026-08-13 06:53:44 +02:00
Bram KragtenandClaude Opus 4.8 4b7d3a7e4f Add rspack persistent cache (nightly writes, CI reads) (#53611)
Co-authored-by: Claude Opus 4.8 <[email protected]>
2026-08-12 22:30:42 +02:00
Petar Petrov 88be7adafa Stop number box rows from reserving unused space (#53614) 2026-08-12 14:42:09 +01:00
Paul Bottein 91a6d737b3 Fix row target badge height and font (#53612) 2026-08-12 10:17:08 +01:00
Petar Petrov 22c3a6fe67 Don't trim the selected value in pickers (#53613) 2026-08-12 10:16:39 +01:00
Petar Petrov bcc799970a Fix lowercase view button in blueprint in-use dialog (#53609) 2026-08-12 09:55:34 +01:00
Petar Petrov 31d4a37c15 Fix time condition summary when before is midnight (#53608) 2026-08-12 09:51:51 +01:00
Bram Kragten 235541748b Bumped version to 20260729.6 2026-08-07 16:30:37 +02:00
Paul Bottein 6bd1d698ce Fix disabled save button when leaving an automation with unsaved changes (#53538) 2026-08-07 16:27:35 +02:00
Bram Kragten 18862b868f Wait with showing pending http changes dialog until loading screen is… (#53534)
* Wait with showing pending http changes dialog until loading screen is gone

* fix timing
2026-08-07 16:27:33 +02:00
Bram Kragten 662d817a5e Fix link to different port being handled as internal link (#53530) 2026-08-07 16:27:32 +02:00
Aidan Timson 7412ab5578 Remove "dev" from tools actions description (#53528)
* Remove "dev" from tools actions description

* Clarify vt is browser developer tools
2026-08-07 16:27:31 +02:00
Krisjanis Lejejs b2be0bd673 Remove cloud demo controls (#53524) 2026-08-07 16:27:30 +02:00
Bram Kragten a141432546 Don't disable interaction when row is disabled (#53517)
dont disable interaction when row is disabled
2026-08-07 16:27:29 +02:00
Paul Bottein cd50531b67 Stack the sidebar when only one column fits (#53515) 2026-08-07 16:27:29 +02:00
Petar Petrov f7438f4d0e Accept hostnames and localize validation messages in the HTTP config form (#53511)
Accept hostnames in HTTP config listen addresses and localize number validation
2026-08-07 16:27:28 +02:00
Petar Petrov a7fabb8a8c Only show the sidebar tab switcher when its tabs are labelled (#53508) 2026-08-07 16:26:46 +02:00
Aidan Timson 9dab55f39a Fix notification stacking (#53486)
* Stack notifications independently

* Preserve identified notifications on legacy close

* Preserve updated notifications during close

* Fix notification stack positioning

* Update src/managers/notification-manager.ts

Co-authored-by: Petar Petrov <[email protected]>

---------

Co-authored-by: Petar Petrov <[email protected]>
(cherry picked from commit d03ba15c09)

# Conflicts:
#	test/panels/config/script/script-paste.test.ts
2026-08-07 16:23:38 +02:00
Bram Kragten 7ac98b7fdd Bumped version to 20260729.5 2026-08-05 09:56:45 +02:00
karwosts 5c1c92e8ca Fix missing label in solar forecast dialog (#53506) 2026-08-05 09:56:31 +02:00
Paul Bottein bf9765d557 Fix back navigation loop on the cloud page (#53497) 2026-08-05 09:56:30 +02:00
Petar Petrov b013b1f929 Keep numeric slider and buttons within min and max when the step overshoots (#53489)
* Clamp numeric controls after snapping to the step

* Cover the pointer path, display and arrow keys at the bounds
2026-08-05 09:53:55 +02:00
Petar Petrov 8026a59e70 Fix wrong month in date picker calendar header (#53453) 2026-08-05 09:50:37 +02:00
Bram Kragten ffa7cf17a6 Bumped version to 20260729.4 2026-08-04 13:19:17 +02:00
karwosts 5a5cec9060 Fix slow loading of entity rows in device page (#53471)
Fix lazy loading of entity rows in device page
2026-08-04 12:50:36 +02:00
Petar Petrov bb962ba3d8 Fix energy default period being saved under the wrong storage key (#53462) 2026-08-04 12:50:35 +02:00
Matthias AlphartandClaude Opus 5 d4a59ff1c7 Drop websocket collections created by an iframe panel on teardown (#53448)
* Drop websocket collections created by an iframe panel on teardown

`getCollection()` caches collections (entity registry, label registry, ...) on
the `Connection` object. A custom panel embedded in an iframe shares the
connection with the main window, so a collection the panel is the first to
request is created inside the iframe's realm.

When the user leaves the panel, `ha-panel-custom` removes the iframe and that
realm is destroyed - but the collection stays cached on the connection. Its
store, and the `setTimeout` that hands the cached state to new subscribers, are
gone, so every later subscriber waits forever for a callback that can never
fire. Since the registries moved to `LazyContextProvider` they are subscribed
on demand, which makes an iframe panel the first requester far more often: the
KNX panel's entity table renders empty after leaving and re-entering it, and
the main frontend can inherit the same dead cache.

Clean up from the iframe's own `pagehide` handler, while the realm is still
alive - `disconnectedCallback` on `ha-panel-custom` runs after the browsing
context is discarded, when `contentWindow` is already `null`.

Co-Authored-By: Claude Opus 5 <[email protected]>

* Use unknown instead of any in the CachedCollection shape

The helper never inspects the subscribed state, so the parameter type only
needs to be a placeholder.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
2026-08-04 12:50:34 +02:00
karwosts f496d842a6 Allow to favorite the manual card (#53445) 2026-08-04 12:50:33 +02:00
Petar Petrov c14d07c845 Stop the statistics graph card editor looping while typing a name (#53434) 2026-08-04 12:50:32 +02:00
Petar Petrov 8a1f2e86bd Show progress on the Zigbee backup button while the backup is created (#53422) 2026-08-04 12:49:55 +02:00
Bram Kragten 1454f4d081 Bumped version to 20260729.3 2026-07-31 16:44:13 +02:00
Paul Bottein 1a47c326b2 Fix tile name truncated too early (#53416) 2026-07-31 16:43:50 +02:00
Aidan Timson d8e827e08b Fix profile theme link colour (#53415) 2026-07-31 16:43:49 +02:00
John G. 301c907fa9 Fix typo in Google Home Matter pairing instructions (#53413)
Corrected a typo in the instructions for pairing a Matter device from Google Home with a pairing code.
2026-07-31 16:43:48 +02:00
karwosts 1ef3bc94d0 Add a few missing logbook csv fields (#53412) 2026-07-31 16:43:47 +02:00
Bram KragtenandSimon Lamon ba0367be2f use defaults provided by core for ports in strings, add url to new lo… (#53407)
* use defaults provided by core for ports in strings, add url to new location after restart

* Apply suggestions from code review

Co-authored-by: Simon Lamon <[email protected]>

---------

Co-authored-by: Simon Lamon <[email protected]>
2026-07-31 16:43:46 +02:00
Bram Kragten c186a31056 Prevent http confirm dialog from getting closed (#53406) 2026-07-31 16:43:45 +02:00
Paul BotteinandPetar Petrov bf8c92c95e Use backend slugify for the entity ID format preview (#53394)
* Use backend slugify for the entity ID format preview

* Update src/panels/config/core/ha-config-entity-id-format.ts

Co-authored-by: Petar Petrov <[email protected]>

* Use top-level slugify websocket command

* Fix formatting

---------

Co-authored-by: Petar Petrov <[email protected]>
2026-07-31 16:43:44 +02:00
Bram Kragten 9743117abf Bumped version to 20260729.2 2026-07-30 23:27:41 +02:00
Petar Petrov 5e012973b2 Reject non-http URLs from integrations before using them as links (#53379) 2026-07-30 23:27:10 +02:00
Petar Petrov ea659f1b33 Show which energy power statistic is missing (#53404) 2026-07-30 23:25:16 +02:00
539803cb5b Search a media player's own library from the media browser (#53402)
* Search a media player's own library from the media browser

The media browser search only ever asked the media sources, so searching
inside a media player's own library (Music Assistant, Sonos, Squeezebox,
Jellyfin) failed. Ask the entity instead when the current item belongs to
it, the same way browsing already does.

* Update src/data/media_source.ts

* Remove blank line in media_source.ts

Removed unnecessary blank line at the top of media_source.ts

---------

Co-authored-by: Bram Kragten <[email protected]>
Co-authored-by: Simon Lamon <[email protected]>
2026-07-30 23:25:15 +02:00
karwosts 944d3332d1 Fix schedule editor dirty tracking (#53401) 2026-07-30 23:25:14 +02:00
Petar Petrov 4a267d160f Fix numeric input feature editor showing the wrong default style (#53398) 2026-07-30 23:25:13 +02:00
7edb9f8164 Launch screen tweaks (#53380)
* Polish the launch screen

- Use the system sans-serif font so the launch screen no longer blocks on
  loading Roboto
- Reduce the gap between the logo and the loading text
- Dim the loading text to 66% opacity
- Match the OHF logo variant to the applied theme instead of the system
  color scheme
- Make the launch screen text and buttons unselectable

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>

* Drop unit test

* Use classMap

* Drop view transition for css transition to avoid flash

---------

Co-authored-by: marcinbauer85 <[email protected]>
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-07-30 23:25:12 +02:00
Bram Kragten ff814167c6 Bumped version to 20260729.1 2026-07-30 10:41:32 +02:00
Paul Bottein d08d8dde64 Show integration logo and name in the replace device dialog (#53384) 2026-07-30 10:41:12 +02:00
Bram Kragten 5da441ceed Strip empty strings from http config (#53377) 2026-07-30 10:41:11 +02:00
Paul Bottein 22e646a68a Allow area card name to wrap to two lines in vertical layout (#53370)
* Allow area card name to wrap to two lines in vertical layout

* Align vertical tile icons in grid sections

* Cut single big word
2026-07-30 10:41:11 +02:00
Maarten Lakerveldandcopilot-swe-agent[bot] d0ab20479f Tools > Template use WA Split Panel (#53021)
* Add Web Awesome Split Panel component

* Use SplitPanel for template page. Add vertical/horizontal option. Cleanup, use flexbox.

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
2026-07-30 10:41:10 +02:00
1929 changed files with 151868 additions and 48051 deletions

No files matched your search

+13 -1
View File
@@ -16,6 +16,7 @@ Container components may keep `hass` when they own it and feed providers. Leaf c
## Core Files
- Context definitions: `src/data/context/index.ts`
- `consume` decorator, `ContextSubscriptionController`, and `consumeContext` / `ContextController` for reactive controllers: `src/common/decorators/consume.ts` (use instead of `@lit/context`'s `consume` and `ContextConsumer`, enforced by ESLint)
- Entity-scoped consume helpers: `src/common/decorators/consume-context-entry.ts`
- Transform decorator: `src/common/decorators/transform.ts`
- Canonical migration example: `src/panels/lovelace/cards/hui-button-card.ts`
@@ -36,6 +37,7 @@ Container components may keep `hass` when they own it and feed providers. Leaf c
| `apiContext` | `hass.callService`, `hass.callApi`, `hass.callApiRaw`, `hass.callWS`, `hass.sendWS`, `hass.fetchWithAuth` |
| `uiContext` | themes, selected theme, panels, sidebar, and UI state |
| `narrowViewportContext` | narrow-layout boolean |
| `reducedMotionContext` | `prefers-reduced-motion` media query |
Lazy contexts subscribe on first consumer and tear down after the last consumer: `labelsContext`, `fullEntitiesContext`, `configEntriesContext`, `manifestsContext`, `triggerDescriptionsContext`, and `conditionDescriptionsContext`.
@@ -43,6 +45,16 @@ The single-field contexts such as `localizeContext`, `themesContext`, and `userC
## Consumption Patterns
Import `consume` from `src/common/decorators/consume`, not from `@lit/context`. The `@lit/context` version forces a host update on every context change, so every consumed field rerenders the component, even without `@state()`, and `@transform` cannot skip anything. Our `consume` leaves update scheduling to the field:
- `@state()` plus `@consume`: rerenders when the context value changes.
- `@state()` plus `@consume` plus `@transform`: rerenders only when the transformed value changes.
- `@consume` alone: the field stays current but never triggers a render. Use this for values only read in event handlers or callbacks, such as `apiContext`, or for data read on demand, such as picker item callbacks.
In reactive controllers, extend `ContextController` and decorate fields with `consumeContext({ context, subscribe, transform })` from the same file. `transform` stores one part of the context value, and `contextUpdated()` runs only when that part changes. `@state()` and `@transform` do not work on controller fields; call `host.requestUpdate()` when the host needs to rerender. Example: `src/data/service-info-controller.ts`.
For lazily created subscriptions, use `ContextSubscriptionController` from the same file instead of `@lit/context`'s `ContextConsumer`, which also forces a host update. Its callback must store the value in a reactive field or call `host.requestUpdate()` itself when the host needs to rerender.
Use entity-scoped helpers when the component watches an entity ID held on the host:
```ts
@@ -81,5 +93,5 @@ To consume a whole group untransformed, omit `@transform` and type the field as
- The component consumes the narrowest context needed for the data it reads.
- A broad `hass` property is kept only when the component is a container or external API requires it.
- Entity-scoped reads use the consume helpers rather than ad hoc context transforms.
- Context fields are marked `@state()` so updates trigger rendering.
- Context fields read during render or `willUpdate` are marked `@state()` so updates trigger rendering. Fields only read outside the render cycle are left without `@state()`.
- Tests and mocks only provide the data the component actually consumes.
+6 -2
View File
@@ -16,8 +16,8 @@ The demo is the full Home Assistant frontend running against a mocked backend an
Run commands from the repository root:
```bash
yarn dev:demo # Development server on http://localhost:8090
yarn dev:demo --background # Detached; also supports --status/--stop/--logs
pnpm dev:demo # Development server on http://localhost:8090
pnpm dev:demo --background # Detached; also supports --status/--stop/--logs
```
Use the E2E workflows documented in `ha-frontend-testing` when validating the demo.
@@ -54,6 +54,10 @@ http://localhost:8090/?demo=<second slug>#/energy/water
- `demo/src/stubs/`: Mocked WebSocket and REST APIs.
- `demo/script/develop_demo`, `demo/script/build_demo`: Development server and static build wrappers.
## Core Data
The service descriptions in `src/fake_data/demo_services.ts` and the trigger and condition descriptions and icons in `demo/src/stubs/automation_platforms_*.ts` are generated from Home Assistant Core. Do not edit them by hand. Run `script/gen_demo_core_data` to regenerate them from the core `dev` branch, and add a domain to the lists in `build-scripts/gulp/gen-demo-core-data.js` when the demo needs its services, triggers, or conditions. Their translations come from the backend translations merged into the demo build.
## Shared Gallery Stubs
`demo/src/stubs/` is shared, not demo-private: gallery pages import from it directly. Before changing or removing anything a stub does, search for its callers across `demo/src/` and `gallery/src/`, then check the affected gallery pages as well as the demo.
+5 -5
View File
@@ -14,11 +14,11 @@ Run commands from the repository root unless noted otherwise:
```bash
gallery/script/develop_gallery # Start the gallery development server
gallery/script/build_gallery # Build the static gallery
yarn lint # ESLint, Prettier, TypeScript, and Lit checks
yarn lint:types # TypeScript compiler, without file arguments
pnpm lint # ESLint, Prettier, TypeScript, and Lit checks
pnpm lint:types # TypeScript compiler, without file arguments
```
Never run `yarn lint:types` or `tsc` with file arguments. File arguments make `tsc` ignore `tsconfig.json` and can emit `.js` files into `src/`.
Never run `pnpm lint:types` or `tsc` with file arguments. File arguments make `tsc` ignore `tsconfig.json` and can emit `.js` files into `src/`.
## Purpose
@@ -122,7 +122,7 @@ Follow the detailed copy standards in `ha-frontend-user-facing-text`: use Americ
## Verification
- For markdown, sidebar, and page-generation changes, run `gallery/script/build_gallery`.
- For TypeScript demo or gallery shell changes, run the smallest relevant check plus `yarn lint` when practical.
- For type checking, run `yarn lint:types` without file arguments.
- For TypeScript demo or gallery shell changes, run the smallest relevant check plus `pnpm lint` when practical.
- For type checking, run `pnpm lint:types` without file arguments.
- For visual changes, run `gallery/script/develop_gallery` and check the affected page on desktop, narrow viewport, and RTL when relevant.
- If verification is skipped, state which command was skipped and why.
+33 -6
View File
@@ -1,12 +1,18 @@
---
name: ha-frontend-review
description: Home Assistant frontend PR and review guidance. Use when reviewing frontend changes, preparing a PR, checking recurring review issues, or applying the PR template.
description: Home Assistant frontend PR and review guidance, including implementation quality, existing review feedback, established design patterns, and the authority of UI/UX evidence. Use when reviewing frontend changes, preparing a PR, checking recurring review issues, or applying the PR template.
---
# HA Frontend Review
Use this skill when reviewing Home Assistant frontend changes or preparing a pull request.
## Review Preparation
1. Establish the review scope from the diff and the behavior changed by it.
2. Before identifying findings, use the [project skill catalogue](../../../AGENTS.md#project-skills) to load every matching companion's `SKILL.md`. Follow applicable companion references in those skills as well; this review skill supplies the workflow, and companions supply the domain-specific criteria.
3. Apply all loaded guidance within that scope. Report only problems introduced or worsened by the changeset, anchored to changed lines. Read surrounding code to understand affected behavior, not to generate unrelated cleanup or migration requests.
## Pull Request Body
When creating a pull request, use `.github/PULL_REQUEST_TEMPLATE.md` as the body.
@@ -20,9 +26,9 @@ When creating a pull request, use `.github/PULL_REQUEST_TEMPLATE.md` as the body
## Pre-Submission Checklist
- `yarn lint` passes when practical for the scope.
- `yarn test` or focused relevant tests are green when practical for the scope.
- Tests are added or updated for new data processing and utilities where applicable.
- `pnpm lint` passes when practical for the scope.
- `pnpm test` or focused relevant tests are green when practical for the scope.
- Each test added by the change protects real logic, not the look of a component.
- User-facing text is localized and follows `ha-frontend-user-facing-text` guidance.
- Components handle loading, error, unavailable, and missing-entity states.
- Entity existence is checked before property access.
@@ -92,9 +98,30 @@ Configuration and props:
- Keep APIs extensible without adding speculative abstractions.
- Validate configuration before applying changes.
## UI/UX Evidence
For user-facing changes, establish the existing design context as part of frontend review:
- Treat an applicable gallery specification as the authoritative repository source for the documented component or interaction. Inspect its written guidance and demos when present.
- Note relevant production designs, approved designs, and shared `ha-*` components so the implementation can also be compared with established frontend behaviour.
- Require the applicable gallery documentation or demo to change when the implementation intentionally changes behaviour documented there.
- Prefer an established input layout or appropriate shared component over a raw input or ad hoc control.
- Treat explicit UI/UX approval, current repository guidance, and direct human or workflow instructions as stronger evidence than inference.
- Treat linked tasks as evidence of the problem and stated requirements, not automatic UI/UX approval.
- When the direction remains uncertain, search frontend pull requests that carry or previously carried **Needs UX**. Inspect their label history, comments, and reviews rather than relying on the current label alone.
- Judge relevant feedback by its content and surrounding discussion. When GitHub provides `author_association`, prioritise feedback marked `MEMBER`.
- Prefer recent feedback about similar interactions or components. Label removal can show that a workflow gate moved on, but does not prove approval without the surrounding discussion.
- Summarise the applicable guidance instead of maintaining a reviewer list or treating one historical decision as a permanent rule.
## Review Flow
- Identify behavioral regressions, bugs, accessibility issues, and missing tests first.
- Before reviewing a pull request, read its existing comments, reviews, and threads, including their status, resolver, and Copilot resolution reason when available.
- Prioritise substantive human feedback, especially from authors marked `MEMBER`, and validate agent-generated feedback against the code and repository guidance.
- Do not duplicate unresolved findings as new inline comments; reference any that still need action in the review summary. Treat resolved feedback as closed only when the resolution reason or surrounding discussion supports that outcome; otherwise validate it against the current code before suppressing it. Respect **Won't fix** and **Incorrect** reasons.
- When a later commit addresses an unresolved thread, note in the review summary that it looks addressed, linking the thread and the commit, so it can be resolved. Do not report it as still open.
- Identify behavioral regressions, bugs, accessibility issues, and missing tests that `ha-frontend-testing` calls for first.
- Do not ask for new tests on visual components. If the visuals clearly changed and the PR has no screenshots or videos, suggest adding them instead.
- When the change adds something repository guidance rules out, such as a rendering test, open the comment with the removal ("Remove this test file") and cite the guidance in one sentence. Do not critique how the unwanted code is written, as that reads as a request to fix it.
- Record the applicable UI/UX evidence for user-facing changes, whether or not further input is needed.
- Keep style-only comments secondary unless they affect maintainability or user experience.
- Prefer small, direct fixes over large refactors during review follow-up.
- Load the matching `ha-frontend-*` skill when a finding falls within its area.
+32 -31
View File
@@ -16,16 +16,16 @@ Use this skill when choosing or running validation for frontend changes.
## Core Commands
```bash
yarn lint # ESLint + Prettier + TypeScript + Lit
yarn format # Auto-fix ESLint + Prettier
yarn lint:types # TypeScript compiler, run without file arguments
yarn test # Vitest
yarn build # Full production build
yarn dev # App dev server
yarn dev:serve # Local serving dev server
pnpm lint # ESLint + Prettier + TypeScript + Lit
pnpm format # Auto-fix ESLint + Prettier
pnpm lint:types # TypeScript compiler, run without file arguments
pnpm test # Vitest
pnpm build # Full production build
pnpm dev # App dev server
pnpm dev:serve # Local serving dev server
```
Never run `tsc` or `yarn lint:types` with file arguments. File arguments make `tsc` ignore `tsconfig.json` and can emit `.js` files into `src/`.
Never run `tsc` or `pnpm lint:types` with file arguments. File arguments make `tsc` ignore `tsconfig.json` and can emit `.js` files into `src/`.
For focused type feedback on one file, use editor diagnostics instead of a file-scoped `tsc` command.
@@ -34,35 +34,36 @@ For focused type feedback on one file, use editor diagnostics instead of a file-
Production builds support foreground and managed background execution:
```bash
yarn build # Full foreground build
yarn build --background # Full managed background build
yarn build --modern # Modern frontend_latest bundle only
yarn build --modern --background # Modern managed background build
yarn build --status
yarn build --logs [--follow]
yarn build --stop
pnpm build # Full foreground build
pnpm build --background # Full managed background build
pnpm build --modern # Modern frontend_latest bundle only
pnpm build --modern --background # Modern managed background build
pnpm build --status
pnpm build --logs [--follow]
pnpm build --stop
```
Use `yarn build --modern --background` for production bundle-size or browser performance comparisons that only need modern browser output. It runs the normal metadata and static preparation, minifies and compresses the modern `frontend_latest` bundle and shared static assets, and generates modern-only entry pages and service workers. It deliberately skips the legacy bundle and its service worker.
Use `pnpm build --modern --background` for production bundle-size or browser performance comparisons that only need modern browser output. It runs the normal metadata and static preparation, minifies and compresses the modern `frontend_latest` bundle and shared static assets, and generates modern-only entry pages and service workers. It deliberately skips the legacy bundle and its service worker.
Do not pass `--help`, `--background`, or `--modern` to `script/build_frontend`; that raw script does not parse arguments and always starts the full foreground build. Use `yarn build` for managed builds. App builds and development servers keep exclusive ownership of `hass_frontend/` for their lifetime.
Do not pass `--help`, `--background`, or `--modern` to `script/build_frontend`; that raw script does not parse arguments and always starts the full foreground build. Use `pnpm build` for managed builds. App builds and development servers keep exclusive ownership of `hass_frontend/` for their lifetime.
Managed app, demo, gallery, and E2E app workflows share one lifetime lock, so only one build or development server can run at a time.
## Unit And Utility Tests
## When To Add Tests
- Add or update Vitest tests for data processing, utility code, and behavior that can be tested without a browser.
- Mock WebSocket connections and API calls at boundaries.
- Cover loading, error, unavailable, and missing-entity states where relevant.
- Test accessibility-sensitive behavior when it can be asserted without brittle DOM internals.
- Write tests for code that computes something: data processing, utilities, config validation, and strategies.
- Do not write rendering tests. This includes views, panels, and components whose text, styles, slots, or option defaults are checked, or that only put context and helper data into a template.
- Do not try to cover every scenario, especially for behaviour that changes often.
- If you are not sure a test is useful, describe it and what it would catch, and let the user decide.
- Tests never talk to a real Home Assistant. Replace `callWS`, `callApi`, and the connection with fakes.
## Dev Servers
`yarn dev` builds and watches the app, served by a running Home Assistant core configured through `development_repo`.
`pnpm dev` builds and watches the app, served by a running Home Assistant core configured through `development_repo`.
`yarn dev:serve` also serves locally and supports `-c` for the core URL and `-p` for the port. The default is 8124, or 8123 in a devcontainer.
`pnpm dev:serve` also serves locally and supports `-c` for the core URL and `-p` for the port. The default is 8124, or 8123 in a devcontainer.
Dev server commands support `--background`, `--status`, `--stop`, and `--logs [--follow]`. `yarn dev`, `yarn dev:serve`, `yarn dev:demo`, and `yarn dev:gallery` also support `--fetch-translations`; this runs translation fetching, including first-time GitHub device authentication, under the workflow lock before starting the watcher. It works in foreground and background modes. Prefer managed background mode while iterating so the watcher stays available across test runs without occupying the terminal. `yarn dev` and `yarn dev:serve` share one managed process slot because both write the app output.
Dev server commands support `--background`, `--status`, `--stop`, and `--logs [--follow]`. `pnpm dev`, `pnpm dev:serve`, `pnpm dev:demo`, and `pnpm dev:gallery` also support `--fetch-translations`; this runs translation fetching, including first-time GitHub device authentication, under the workflow lock before starting the watcher. It works in foreground and background modes. Prefer managed background mode while iterating so the watcher stays available across test runs without occupying the terminal. `pnpm dev` and `pnpm dev:serve` share one managed process slot because both write the app output.
## Playwright E2E
@@ -72,15 +73,15 @@ Start the relevant suite server, then run that suite:
| Suite | Background server | Test command |
| ------- | -------------------------------------------- | ----------------------- |
| App | `yarn test:e2e:app:dev --background` on 8095 | `yarn test:e2e:app` |
| Demo | `yarn dev:demo --background` on 8090 | `yarn test:e2e:demo` |
| Gallery | `yarn dev:gallery --background` on 8100 | `yarn test:e2e:gallery` |
| App | `pnpm test:e2e:app:dev --background` on 8095 | `pnpm test:e2e:app` |
| Demo | `pnpm dev:demo --background` on 8090 | `pnpm test:e2e:demo` |
| Gallery | `pnpm dev:gallery --background` on 8100 | `pnpm test:e2e:gallery` |
The custom development wrappers use `/__ha_dev_status` to identify and manage their own suites. Playwright server reuse checks the configured URL instead. Wrapper start and stop operations are idempotent for a matching suite and reject an unrelated process occupying the port.
Local runs against a watched development server do not always match CI's clean build artifacts, environment, sharding, or worker configuration. Use background servers for the fast iteration loop, but confirm the relevant CI jobs complete successfully before considering E2E changes verified.
Use `-g "<title>" --project=chromium` to narrow a run. `yarn test:e2e` runs suites sequentially when managed servers are unavailable to prevent cold builds racing over shared generated assets. Run suites directly; piping through output truncation hides progress and failures.
Use `-g "<title>" --project=chromium` to narrow a run. `pnpm test:e2e` runs suites sequentially when managed servers are unavailable to prevent cold builds racing over shared generated assets. Run suites directly; piping through output truncation hides progress and failures.
The app suite uses a stripped-down harness for e2e. Demo and gallery use their normal dev servers.
@@ -93,7 +94,7 @@ That workflow owns the baseline, noise analysis, guardrails, acceptance threshol
## Verification Selection
- Documentation-only change: no code test required unless examples or commands changed.
- Type-only or utility change: run focused Vitest if available, then `yarn lint:types` if practical.
- Type-only or utility change: run focused Vitest if available, then `pnpm lint:types` if practical.
- Lit component change: run relevant tests plus lint or typecheck depending on scope.
- E2E-sensitive flow: start the relevant e2e dev server and run the narrow Playwright suite.
- Broad refactor: run `yarn lint` and relevant test suites when practical.
- Broad refactor: run `pnpm lint` and relevant test suites when practical.
@@ -0,0 +1,44 @@
---
name: ha-frontend-ux-readiness
description: Home Assistant frontend UI/UX readiness routing for new cards, badges, screens, and interaction patterns. Use it with `ha-frontend-review` to decide whether frontend review is enough or further UI/UX input is needed. Skip it for PRs already carrying Needs UX and for fixes or technical details that preserve an established experience.
---
# HA Frontend UI/UX Readiness
Use the design context and evidence gathered through `ha-frontend-review` to decide whether a change's UI/UX direction is settled and whether further UI/UX review should be recommended or is explicitly required. This skill routes the result; it does not repeat or replace implementation, accessibility, or frontend quality review.
## Early Exit
If the PR already carries the **Needs UX** label, reviewers have already decided to ask designers or UX reviewers for guidance. Do not use this skill to make that recommendation again.
## Triage
1. Apply `ha-frontend-review` and record its UI/UX evidence.
- Include the applicable gallery specification, production or approved designs, shared `ha-*` components, task requirements, historical feedback, and direct instructions.
- Keep the implementation review separate from this readiness decision.
2. Classify the user-facing decision.
- Existing-feature fixes and technical details normally remain with frontend review when they preserve the established experience.
- New cards, badges, screens, and interaction patterns normally need this readiness check.
3. Decide whether the evidence gathered during frontend review settles the direction.
- Frontend maintainer guidance, explicit UI/UX approval, current guidance, an established pattern, or a task that settles the material visual and interaction choices can settle the direction.
- Insufficient or conflicting evidence leaves the direction unresolved.
4. Select exactly one route below and state which frontend-review evidence supports it.
## Routes
- **Frontend review sufficient:** The change preserves the established experience, or the evidence settles the material visual and interaction choices. Cite that evidence and continue with `ha-frontend-review`.
- **UI/UX review recommended:** A new user experience has material design choices that remain unresolved. Identify the decision that needs input and recommend UI/UX review.
- **UI/UX review required:** A workflow rule or direct human instruction explicitly requires UI/UX review. Cite that evidence. A new design, task link, or lack of evidence is not enough on its own.
Frontend maintainer guidance, explicit UI/UX approval, established patterns, and task requirements inform the route. A task can settle requirements without settling the UI/UX. Recommend UI/UX review when important design choices remain unresolved.
## Reporting
Keep the result concise and use this structure:
- **Route:** Frontend review sufficient, UI/UX review recommended, or UI/UX review required
- **Established patterns:** relevant gallery specifications, production designs, and shared `ha-*` components for the next reviewer to compare
- **Supporting evidence:** approval, guidance, established patterns, task requirements, direct instructions, or the evidence gap or conflict
- **Next action:** the review action implied by the route
Separate whether the UI/UX direction is settled from whether the implementation is correct.
+40 -24
View File
@@ -1,36 +1,52 @@
[modern]
# Modern builds target recent browsers supporting the latest features to minimize transpilation, polyfills, etc.
# It is served to browsers meeting the following requirements:
# - released in the last year + current alpha/beta versions
# - Firefox extended support release (ESR)
# - with global utilization at or above 0.5%
# - released in the last 2 years + current alpha/beta versions
# - exclude dead browsers (no security maintenance for 2+ years)
# - exclude KaiOS, QQ, and UC browsers due to lack of sufficient feature support data
# - exclude QQ, and UC browsers due to lack of sufficient feature support data
unreleased versions
last 1 year
Firefox ESR
>= 0.5%
last 2 years
not dead
not KaiOS > 0
not QQAndroid > 0
not UCAndroid > 0
[legacy]
# Legacy builds are served when modern requirements are not met and support browsers:
# - released in the last 7 years + current alpha/beta versionss
# - with global utilization at or above 0.05%
# - exclude dead browsers (no security maintenance for 2+ years)
# - exclude Opera Mini which does not support web sockets
unreleased versions
last 7 years
>= 0.05%
not dead
not op_mini all
# Legacy builds are served when modern requirements are not met.
# Floors are pinned explicitly (not usage-based) so the support policy is
# deliberate and does not drift with global usage statistics, which do not
# represent old tablets and wall displays used as Home Assistant dashboards:
# - iOS/Safari >= 12: iPad Air 1 / mini 2 / mini 3 (last supported iOS).
# Older iPads (iPad 2/3/mini 1 on iOS 9.3, iPad 4 on iOS 10.3) cannot run
# the app: their engines lack custom elements, shadow DOM, and/or CSS grid.
# - Chrome >= 59: Fire OS 5 tablets (Fire 7/HD 8/HD 10 through ~2017) have
# their system WebView pinned at Chromium 59 and commonly run Fully Kiosk;
# also covers old kiosk browsers and no-longer-updating webviews above it.
# - Edge >= 79: all Chromium-based Edge. Costs nothing (above the Chrome
# floor); mainly catches Edge 109 on Windows 7/8.1 and update-frozen
# enterprise installs, whose engines can run the legacy build fine.
# - Firefox >= 94: the zero-cost floor, not a chased population — pinning it
# adds no babel transforms, core-js modules, or Lightning CSS prefixes to
# the output. Mozilla-supported Firefox (incl. current ESR) always matches
# [modern]; Firefox on old OSes is not supported (use Chrome 109 instead).
# If Firefox ever becomes the pin forcing extra output, raise it first.
# - Samsung >= 9: Samsung Internet on old Galaxy tablets
Chrome >= 59
ChromeAndroid >= 59
Edge >= 79
Firefox >= 94
FirefoxAndroid >= 94
iOS >= 12
Safari >= 12
Samsung >= 9
[legacy-sw]
# Same as legacy plus supports service workers
unreleased versions
last 7 years
>= 0.05% and supports serviceworkers
not dead
not op_mini all
# Same as legacy, restricted to browsers that support service workers
# (currently resolves to the same set; guards the service worker build if the legacy floor ever drops below them)
Chrome >= 59 and supports serviceworkers
ChromeAndroid >= 59 and supports serviceworkers
Edge >= 79 and supports serviceworkers
Firefox >= 94 and supports serviceworkers
FirefoxAndroid >= 94 and supports serviceworkers
iOS >= 12 and supports serviceworkers
Safari >= 12 and supports serviceworkers
Samsung >= 9 and supports serviceworkers
+15
View File
@@ -7,13 +7,17 @@ body:
value: |
Make sure you are running the [latest version of Home Assistant][releases] before reporting an issue.
Please read our [issue reporting guide][reporting-issues] before submitting a report.
If you have a feature or enhancement request for the frontend, please [start a discussion][fr] instead of creating an issue.
**Please do not report issues for custom cards.**
[fr]: https://github.com/orgs/home-assistant/discussions
[releases]: https://github.com/home-assistant/home-assistant/releases
[reporting-issues]: https://www.home-assistant.io/help/reporting_issues/
- type: checkboxes
id: checklist
attributes:
label: Checklist
description: Please verify that you've followed these steps
@@ -30,18 +34,21 @@ body:
value: |
## The problem
- type: textarea
id: problem
validations:
required: true
attributes:
label: Describe the issue you are experiencing
description: Provide a clear and concise description of what the bug is.
- type: textarea
id: expected_behavior
validations:
required: true
attributes:
label: Describe the behavior you expected
description: Describe what you expected to happen or it should look/behave.
- type: textarea
id: steps_to_reproduce
validations:
required: true
attributes:
@@ -59,6 +66,7 @@ body:
value: |
## Environment
- type: input
id: core_version
validations:
required: true
attributes:
@@ -67,18 +75,21 @@ body:
description: >
Can be found in: [Settings -> About](https://my.home-assistant.io/redirect/info/).
- type: input
id: last_working_version
attributes:
label: What was the last working version of Home Assistant Core?
placeholder: core-
description: >
If known, otherwise leave blank.
- type: input
id: browser
attributes:
label: In which browser are you experiencing the issue?
placeholder: Google Chrome 88.0.4324.150
description: >
Provide the full name and don't forget to add the version!
- type: input
id: os
attributes:
label: Which operating system are you using to run this browser?
placeholder: macOS Big Sur (1.11)
@@ -90,6 +101,7 @@ body:
# Details
- type: textarea
id: entity_state
attributes:
label: State of relevant entities
description: >
@@ -98,6 +110,7 @@ body:
information in the Details view of the More info dialog.
render: txt
- type: textarea
id: configuration
attributes:
label: Problem-relevant frontend configuration
description: >
@@ -107,6 +120,7 @@ body:
passwords, private URLs and other credentials.
render: yaml
- type: textarea
id: javascript_errors
attributes:
label: JavaScript errors shown in your browser console/inspector
description: >
@@ -114,6 +128,7 @@ body:
browser console/inspector please provide them.
render: txt
- type: textarea
id: additional_information
attributes:
label: Additional information
description: >
+4
View File
@@ -11,6 +11,9 @@ inputs:
is-test:
description: Set IS_TEST for the build (skips source maps and compression)
default: "false"
rspack-cache:
description: rspack persistent cache mode ("readwrite", "readonly", or "" to disable)
default: ""
runs:
using: composite
@@ -21,3 +24,4 @@ runs:
env:
GITHUB_TOKEN: ${{ inputs.github-token }}
IS_TEST: ${{ inputs.is-test }}
RSPACK_CACHE: ${{ inputs.rspack-cache }}
@@ -16,10 +16,10 @@ runs:
with:
path: |
node_modules
.yarn/install-state.gz
~/.local/share/pnpm/store
key: >-
${{ inputs.node-modules-cache-key }}-${{ runner.os }}-${{ runner.arch }}-${{
hashFiles('.nvmrc', 'package.json', 'yarn.lock', '.yarnrc.yml', '.yarn/releases/**', '.yarn/patches/**') }}
hashFiles('.nvmrc', 'package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml', 'patches/**') }}
lookup-only: true
- name: Setup Node and install
@@ -35,7 +35,7 @@ runs:
with:
path: |
node_modules
.yarn/install-state.gz
~/.local/share/pnpm/store
key: >-
${{ inputs.node-modules-cache-key }}-${{ runner.os }}-${{ runner.arch }}-${{
hashFiles('.nvmrc', 'package.json', 'yarn.lock', '.yarnrc.yml', '.yarn/releases/**', '.yarn/patches/**') }}
hashFiles('.nvmrc', 'package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml', 'patches/**') }}
+22 -7
View File
@@ -1,12 +1,12 @@
name: Setup Node and install
description: Set up Node from .nvmrc and install yarn dependencies
description: Set up Node from .nvmrc and install pnpm dependencies
inputs:
immutable:
description: Pass --immutable to yarn install
description: Pass --frozen-lockfile to pnpm install
default: "true"
cache:
description: Enable the yarn cache in setup-node
description: Cache the pnpm store
default: "true"
node-modules-cache:
description: Restore the exact shared node_modules cache before installing
@@ -18,6 +18,8 @@ inputs:
runs:
using: composite
steps:
# The pnpm store is cached with node_modules because `pnpm licenses`
# (used by the license file generation) reads package metadata from it.
- name: Restore complete dependency tree
id: dependency-cache
if: inputs.node-modules-cache == 'true'
@@ -26,22 +28,35 @@ runs:
with:
path: |
node_modules
.yarn/install-state.gz
~/.local/share/pnpm/store
key: >-
${{ inputs.node-modules-cache-key }}-${{ runner.os }}-${{ runner.arch }}-${{
hashFiles('.nvmrc', 'package.json', 'yarn.lock', '.yarnrc.yml', '.yarn/releases/**', '.yarn/patches/**') }}
hashFiles('.nvmrc', 'package.json', 'pnpm-lock.yaml', 'pnpm-workspace.yaml', 'patches/**') }}
- name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version-file: ".nvmrc"
cache: ${{ inputs.cache == 'true' && (inputs.node-modules-cache != 'true' || steps.dependency-cache.outputs.cache-hit != 'true') && 'yarn' || '' }}
- name: Enable Corepack
shell: bash
run: corepack enable
- name: Get pnpm store directory
id: pnpm-store
if: inputs.cache == 'true' && (inputs.node-modules-cache != 'true' || steps.dependency-cache.outputs.cache-hit != 'true')
shell: bash
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
- name: Cache pnpm store
if: steps.pnpm-store.outputs.path
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: pnpm-store-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-store-${{ runner.os }}-${{ runner.arch }}-
- name: Install dependencies
if: inputs.node-modules-cache != 'true' || steps.dependency-cache.outputs.cache-hit != 'true'
shell: bash
run: yarn install ${{ inputs.immutable == 'true' && '--immutable' || '' }}
run: pnpm install ${{ inputs.immutable == 'true' && '--frozen-lockfile' || '--no-frozen-lockfile' }}
-24
View File
@@ -1,24 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
# Dependabot only scans .github/workflows by default; composite actions
# under .github/actions must be listed explicitly to stay updated.
# https://github.com/dependabot/dependabot-core/issues/6704
directories:
- "/"
- "/.github/actions/setup"
- "/.github/actions/build"
- "/.github/actions/netlify-deploy"
schedule:
interval: weekly
time: "06:00"
cooldown:
default-days: 7
open-pull-requests-limit: 10
groups:
codeql-action:
patterns:
- "github/codeql-action/*"
labels:
- Dependencies
- GitHub Actions
+229 -3
View File
@@ -1,3 +1,23 @@
# Path rules for .github/workflows/labeler.yaml, which runs actions/labeler on
# every pull request. A label is added when a pull request changes a matching
# file, and removed again when it no longer does, including one added by hand.
#
# Do not add these labels here. .github/scripts/label-content.mts applies and
# removes them from paths and code. A rule here would remove them whenever its
# paths don't match, even when the script's code check does:
#
# - Companion App
# - Home Assistant Link
# - Labs
# - Supervisor
Activity:
- changed-files:
- any-glob-to-any-file:
- src/panels/logbook/**
- src/panels/lovelace/**/*logbook*
- src/data/logbook.ts
Agents:
- changed-files:
- any-glob-to-any-file:
@@ -16,6 +36,36 @@ Agents:
- .github/skills/**
- .github/workflows/copilot-setup-steps.yml
AI:
- changed-files:
- any-glob-to-any-file:
- "src/panels/config/core/{ha-config-section-ai,ai-task-pref,mcp-pref}.ts"
- src/components/ha-suggest-with-ai-button.ts
- "src/data/{ai_task,llm}.ts"
Areas:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/areas/**
- src/data/area/**
- "src/data/{area_floor_picker,floor_registry,ws-area_registry,ws-floor_registry}.ts"
Automations:
- changed-files:
- any-glob-to-any-file:
- "src/panels/config/{automation,script,scene,blueprint}/**"
- src/components/automation/**
- src/components/trace/**
- src/data/trace*.ts
- "src/data/{automation,automation_i18n,script,script_i18n,scene,blueprint,trigger,condition,action}.ts"
Backups:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/backup/**
- src/data/backup*.ts
- src/onboarding/onboarding-restore-backup.ts
Build:
- changed-files:
- any-glob-to-any-file:
@@ -23,12 +73,37 @@ Build:
- .browserslistrc
- gulpfile.js
Calendar:
- changed-files:
- any-glob-to-any-file:
- src/panels/calendar/**
- src/panels/lovelace/**/*calendar*
- src/data/calendar.ts
Cast:
- changed-files:
- any-glob-to-any-file:
- cast/src/**
- src/cast/**
Connectivity:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/connectivity/**
- src/panels/config/tags/**
- "src/panels/config/integrations/integration-panels/{bluetooth,infrared,matter,modbus,mqtt,radio_frequency,serial,thread,zha,zwave_js}/**"
- "src/data/{bluetooth,infrared,matter,matter-lock,modbus,mqtt,otbr,radio_frequency,tag,thread,usb,zha,zwave_js,zwave_js-credentials}.ts"
Dashboards:
- changed-files:
- any-glob-to-any-file:
- src/panels/lovelace/**
- "src/panels/{home,climate,light,security,maintenance,map}/**"
- src/panels/config/lovelace/**
- "src/panels/config/dashboard/{dashboard-card,dialog-new-dashboard,show-dialog-new-dashboard}.ts"
- src/data/lovelace/**
- src/data/lovelace*.ts
Demo:
- changed-files:
- any-glob-to-any-file:
@@ -48,15 +123,38 @@ Dependencies:
- any-glob-to-all-files:
- package.json
- renovate.json
- yarn.lock
- .yarn/**
- .yarnrc.yml
- pnpm-lock.yaml
- pnpm-workspace.yaml
- patches/**
- .nvmrc
# Dependabot and Renovate branches always match (i.e. compatibility tweaks by members considered minor)
- head-branch:
- "^renovate/"
- "^dependabot/"
Devices:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/devices/**
- src/data/device/device_registry.ts
- src/data/ws-device_registry.ts
Energy:
- changed-files:
- any-glob-to-any-file:
- src/panels/energy/**
- src/panels/config/energy/**
- src/panels/lovelace/cards/energy/**
- src/panels/lovelace/**/*energy*
- src/data/energy*.ts
Entities:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/entities/**
- src/data/entity/entity_registry*.ts
- src/data/ws-entity_registry_display.ts
GitHub Actions:
- changed-files:
- any-glob-to-any-file:
@@ -64,6 +162,100 @@ GitHub Actions:
- .github/workflows/**
- .github/*.yml
Helpers:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/helpers/**
- src/data/helpers_crud.ts
History:
- changed-files:
- any-glob-to-any-file:
- src/panels/history/**
- src/panels/lovelace/**/*history*
- src/data/history.ts
Integrations:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/integrations/**
- src/panels/config/application_credentials/**
- src/dialogs/config-flow/**
- src/data/application_credential.ts
- src/data/config_entries.ts
- "src/data/{config_flow,data_entry_flow,options_flow,sub_config_flow}.ts"
Labels:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/labels/**
- src/data/label/**
Landing Page:
- changed-files:
- any-glob-to-any-file:
- landing-page/**
Marketplace:
- changed-files:
- any-glob-to-any-file:
- src/panels/marketplace/**
- src/data/marketplace/**
- src/panels/config/integrations/offer-marketplace-uninstall.ts
Media:
- changed-files:
- any-glob-to-any-file:
- src/panels/media-browser/**
- src/components/media-player/**
- src/data/media_source.ts
Notifications:
- changed-files:
- any-glob-to-any-file:
- src/dialogs/notifications/**
- src/data/persistent_notification.ts
Onboarding:
- changed-files:
- any-glob-to-any-file:
- src/onboarding/**
- src/auth/**
- src/data/onboarding.ts
- src/data/auth.ts
People:
- changed-files:
- any-glob-to-any-file:
- "src/panels/config/{person,users}/**"
- "src/data/{person,user,ws-user}.ts"
Profile:
- changed-files:
- any-glob-to-any-file:
- src/panels/profile/**
Search:
- changed-files:
- any-glob-to-any-file:
- src/dialogs/quick-bar/**
- src/state/quick-bar-mixin.ts
- "src/data/{quick_bar,search}.ts"
Sidebar:
- changed-files:
- any-glob-to-any-file:
- src/components/ha-sidebar.ts
- src/dialogs/sidebar/**
System:
- changed-files:
- any-glob-to-any-file:
- "src/panels/config/{core,hardware,info,logs,network,repairs,storage}/**"
- src/panels/config/dashboard/ha-config-updates.ts
- "src/dialogs/{repairs-flow,restart}/**"
- "src/data/{analytics,entity_id_format,error_log,hardware,network,repairs,system_health,system_log,system_log_report,update}.ts"
"Tests: E2E":
- changed-files:
- any-glob-to-any-file:
@@ -93,3 +285,37 @@ GitHub Actions:
- any-glob-to-any-file:
- test/*.ts
- "test/!(e2e)/**"
Theming:
- changed-files:
- any-glob-to-any-file:
- src/resources/theme/**
- src/state/themes-mixin.ts
- src/common/dom/apply_themes_on_element.ts
- "src/data/{theme,ws-themes}.ts"
To-do:
- changed-files:
- any-glob-to-any-file:
- src/panels/todo/**
- src/panels/lovelace/**/*todo*
- src/data/todo.ts
Tools:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/tools/**
Voice:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/voice-assistants/**
- "src/dialogs/{voice-assistant-setup,voice-command-dialog}/**"
- src/components/ha-assist-chat.ts
- "src/data/{assist_pipeline,assist_satellite,conversation,stt,tts,wake_word}.ts"
Zones:
- changed-files:
- any-glob-to-any-file:
- src/panels/config/zone/**
- src/data/zone.ts
-38
View File
@@ -1,38 +0,0 @@
#!/usr/bin/env node
// Fails the check when a pull request carries a label that blocks merging, and
// writes the outcome to the job summary. Invoked from the `check` job in
// .github/workflows/blocking-labels.yaml via actions/github-script:
//
// const { default: checkBlockingLabels } =
// await import(`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-blocking-labels.mjs`);
// await checkBlockingLabels({ github, context, core });
export default async function checkBlockingLabels({ context, core }) {
const blockingLabels = [
"wait for backend",
"Needs UX",
"Do Not Review",
"Blocked",
"has-parent",
];
const prLabels = context.payload.pull_request.labels.map((l) => l.name);
const found = blockingLabels.filter((bl) => prLabels.includes(bl));
if (found.length > 0) {
const message = `This Pull Request is blocked by label${found.length > 1 ? "s" : ""}: ${found.join(", ")}`;
await core.summary
.addHeading(":no_entry_sign: Pull Request is blocked", 2)
.addRaw(message)
.write();
core.setFailed(message);
} else {
await core.summary
.addHeading(
":white_check_mark: Pull Request is clear to merge after review",
2
)
.addRaw(
"This Pull Request is not blocked by any labels which prevent it from being merged."
)
.write();
}
}
+289
View File
@@ -0,0 +1,289 @@
#!/usr/bin/env node
// Checks npm registry metadata for the direct dependencies in package.json:
// deprecation, source repository and provenance. On pull requests only newly
// added packages are checked, and a deprecated one fails the check. Scheduled
// and manual runs report on every direct dependency without failing. Invoked
// from the `npm-metadata` job in .github/workflows/dependency-review.yaml via
// actions/github-script:
//
// const { default: checkNpmMetadata } =
// await import(`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-npm-metadata.mts`);
// await checkNpmMetadata({ github, context, core });
import type { Octokit } from "@octokit/rest";
import type {
Context,
Core,
GitHubScriptArgs,
PullRequestPayload,
} from "./github-script.d.ts";
import { withRetry } from "./github-retry.mts";
// Scheduled and manual runs have no pull request
type Payload = Partial<PullRequestPayload>;
type Section =
| "dependencies"
| "devDependencies"
| "optionalDependencies"
| "peerDependencies";
type PackageJson = Partial<Record<Section, Record<string, string>>>;
interface Dependency {
name: string;
// The package npm installs, which differs from name for npm: aliases
registryName: string;
version: string;
section: Section;
}
// The fields read from a version document on registry.npmjs.org
interface NpmManifest {
deprecated?: string;
repository?: string | { url?: string };
dist?: { attestations?: object };
}
interface Result {
name: string;
version: string;
section: Section;
skipped?: string;
deprecated?: string;
repository?: string;
provenance?: boolean;
}
const SECTIONS: Section[] = [
"dependencies",
"devDependencies",
"optionalDependencies",
"peerDependencies",
];
const EXACT_VERSION = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
const NPM_ALIAS = /^npm:((?:@[^/]+\/)?[^@]+)@(.+)$/;
const CONCURRENCY = 8;
// Returns undefined when the registry reports 404, and throws on any other
// failure so a registry outage fails the job instead of skipping the check.
const fetchJson = async <T,>(url: string): Promise<T | undefined> => {
const response = await fetch(url);
if (response.status === 404) {
return undefined;
}
if (!response.ok) {
throw new Error(
`Request to ${url} failed: ${response.status} ${response.statusText}`
);
}
return JSON.parse(await response.text());
};
const readPackageJson = async (
github: Octokit,
context: Context<Payload>,
ref: string
): Promise<PackageJson> => {
const { data } = await withRetry(`package.json lookup at ${ref}`, () =>
github.rest.repos.getContent({
...context.repo,
path: "package.json",
ref,
mediaType: { format: "raw" },
})
);
// The raw media type returns the file contents as a string, but Octokit
// types the response as the JSON form
if (typeof data !== "string") {
throw new Error("Expected raw package.json contents");
}
return JSON.parse(data);
};
const listDependencies = (pkg: PackageJson): Dependency[] =>
SECTIONS.flatMap((section) =>
Object.entries(pkg[section] ?? {}).map(([name, spec]) => {
// npm: aliases install another package, e.g. npm:[email protected]
const alias = spec.match(NPM_ALIAS);
return {
name,
registryName: alias?.[1] ?? name,
version: alias?.[2] ?? spec,
section,
};
})
);
const repositoryUrl = (repository: NpmManifest["repository"]) => {
const url = typeof repository === "string" ? repository : repository?.url;
return url?.replace(/^git\+/, "").replace(/\.git$/, "");
};
const checkPackage = async ({
name,
registryName,
version,
section,
}: Dependency): Promise<Result> => {
const result = {
name: registryName === name ? name : `${name} (npm:${registryName})`,
version,
section,
};
if (!EXACT_VERSION.test(version)) {
return { ...result, skipped: "not an exact version" };
}
const manifest = await fetchJson<NpmManifest>(
`https://registry.npmjs.org/${encodeURIComponent(registryName)}/${version}`
);
if (!manifest) {
return { ...result, skipped: "not found on the npm registry" };
}
return {
...result,
deprecated: manifest.deprecated,
repository: repositoryUrl(manifest.repository),
provenance: Boolean(manifest.dist?.attestations),
};
};
const checkAll = async (dependencies: Dependency[]) => {
const results: Result[] = [];
for (let i = 0; i < dependencies.length; i += CONCURRENCY) {
results.push(
// eslint-disable-next-line no-await-in-loop
...(await Promise.all(
dependencies.slice(i, i + CONCURRENCY).map(checkPackage)
))
);
}
return results;
};
const writeSummary = async (core: Core, heading: string, results: Result[]) => {
await core.summary
.addHeading(heading, 2)
.addTable([
[
"Package",
"Version",
"Section",
"Deprecated",
"Provenance",
"Repository",
].map((data) => ({ data, header: true })),
...results.map((result) =>
result.skipped
? [
result.name,
result.version,
result.section,
`skipped: ${result.skipped}`,
"-",
"-",
]
: [
result.name,
result.version,
result.section,
result.deprecated ? "yes" : "no",
result.provenance ? "yes" : "no",
result.repository ?? "none",
]
),
])
.write();
};
export default async function checkNpmMetadata({
github,
context,
core,
}: GitHubScriptArgs<Payload>) {
const pr = context.payload.pull_request;
if (!pr) {
const pkg = await readPackageJson(github, context, context.sha);
const results = await checkAll(listDependencies(pkg));
const flagged = (result: Result) =>
Number(
Boolean(result.skipped || result.deprecated || !result.repository)
);
results.sort(
(a, b) => flagged(b) - flagged(a) || a.name.localeCompare(b.name)
);
await writeSummary(core, "Direct dependencies", results);
return;
}
const [base, head] = await Promise.all([
readPackageJson(github, context, pr.base.sha),
readPackageJson(github, context, pr.head.sha),
]);
// Compare the packages npm installs, so pointing an npm: alias at another
// package counts as new, but moving a package between sections does not
const existing = new Set(
listDependencies(base).map(({ registryName }) => registryName)
);
const added = listDependencies(head).filter(
({ registryName }) => !existing.has(registryName)
);
if (added.length === 0) {
core.info("No new dependencies");
return;
}
const results = await checkAll(added);
const annotation = { file: "package.json" };
for (const result of results) {
const label = `${result.name}@${result.version}`;
if (result.skipped) {
core.warning(`${label}: ${result.skipped}, not checked`, annotation);
continue;
}
if (result.deprecated) {
core.error(`${label} is deprecated: ${result.deprecated}`, annotation);
}
if (!result.repository) {
core.warning(`${label} has no source repository`, annotation);
}
if (!result.provenance) {
core.notice(`${label} was published without provenance`, annotation);
}
}
await writeSummary(core, "New dependencies", results);
if (results.some((result) => result.deprecated)) {
core.setFailed("New dependencies must not be deprecated on npm");
}
}
@@ -6,14 +6,20 @@
// via actions/github-script:
//
// const { default: checkStandards } =
// await import(`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-pull-request-standards.mjs`);
// await import(`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-pull-request-standards.mts`);
// await checkStandards({ github, context, core });
import type {
GitHubScriptArgs,
PullRequestPayload,
} from "./github-script.d.ts";
import { withRetry } from "./github-retry.mts";
export default async function checkPullRequestStandards({
github,
context,
core,
}) {
}: GitHubScriptArgs<PullRequestPayload>) {
const pr = context.payload.pull_request;
// Exempt bots (Copilot agent, dependabot), drafts, and maintainers.
@@ -26,10 +32,12 @@ export default async function checkPullRequestStandards({
return;
}
try {
await github.rest.orgs.checkMembershipForUser({
org: "home-assistant",
username: pr.user.login,
});
await withRetry("organization membership check", () =>
github.rest.orgs.checkMembershipForUser({
org: "home-assistant",
username: pr.user.login,
})
);
core.info(`Skipping organization member: ${pr.user.login}`);
return;
} catch (_error) {
@@ -52,11 +60,16 @@ export default async function checkPullRequestStandards({
const normalized = body.toLowerCase();
// Ignore 404s from mutations that race manual edits or cancelled runs.
const ignoreMissing = async (fn) => {
const ignoreMissing = async <T,>(fn: () => Promise<T>) => {
try {
await fn();
} catch (error) {
if (error.status === 404) {
if (
typeof error === "object" &&
error !== null &&
"status" in error &&
error.status === 404
) {
core.info("Target already removed, nothing to do");
return;
}
@@ -65,7 +78,7 @@ export default async function checkPullRequestStandards({
};
// Hide/restore our comment via GraphQL (REST cannot minimize).
const setMinimized = async (subjectId, minimized) => {
const setMinimized = async (subjectId: string, minimized: boolean) => {
const mutation = minimized
? `mutation($id: ID!) {
minimizeComment(input: { subjectId: $id, classifier: RESOLVED }) {
@@ -78,16 +91,18 @@ export default async function checkPullRequestStandards({
}
}`;
try {
await github.graphql(mutation, { id: subjectId });
await withRetry(`comment ${minimized ? "minimize" : "restore"}`, () =>
github.graphql(mutation, { id: subjectId })
);
} catch (error) {
core.info(
`Could not ${minimized ? "minimize" : "restore"} comment: ${error.message}`
`Could not ${minimized ? "minimize" : "restore"} comment: ${error instanceof Error ? error.message : error}`
);
}
};
// Content of a "## <name>" section, or null when the heading is absent.
const section = (name) => {
const section = (name: string) => {
const match = body.match(
new RegExp(`##\\s${name}([\\s\\S]*?)(?=\\n##\\s|$)`, "i")
);
@@ -122,13 +137,16 @@ export default async function checkPullRequestStandards({
const isValid = problems.length === 0;
const comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number,
per_page: 100,
});
const existing = comments.find((c) => c.body.includes(marker));
const comments = await withRetry("comment list", () =>
github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number,
per_page: 100,
})
);
const existing = comments.find((c) => c.body?.includes(marker));
const hasLabel = pr.labels.some((l) => l.name === label);
if (isValid) {
@@ -136,12 +154,14 @@ export default async function checkPullRequestStandards({
if (hasLabel) {
await ignoreMissing(() =>
github.rest.issues.removeLabel({
owner,
repo,
issue_number,
name: label,
})
withRetry("label removal", () =>
github.rest.issues.removeLabel({
owner,
repo,
issue_number,
name: label,
})
)
);
}
if (existing) {
@@ -153,12 +173,14 @@ export default async function checkPullRequestStandards({
core.info(`Pull request standards not met:\n- ${problems.join("\n- ")}`);
if (!hasLabel) {
await github.rest.issues.addLabels({
owner,
repo,
issue_number,
labels: [label],
});
await withRetry("label addition", () =>
github.rest.issues.addLabels({
owner,
repo,
issue_number,
labels: [label],
})
);
}
const message =
@@ -174,14 +196,17 @@ export default async function checkPullRequestStandards({
`for more on creating a great pull request (see point 6).`;
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body: message,
});
await withRetry("comment update", () =>
github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body: message,
})
);
await setMinimized(existing.node_id, false);
} else {
// Not retried, as a retry after GitHub created the comment would post it twice
await github.rest.issues.createComment({
owner,
repo,
@@ -5,29 +5,35 @@
// actions/github-script:
//
// const { default: checkTaskAuthorization } =
// await import(`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-task-authorization.mjs`);
// await import(`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-task-authorization.mts`);
// await checkTaskAuthorization({ github, context, core });
import type { GitHubScriptArgs, IssuePayload } from "./github-script.d.ts";
import { withRetry } from "./github-retry.mts";
export default async function checkTaskAuthorization({
github,
context,
core,
}) {
}: GitHubScriptArgs<IssuePayload>) {
const issueAuthor = context.payload.issue.user.login;
// Check if user is an organization member
try {
await github.rest.orgs.checkMembershipForUser({
org: "home-assistant",
username: issueAuthor,
});
await withRetry("organization membership check", () =>
github.rest.orgs.checkMembershipForUser({
org: "home-assistant",
username: issueAuthor,
})
);
core.info(`✅ ${issueAuthor} is an organization member`);
return; // Authorized
} catch (_error) {
core.info(`❌ ${issueAuthor} is not authorized to create Task issues`);
}
// Close the issue with a comment
// Close the issue with a comment. Not retried, as a retry after GitHub
// created the comment would post it twice.
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -41,18 +47,22 @@ export default async function checkTaskAuthorization({
`If you believe you should have access to create Task issues, please contact the maintainers.`,
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
state: "closed",
});
await withRetry("issue close", () =>
github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
state: "closed",
})
);
// Add a label to indicate this was auto-closed
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ["auto-closed"],
});
await withRetry("auto-closed label", () =>
github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ["auto-closed"],
})
);
}
+69
View File
@@ -0,0 +1,69 @@
// Retries GitHub API requests with jittered exponential backoff. Shared by the
// workflow scripts in this directory, test/e2e/post-report-comment.mjs and the
// fetch-nightly-translations gulp task. Only wrap requests that are safe to
// repeat: a create that fails after GitHub has applied it would run twice.
//
// This replaces @octokit/plugin-retry, which only retries HTTP error statuses
// on a fixed 1s, 4s, 9s delay with no jitter or logging. GitHub can also
// answer 200 with briefly stale data, such as the nightly translations lookup
// returning an old run with no artifact, and the plugin cannot retry that.
// github-script also leaves its built-in retries off by default.
const RETRIES = 3;
const BASE_DELAY = 1000; // ms
const MAX_DELAY = 10000; // ms
const TRANSIENT_STATUSES = new Set([408, 429, 500, 502, 503, 504]);
// Throw from a request to retry a response GitHub may answer differently on
// the next attempt, such as briefly stale data
export class RetryableError extends Error {}
// Octokit reports network failures as status 500
const isRetryable = (err: unknown) => {
if (err instanceof RetryableError) {
return true;
}
if (!(err instanceof Error) || !("status" in err)) {
return false;
}
const status = Number(err.status);
return (
TRANSIENT_STATUSES.has(status) ||
(status === 403 && /rate limit/i.test(err.message))
);
};
export async function withRetry<T>(
label: string,
request: () => Promise<T>
): Promise<T> {
for (let attempt = 1; ; attempt++) {
try {
// eslint-disable-next-line no-await-in-loop
return await request();
} catch (err) {
if (attempt > RETRIES || !isRetryable(err)) {
throw err;
}
const delay =
Math.min(BASE_DELAY * 2 ** (attempt - 1), MAX_DELAY) *
(0.8 + Math.random() * 0.4);
// eslint-disable-next-line no-console
console.log(
`Retrying ${label} after ${(delay / 1000).toFixed(1)}s (attempt ${attempt}/${RETRIES}): ${err instanceof Error ? err.message : err}`
);
// eslint-disable-next-line no-await-in-loop
await new Promise((resolve) => {
setTimeout(resolve, delay);
});
}
}
}
+61
View File
@@ -0,0 +1,61 @@
// The arguments actions/github-script passes to the scripts in this directory,
// limited to the parts they use.
import type { Octokit } from "@octokit/rest";
export type SummaryTableCell = string | { data: string; header?: boolean };
export interface Summary {
addHeading(text: string, level?: number): Summary;
addRaw(text: string): Summary;
addTable(rows: SummaryTableCell[][]): Summary;
write(): Promise<Summary>;
}
export interface AnnotationProperties {
file?: string;
}
export interface Core {
info(message: string): void;
notice(message: string, properties?: AnnotationProperties): void;
warning(message: string, properties?: AnnotationProperties): void;
error(message: string, properties?: AnnotationProperties): void;
setFailed(message: string): void;
summary: Summary;
}
export interface User {
login: string;
type: string;
}
export interface PullRequestPayload {
pull_request: {
number: number;
body: string | null;
draft: boolean;
user: User;
labels: { name: string }[];
base: { sha: string };
head: { sha: string };
};
}
export interface IssuePayload {
issue: {
user: User;
};
}
export interface Context<Payload> {
sha: string;
repo: { owner: string; repo: string };
issue: { owner: string; repo: string; number: number };
payload: Payload;
}
export interface GitHubScriptArgs<Payload> {
github: Octokit;
context: Context<Payload>;
core: Core;
}
+56
View File
@@ -0,0 +1,56 @@
/**
* Builds a section of a workflow run's summary: a heading, a table of rows and
* the warnings raised along the way.
*
* Warnings are also logged as annotations, so a script can report problems
* without failing its step.
*/
import type { AnnotationProperties, Core } from "./github-script.d.ts";
interface SummaryOptions {
heading: string;
columns: string[];
// Shown instead of the table when no rows were added
empty: string;
}
export const createSummary = (
core: Core,
{ heading, columns, empty }: SummaryOptions
) => {
const rows: string[][] = [];
const warnings: string[] = [];
return {
addRow: (...cells: string[]) => {
rows.push(cells);
},
warn: (message: string, properties?: AnnotationProperties) => {
core.warning(message, properties);
warnings.push(message);
},
write: async () => {
core.summary.addHeading(heading, 2);
if (rows.length > 0) {
core.summary.addTable([
columns.map((data) => ({ data, header: true })),
...rows,
]);
} else {
core.summary.addRaw(`${empty}\n`);
}
if (warnings.length > 0) {
core.summary
.addHeading("Warnings", 3)
.addRaw(`${warnings.map((warning) => `- ${warning}`).join("\n")}\n`);
}
await core.summary.write();
},
};
};
+324
View File
@@ -0,0 +1,324 @@
#!/usr/bin/env node
/**
* Applies the Companion App, Home Assistant Link, Labs and Supervisor labels
* to pull requests.
*
* These areas are often changed from code outside their folders, which
* actions/labeler can't see, so this script owns them and .github/labeler.yml
* leaves them out.
*
* A label matches when the pull request:
* - changes a file in one of the area's paths, or
* - adds or removes a line that uses the area's API, such as gating a feature
* behind Labs or only showing it on Supervisor installs.
*
* Like actions/labeler, a label is removed once the pull request no longer
* matches, including one added by hand.
*
* Invoked from the `triage` job in .github/workflows/labeler.yaml.
*/
import type {
GitHubScriptArgs,
PullRequestPayload,
} from "./github-script.d.ts";
import { withRetry } from "./github-retry.mts";
import { createSummary } from "./github-summary.mts";
const RULES: { label: string; paths: RegExp[]; pattern: RegExp }[] = [
{
label: "Companion App",
paths: [
/^src\/external_app\//,
/^src\/data\/external\.ts$/,
/^src\/util\/is_ios\.ts$/,
],
// Reads or messages the companion app the frontend is running in, or
// imports its modules. Matches imports of data/external rather than
// isExternal, which is also a common local name.
pattern:
/\bauth\??\.external\b(?:[!?]*\.\w+)*(?:\([^)]*)?|\bfireExternalBusMessage\([^)]*|(?:\bimport\s[^;]*?from\s*|\bimport\(\s*)["'][^"']*\/(?:external_app\/[^"']*|data\/external)["']/g,
},
{
label: "Home Assistant Link",
paths: [
/^src\/panels\/config\/cloud\//,
/^src\/data\/cloud\//,
/^src\/data\/cloud\.ts$/,
],
// Only runs when Home Assistant Link is set up
pattern: /isComponentLoaded\([^)]*["']cloud["']/g,
},
{
label: "Labs",
paths: [/^src\/panels\/config\/labs\//, /^src\/data\/labs\.ts$/],
// Gates a feature behind, or toggles, a Labs preview feature
pattern:
/\b(?:subscribeLabFeatures?|fetchLabFeatures|labsUpdatePreviewFeature)\([^)]*/g,
},
{
label: "Supervisor",
paths: [
/^src\/panels\/config\/apps\//,
/^src\/panels\/app\//,
/^src\/data\/hassio\//,
/^src\/data\/supervisor\//,
],
// Only runs on installs with the Supervisor
pattern: /isComponentLoaded\([^)]*["']hassio["']/g,
},
];
interface HunkSide {
lines: string[];
changed: boolean[];
}
interface CodeChange {
code: string;
filename: string;
}
const parseHunks = (patch: string) => {
const hunks: { before: HunkSide; after: HunkSide }[] = [];
for (const line of patch.split("\n")) {
if (line.startsWith("@@")) {
hunks.push({
before: { lines: [], changed: [] },
after: { lines: [], changed: [] },
});
continue;
}
const hunk = hunks.at(-1);
if (!hunk || line.startsWith("\\")) {
continue;
}
const text = line.slice(1);
if (!line.startsWith("+")) {
hunk.before.lines.push(text);
hunk.before.changed.push(line.startsWith("-"));
}
if (!line.startsWith("-")) {
hunk.after.lines.push(text);
hunk.after.changed.push(line.startsWith("+"));
}
}
return hunks;
};
// Ignores whitespace and trailing commas outside strings, as Prettier changes
// them when wrapping
const normaliseCode = (code: string) => {
const parts = code.split(
/("(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|`(?:[^`\\]|\\.)*`)/
);
return parts
.map((part, i) => {
if (i % 2 === 1) {
return part;
}
const stripped = part.replace(/\s+/g, "").replace(/,(?=[}\])])/g, "");
return i === parts.length - 1 ? stripped.replace(/,$/, "") : stripped;
})
.join("");
};
// Matches whole calls, which can span lines, that touch a changed line
const changedMatches = (side: HunkSide, pattern: RegExp) => {
const text = side.lines.join("\n");
const matches: string[] = [];
for (const match of text.matchAll(pattern)) {
const first = text.slice(0, match.index).split("\n").length - 1;
const last = first + match[0].split("\n").length - 1;
if (side.changed.slice(first, last + 1).some(Boolean)) {
matches.push(normaliseCode(match[0]));
}
}
return matches;
};
// Matches that were only moved, reindented or reformatted cancel out in pairs,
// returning a file with a match that doesn't
const unmatchedChange = (added: CodeChange[], removed: CodeChange[]) => {
const remaining = [...removed];
for (const change of added) {
const index = remaining.findIndex(({ code }) => code === change.code);
if (index === -1) {
return change.filename;
}
remaining.splice(index, 1);
}
return remaining[0]?.filename;
};
const describeError = (cause: unknown) =>
cause instanceof Error ? cause.message : String(cause);
const isNotFound = (cause: unknown) =>
cause instanceof Error && "status" in cause && cause.status === 404;
export default async function labelContent({
github,
context,
core,
}: GitHubScriptArgs<PullRequestPayload>) {
const pr = context.payload.pull_request;
const summary = createSummary(core, {
heading: "Content labels",
columns: ["Label", "Change", "Reason"],
empty: "No content labels changed.",
});
if (process.env.LABELER_OUTCOME === "failure") {
summary.warn(
"Applying labels from .github/labeler.yml failed, see its step"
);
}
// Bot pull requests, such as Prettier bumps, rewrite code they don't change
const checkCode = pr.user.type !== "Bot";
const { owner, repo } = context.repo;
let files;
let existing: Set<string>;
try {
// Read the current labels, as the event's snapshot can be stale by now
const [fileList, labels] = await Promise.all([
withRetry("pull request files", () =>
github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number: pr.number,
per_page: 100,
})
),
withRetry("pull request labels", () =>
github.paginate(github.rest.issues.listLabelsOnIssue, {
owner,
repo,
issue_number: pr.number,
per_page: 100,
})
),
]);
files = fileList;
existing = new Set(labels.map((l) => l.name));
} catch (error) {
summary.warn(
`Could not read the pull request's files and labels: ${describeError(error)}`
);
await summary.write();
return;
}
const add: { label: string; reason: string }[] = [];
const remove: string[] = [];
for (const rule of RULES) {
const added: CodeChange[] = [];
const removed: CodeChange[] = [];
if (checkCode) {
for (const { filename, patch } of files) {
for (const { before, after } of parseHunks(patch ?? "")) {
for (const code of changedMatches(after, rule.pattern)) {
added.push({ code, filename });
}
for (const code of changedMatches(before, rule.pattern)) {
removed.push({ code, filename });
}
}
}
}
// Renames count for both locations, as moving a file out of an area changes it
const match =
files.find(({ filename, previous_filename }) =>
rule.paths.some(
(path) =>
path.test(filename) ||
(previous_filename !== undefined && path.test(previous_filename))
)
)?.filename ?? unmatchedChange(added, removed);
if (match && !existing.has(rule.label)) {
core.info(`Adding ${rule.label} for ${match}`);
add.push({ label: rule.label, reason: match });
} else if (!match && existing.has(rule.label)) {
core.info(`Removing ${rule.label}, no longer matched`);
remove.push(rule.label);
}
}
const removals = await Promise.allSettled(
remove.map((name) =>
withRetry("label removal", () =>
github.rest.issues.removeLabel({
owner,
repo,
issue_number: pr.number,
name,
})
)
)
);
removals.forEach((removal, i) => {
const name = remove[i];
// Already removed, such as by hand or a run that raced this one
if (removal.status === "fulfilled" || isNotFound(removal.reason)) {
summary.addRow(name, "Removed", "No longer matched");
} else {
summary.warn(
`Could not remove ${name}: ${describeError(removal.reason)}`
);
}
});
if (add.length > 0) {
try {
await withRetry("label addition", () =>
github.rest.issues.addLabels({
owner,
repo,
issue_number: pr.number,
labels: add.map(({ label }) => label),
})
);
for (const { label, reason } of add) {
summary.addRow(label, "Added", reason);
}
} catch (error) {
summary.warn(
`Could not add ${add.map(({ label }) => label).join(", ")}: ${describeError(error)}`
);
}
}
await summary.write();
}
+19
View File
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2024",
"lib": ["ES2024"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
// actions/github-script imports these directly, relying on Node's type stripping
"erasableSyntaxOnly": true,
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"skipLibCheck": true,
"types": ["node"]
},
"include": ["*.mts", "*.d.ts"]
}
-35
View File
@@ -1,35 +0,0 @@
name: Blocking labels
on:
pull_request:
types:
- opened
- synchronize
- reopened
- labeled
- unlabeled
branches:
- dev
- master
permissions:
contents: read
jobs:
check:
name: Check for labels which block the Pull Request from being merged
runs-on: ubuntu-latest
steps:
- name: Check out workflow scripts
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
sparse-checkout: .github/scripts
- name: Check for blocking labels
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const { default: checkBlockingLabels } = await import(
`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-blocking-labels.mjs`
);
await checkBlockingLabels({ github, context, core });
+2 -2
View File
@@ -18,7 +18,7 @@ jobs:
deploy_dev:
runs-on: ubuntu-latest
name: Deploy Development
if: github.event_name != 'push'
if: github.repository == 'home-assistant/frontend' && github.event_name != 'push'
environment:
name: Cast Development
url: ${{ steps.deploy.outputs.netlify_url }}
@@ -50,7 +50,7 @@ jobs:
deploy_master:
runs-on: ubuntu-latest
name: Deploy Production
if: github.event_name == 'push'
if: github.repository == 'home-assistant/frontend' && github.event_name == 'push'
environment:
name: Cast Production
url: ${{ steps.deploy.outputs.netlify_url }}
+25 -9
View File
@@ -47,7 +47,7 @@ jobs:
with:
node-modules-cache: true
- name: Check for duplicate dependencies
run: yarn dedupe --check
run: pnpm dedupe --check
- name: Build resources
id: build_resources
run: ./node_modules/.bin/gulp gen-icons-json build-translations build-locale-data gather-gallery-pages
@@ -63,19 +63,22 @@ jobs:
key: lint-${{ github.sha }}
restore-keys: lint-
- name: Run eslint
run: yarn run lint:eslint --quiet
run: pnpm run lint:eslint --quiet
- name: Run tsc
if: ${{ !cancelled() && steps.build_resources.outcome == 'success' }}
run: yarn run lint:types
run: pnpm run lint:types
- name: Run lit-analyzer
if: ${{ !cancelled() && steps.build_resources.outcome == 'success' }}
run: yarn run lint:lit --quiet
run: pnpm run lint:lit --quiet
- name: Run prettier
if: ${{ !cancelled() && steps.build_resources.outcome == 'success' }}
run: yarn run lint:prettier
run: pnpm run lint:prettier
- name: Check dependency licenses
if: ${{ !cancelled() && steps.build_resources.outcome == 'success' }}
run: yarn run lint:licenses
run: pnpm run lint:licenses
- name: Check the bundled map sprite sheet
if: ${{ !cancelled() }}
run: ./node_modules/.bin/gulp check-map-sprites
test:
name: Run tests
needs: prepare-dependencies
@@ -94,11 +97,10 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run Tests
run: yarn run test
run: pnpm run test
build:
name: Build frontend
needs:
- prepare-dependencies
- lint
- test
runs-on: ubuntu-latest
@@ -111,12 +113,26 @@ jobs:
uses: ./.github/actions/setup
with:
node-modules-cache: true
# Read-only reuse of the rspack cache written by the nightly (see
# nightly.yaml). rspack itself decides what is still valid (version +
# buildDependencies + node_modules snapshot), so the GHA key just restores
# the latest nightly cache; no fingerprint, and no save step (CI never
# writes the shared cache).
- name: Restore rspack cache
continue-on-error: true
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .rspack-cache
key: rspack-cache-${{ runner.os }}-${{ github.run_id }}
restore-keys: |
rspack-cache-${{ runner.os }}-
- name: Build Application
uses: ./.github/actions/build
with:
target: build-app
github-token: ${{ secrets.GITHUB_TOKEN }}
is-test: true
rspack-cache: readonly
- name: Upload bundle stats
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
@@ -124,7 +140,7 @@ jobs:
path: build/stats/*.json
if-no-files-found: error
- name: Check entrypoint bundle size budget
run: yarn run check-bundlesize
run: pnpm run check-bundlesize
- name: Upload frontend build
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
+2 -2
View File
@@ -32,12 +32,12 @@ jobs:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
languages: javascript-typescript
build-mode: none
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
category: "/language:javascript-typescript"
+2 -2
View File
@@ -19,7 +19,7 @@ jobs:
deploy_dev:
runs-on: ubuntu-latest
name: Demo Development
if: github.event_name != 'push' || github.ref_name != 'master'
if: github.repository == 'home-assistant/frontend' && (github.event_name != 'push' || github.ref_name != 'master')
environment:
name: Demo Development
url: ${{ steps.deploy.outputs.unique_deploy_url }}
@@ -50,7 +50,7 @@ jobs:
deploy_master:
runs-on: ubuntu-latest
name: Demo Production
if: github.event_name == 'push' && github.ref_name == 'master'
if: github.repository == 'home-assistant/frontend' && github.event_name == 'push' && github.ref_name == 'master'
environment:
name: Demo Production
url: ${{ steps.deploy.outputs.netlify_url }}
+55
View File
@@ -0,0 +1,55 @@
name: Dependency review
on:
pull_request:
branches:
- dev
paths:
- package.json
- pnpm-lock.yaml
- pnpm-workspace.yaml
schedule:
- cron: "0 6 1 * *" # Monthly report on all direct dependencies
workflow_dispatch:
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
dependency-review:
name: Review dependency changes
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read # To compare the dependency graph between base and head
steps:
- name: Dependency review
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
with:
license-check: false # Covered by pnpm lint:licenses
fail-on-severity: high
show-openssf-scorecard: true
warn-on-openssf-scorecard-level: 3
npm-metadata:
name: Check npm metadata
runs-on: ubuntu-latest
permissions:
contents: read # To read package.json
steps:
- name: Check out workflow scripts
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
sparse-checkout: .github/scripts
- name: Check npm metadata
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const { default: checkNpmMetadata } = await import(
`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-npm-metadata.mts`
);
await checkNpmMetadata({ github, context, core });
+1
View File
@@ -13,6 +13,7 @@ env:
jobs:
deploy:
if: github.repository == 'home-assistant/frontend'
runs-on: ubuntu-latest
environment:
name: Design
+8 -7
View File
@@ -38,7 +38,7 @@ jobs:
name: Prepare container dependencies
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.62.1-noble
image: mcr.microsoft.com/playwright:v1.64.0-noble
options: --user 1001
defaults:
run:
@@ -137,6 +137,7 @@ jobs:
with:
target: build-gallery
github-token: ${{ secrets.GITHUB_TOKEN }}
is-test: true
- name: Upload gallery build
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -154,7 +155,7 @@ jobs:
- prepare-container-dependencies
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.62.1-noble
image: mcr.microsoft.com/playwright:v1.64.0-noble
options: --user 1001 --ipc=host
defaults:
run:
@@ -187,7 +188,7 @@ jobs:
path: demo/dist/
- name: Run Playwright demo tests
run: yarn test:e2e:demo --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
run: pnpm run test:e2e:demo --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
timeout-minutes: 15
- name: Upload demo blob report
@@ -206,7 +207,7 @@ jobs:
- prepare-container-dependencies
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.62.1-noble
image: mcr.microsoft.com/playwright:v1.64.0-noble
options: --user 1001 --ipc=host
defaults:
run:
@@ -241,7 +242,7 @@ jobs:
path: test/e2e/app/dist/
- name: Run Playwright app tests
run: yarn test:e2e:app --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
run: pnpm run test:e2e:app --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
timeout-minutes: 15
- name: Upload app blob report
@@ -260,7 +261,7 @@ jobs:
- prepare-container-dependencies
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.62.1-noble
image: mcr.microsoft.com/playwright:v1.64.0-noble
options: --user 1001 --ipc=host
defaults:
run:
@@ -295,7 +296,7 @@ jobs:
path: gallery/dist/
- name: Run Playwright gallery tests
run: yarn test:e2e:gallery --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
run: pnpm run test:e2e:gallery --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
timeout-minutes: 15
- name: Upload gallery blob report
+24 -1
View File
@@ -1,6 +1,11 @@
name: "Pull Request Labeler"
on: pull_request_target # zizmor: ignore[dangerous-triggers] -- safe: only runs actions/labeler, no PR code checkout
on: pull_request_target # zizmor: ignore[dangerous-triggers] -- safe: checks out base repo scripts only and reads PR files through the API, never PR head code
# Runs one at a time per pull request, so an older run can't undo a newer one
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
triage:
@@ -10,6 +15,24 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Apply labels
id: labeler
continue-on-error: true
uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
with:
sync-labels: true
- name: Check out workflow scripts
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
sparse-checkout: .github/scripts
- name: Apply content labels
continue-on-error: true
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
LABELER_OUTCOME: ${{ steps.labeler.outcome }}
with:
script: |
const { default: labelContent } = await import(
`${process.env.GITHUB_WORKSPACE}/.github/scripts/label-content.mts`
);
await labelContent({ github, context, core });
+1
View File
@@ -11,6 +11,7 @@ permissions:
jobs:
lock:
if: github.repository == 'home-assistant/frontend'
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@89ae32b08ed1a541efecbab17912962a5e38981c # v6.0.2
+27 -2
View File
@@ -14,6 +14,7 @@ permissions:
jobs:
nightly:
if: github.repository == 'home-assistant/frontend'
name: Nightly
runs-on: ubuntu-latest
permissions:
@@ -58,18 +59,33 @@ jobs:
restore-keys: |
compress-cache-${{ runner.os }}-
# The nightly writes the rspack persistent cache; CI reads it read-only
# (see ci.yaml). rspack invalidates internally (version + buildDependencies
# + node_modules snapshot), so the cache rolls forward daily and a single
# dependency bump keeps most of it warm instead of dropping the lineage.
- name: Restore rspack cache
id: rspack-cache
continue-on-error: true
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .rspack-cache
key: rspack-cache-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }}
restore-keys: |
rspack-cache-${{ runner.os }}-
- name: Build nightly Python wheels
env:
COMPRESS_CACHE_DIR: ${{ github.workspace }}/.compress-cache
RSPACK_CACHE: readwrite
run: |
pip install build
yarn install
pnpm install --frozen-lockfile
export SKIP_FETCH_NIGHTLY_TRANSLATIONS=1
script/build_frontend
rm -rf dist home_assistant_frontend.egg-info
python3 -m build
# Not gated on the restore step: a transient restore failure (it is
# Not gated on the restore steps: a transient restore failure (they are
# continue-on-error) must not stop us persisting a freshly built cache.
- name: Save compression cache
if: success()
@@ -79,6 +95,14 @@ jobs:
path: .compress-cache
key: compress-cache-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }}
- name: Save rspack cache
if: success()
continue-on-error: true
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .rspack-cache
key: rspack-cache-${{ runner.os }}-${{ github.run_id }}-${{ github.run_attempt }}
- name: Upload build artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
@@ -90,6 +114,7 @@ jobs:
# needed for the uploaded artifact, not the wheel, so they are downloaded in
# parallel here instead of blocking the build above.
translations:
if: github.repository == 'home-assistant/frontend'
name: Translations
runs-on: ubuntu-latest
steps:
@@ -33,6 +33,6 @@ jobs:
with:
script: |
const { default: checkStandards } = await import(
`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-pull-request-standards.mjs`
`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-pull-request-standards.mts`
);
await checkStandards({ github, context, core });
+4 -4
View File
@@ -14,11 +14,11 @@ permissions:
jobs:
upload-frontend-modern:
name: Upload stats (frontend/modern)
if: ${{ github.event.workflow_run.conclusion == 'success' }}
if: ${{ github.repository == 'home-assistant/frontend' && github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- name: Send bundle stats and build information to RelativeCI
uses: relative-ci/agent-action@fcf45416581928e8dd62eded78ce98c78e5149f8 # v3.2.3
uses: relative-ci/agent-action@711f3a8fa1b928e6afde280011110c9b0a224a60 # v3.2.4
with:
key: ${{ secrets.RELATIVE_CI_KEY_frontend_modern }}
token: ${{ github.token }}
@@ -27,11 +27,11 @@ jobs:
upload-frontend-legacy:
name: Upload stats (frontend/legacy)
if: ${{ github.event.workflow_run.conclusion == 'success' }}
if: ${{ github.repository == 'home-assistant/frontend' && github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- name: Send bundle stats and build information to RelativeCI
uses: relative-ci/agent-action@fcf45416581928e8dd62eded78ce98c78e5149f8 # v3.2.3
uses: relative-ci/agent-action@711f3a8fa1b928e6afde280011110c9b0a224a60 # v3.2.4
with:
key: ${{ secrets.RELATIVE_CI_KEY_frontend_legacy }}
token: ${{ github.token }}
+2 -1
View File
@@ -10,6 +10,7 @@ permissions:
jobs:
update_release_draft:
if: github.repository == 'home-assistant/frontend'
permissions:
# write permission for contents is required to create a github release
contents: write
@@ -18,6 +19,6 @@ jobs:
pull-requests: read
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@34d80673e067bdc0c24568d3af899c216adcfaa9 # v7.7.0
- uses: release-drafter/release-drafter@72967cdc98ddd3160f1fc3dff619de365e137dd0 # v7.9.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+2 -2
View File
@@ -36,7 +36,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
- name: Verify version
uses: home-assistant/actions/helpers/verify-version@a7c616ce81ccda50150bf1595786c71b1883fabb # master
uses: home-assistant/actions/helpers/verify-version@06749dd8c0b54f350bc69c8752456cee498808a3 # master
- name: Setup Node and install
uses: ./.github/actions/setup
@@ -136,7 +136,7 @@ jobs:
release-landing-page:
name: Release landing-page frontend
if: github.event.release.prerelease == false
if: github.repository == 'home-assistant/frontend' && github.event.release.prerelease == false
runs-on: ubuntu-latest
permissions:
contents: write # Required to upload release assets
+18 -7
View File
@@ -15,22 +15,33 @@ jobs:
name: Add no-stale label
runs-on: ubuntu-latest
permissions:
contents: read # To check out workflow scripts
issues: write # To add labels to issues
if: >-
github.event.issue.type.name == 'Task'
|| github.event.issue.type.name == 'Epic'
|| github.event.issue.type.name == 'Opportunity'
steps:
- name: Check out workflow scripts
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
sparse-checkout: .github/scripts
- name: Add no-stale label
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['no-stale']
});
const { withRetry } = await import(
`${process.env.GITHUB_WORKSPACE}/.github/scripts/github-retry.mts`
);
await withRetry("no-stale label", () =>
github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['no-stale']
})
);
check-authorization:
name: Check authorization
@@ -51,6 +62,6 @@ jobs:
with:
script: |
const { default: checkTaskAuthorization } = await import(
`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-task-authorization.mjs`
`${process.env.GITHUB_WORKSPACE}/.github/scripts/check-task-authorization.mts`
);
await checkTaskAuthorization({ github, context, core });
+4 -2
View File
@@ -12,13 +12,15 @@ permissions:
jobs:
stale:
if: github.repository == 'home-assistant/frontend'
runs-on: ubuntu-latest
steps:
- name: 90 days stale policy
- name: Stale policy
uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
days-before-stale: 90
days-before-issue-stale: 90
days-before-pr-stale: 60
days-before-close: 7
operations-per-run: 25
remove-stale-when-updated: true
@@ -0,0 +1,48 @@
name: Sync device class constants
# Mirrors the device class constants for Home Assistant Core's into the
# build-time default in src/data/device_classes.ts and opens a PR
# when it drifts. Reads homeassistant/generated/device_classes.json from core.
on:
workflow_dispatch:
schedule:
- cron: "0 4 * * *" # Daily, 04:00 UTC
permissions:
contents: read
jobs:
sync:
if: github.repository == 'home-assistant/frontend'
name: Sync
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Node and install
uses: ./.github/actions/setup
- name: Regenerate device class constants
run: ./script/gen_device_classes
- name: Format
run: pnpm exec prettier --write src/data/device_classes.ts
- name: Create pull request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
branch: chore/sync-device-classes
commit-message: Update device class constants
title: Update device class constants
body: |
Regenerated `DOMAIN_DEVICE_CLASSES` from Home Assistant Core's
`homeassistant/generated/device_classes.json`.
Automated by `.github/workflows/sync-device-classes.yaml`.
@@ -1,47 +0,0 @@
name: Sync numeric device classes
# Mirrors Home Assistant Core's numeric `SensorDeviceClass` list into the
# build-time default in src/data/sensor_numeric_device_classes.ts and opens a PR
# when it drifts. Reads homeassistant/generated/sensor.json from core.
on:
workflow_dispatch:
schedule:
- cron: "0 4 * * *" # Daily, 04:00 UTC
permissions:
contents: read
jobs:
sync:
name: Sync
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Node and install
uses: ./.github/actions/setup
- name: Regenerate numeric device classes
run: ./script/gen_numeric_device_classes
- name: Format
run: yarn prettier --write src/data/sensor_numeric_device_classes.ts
- name: Create pull request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
branch: chore/sync-numeric-device-classes
commit-message: Update numeric sensor device classes
title: Update numeric sensor device classes
body: |
Regenerated `SENSOR_NUMERIC_DEVICE_CLASSES` from Home Assistant Core's
`SensorDeviceClass`.
Automated by `.github/workflows/sync-numeric-device-classes.yaml`.
@@ -0,0 +1,49 @@
name: Sync sensor entity constants
# Mirrors Home Assistant Core's numeric `SensorDeviceClass`, `SensorStateClass`,
# units and related device and state classes arrays into the
# build-time default in src/data/sensor_entity_constants.ts and opens a PR
# when it drifts. Reads homeassistant/generated/sensor.json from core.
on:
workflow_dispatch:
schedule:
- cron: "0 4 * * *" # Daily, 04:00 UTC
permissions:
contents: read
jobs:
sync:
if: github.repository == 'home-assistant/frontend'
name: Sync
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout the repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Node and install
uses: ./.github/actions/setup
- name: Regenerate sensor entity constants
run: ./script/gen_sensor_entity_constants
- name: Format
run: pnpm exec prettier --write src/data/sensor_entity_constants.ts
- name: Create pull request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
branch: chore/sync-sensor-entity-constants
commit-message: Update sensor entity constants
title: Update sensor entity constants
body: |
Regenerated the sensor entity constants from Home Assistant Core's
`homeassistant/generated/sensor.json`.
Automated by `.github/workflows/sync-sensor-entity-constants.yaml`.
+1
View File
@@ -15,6 +15,7 @@ permissions:
jobs:
upload:
name: Upload
if: github.repository == 'home-assistant/frontend'
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
+4 -9
View File
@@ -7,20 +7,14 @@ dist/
/hass_frontend/
/translations/
/.compress-cache/
/.rspack-cache/
# Composite action source, not build output
!/.github/actions/build/
# yarn
.yarn/*
!.yarn/patches
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*
# Node
node_modules/
yarn-error.log
npm-debug.log
.pnpm-store/
# Python stuff
*.py[cod]
@@ -73,3 +67,4 @@ test/e2e/app/dist/
.serena
test/benchmarks/results/
+1 -1
View File
@@ -1 +1 @@
yarn run lint-staged --relative
pnpm exec lint-staged --relative
+1 -1
View File
@@ -1 +1 @@
24.19.0
24.21.0
+3 -1
View File
@@ -1,4 +1,6 @@
CLA.md
CODE_OF_CONDUCT.md
LICENSE.md
PULL_REQUEST_TEMPLATE.md
PULL_REQUEST_TEMPLATE.md
public/static/map/sprites/*.json
pnpm-lock.yaml
@@ -1,22 +0,0 @@
diff --git a/mwc-formfield-base.js b/mwc-formfield-base.js
index 7b763326d7d51835ad52646bfbc80fe21989abd3..f2baa8224e6d03df1fdb0b9fd03f5c6d77fc8747 100644
--- a/mwc-formfield-base.js
+++ b/mwc-formfield-base.js
@@ -9,7 +9,7 @@ import { BaseElement } from '@material/mwc-base/base-element.js';
import { FormElement } from '@material/mwc-base/form-element.js';
import { observer } from '@material/mwc-base/observer.js';
import { html } from 'lit';
-import { property, query, queryAssignedNodes } from 'lit/decorators.js';
+import { property, query, queryAssignedElements } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
export class FormfieldBase extends BaseElement {
constructor() {
@@ -96,7 +96,7 @@ __decorate([
query('.mdc-form-field')
], FormfieldBase.prototype, "mdcRoot", void 0);
__decorate([
- queryAssignedNodes('', true, '*')
+ queryAssignedElements({ slot: "", flatten: true, selector: "*" })
], FormfieldBase.prototype, "slottedInputs", void 0);
__decorate([
query('label')
@@ -1,13 +0,0 @@
diff --git a/dist/leaflet.draw.js b/dist/leaflet.draw.js
index 71aeb33b49192dac65f869795716fc3e34969b7e..9be93575809b224c3100fbb9cca72de4bce3faf4 100644
--- a/dist/leaflet.draw.js
+++ b/dist/leaflet.draw.js
@@ -5,6 +5,7 @@
https://github.com/Leaflet/Leaflet.draw
http://leafletjs.com
*/
+var radius;
!function(t,e,i){function o(t,e){for(;(t=t.parentElement)&&!t.classList.contains(e););return t}L.drawVersion="1.0.4",L.Draw={},L.drawLocal={draw:{toolbar:{actions:{title:"Cancel drawing",text:"Cancel"},finish:{title:"Finish drawing",text:"Finish"},undo:{title:"Delete last point drawn",text:"Delete last point"},buttons:{polyline:"Draw a polyline",polygon:"Draw a polygon",rectangle:"Draw a rectangle",circle:"Draw a circle",marker:"Draw a marker",circlemarker:"Draw a circlemarker"}},handlers:{circle:{tooltip:{start:"Click and drag to draw circle."},radius:"Radius"},circlemarker:{tooltip:{start:"Click map to place circle marker."}},marker:{tooltip:{start:"Click map to place marker."}},polygon:{tooltip:{start:"Click to start drawing shape.",cont:"Click to continue drawing shape.",end:"Click first point to close this shape."}},polyline:{error:"<strong>Error:</strong> shape edges cannot cross!",tooltip:{start:"Click to start drawing line.",cont:"Click to continue drawing line.",end:"Click last point to finish line."}},rectangle:{tooltip:{start:"Click and drag to draw rectangle."}},simpleshape:{tooltip:{end:"Release mouse to finish drawing."}}}},edit:{toolbar:{actions:{save:{title:"Save changes",text:"Save"},cancel:{title:"Cancel editing, discards all changes",text:"Cancel"},clearAll:{title:"Clear all layers",text:"Clear All"}},buttons:{edit:"Edit layers",editDisabled:"No layers to edit",remove:"Delete layers",removeDisabled:"No layers to delete"}},handlers:{edit:{tooltip:{text:"Drag handles or markers to edit features.",subtext:"Click cancel to undo changes."}},remove:{tooltip:{text:"Click on a feature to remove."}}}}},L.Draw.Event={},L.Draw.Event.CREATED="draw:created",L.Draw.Event.EDITED="draw:edited",L.Draw.Event.DELETED="draw:deleted",L.Draw.Event.DRAWSTART="draw:drawstart",L.Draw.Event.DRAWSTOP="draw:drawstop",L.Draw.Event.DRAWVERTEX="draw:drawvertex",L.Draw.Event.EDITSTART="draw:editstart",L.Draw.Event.EDITMOVE="draw:editmove",L.Draw.Event.EDITRESIZE="draw:editresize",L.Draw.Event.EDITVERTEX="draw:editvertex",L.Draw.Event.EDITSTOP="draw:editstop",L.Draw.Event.DELETESTART="draw:deletestart",L.Draw.Event.DELETESTOP="draw:deletestop",L.Draw.Event.TOOLBAROPENED="draw:toolbaropened",L.Draw.Event.TOOLBARCLOSED="draw:toolbarclosed",L.Draw.Event.MARKERCONTEXT="draw:markercontext",L.Draw=L.Draw||{},L.Draw.Feature=L.Handler.extend({initialize:function(t,e){this._map=t,this._container=t._container,this._overlayPane=t._panes.overlayPane,this._popupPane=t._panes.popupPane,e&&e.shapeOptions&&(e.shapeOptions=L.Util.extend({},this.options.shapeOptions,e.shapeOptions)),L.setOptions(this,e);var i=L.version.split(".");1===parseInt(i[0],10)&&parseInt(i[1],10)>=2?L.Draw.Feature.include(L.Evented.prototype):L.Draw.Feature.include(L.Mixin.Events)},enable:function(){this._enabled||(L.Handler.prototype.enable.call(this),this.fire("enabled",{handler:this.type}),this._map.fire(L.Draw.Event.DRAWSTART,{layerType:this.type}))},disable:function(){this._enabled&&(L.Handler.prototype.disable.call(this),this._map.fire(L.Draw.Event.DRAWSTOP,{layerType:this.type}),this.fire("disabled",{handler:this.type}))},addHooks:function(){var t=this._map;t&&(L.DomUtil.disableTextSelection(),t.getContainer().focus(),this._tooltip=new L.Draw.Tooltip(this._map),L.DomEvent.on(this._container,"keyup",this._cancelDrawing,this))},removeHooks:function(){this._map&&(L.DomUtil.enableTextSelection(),this._tooltip.dispose(),this._tooltip=null,L.DomEvent.off(this._container,"keyup",this._cancelDrawing,this))},setOptions:function(t){L.setOptions(this,t)},_fireCreatedEvent:function(t){this._map.fire(L.Draw.Event.CREATED,{layer:t,layerType:this.type})},_cancelDrawing:function(t){27===t.keyCode&&(this._map.fire("draw:canceled",{layerType:this.type}),this.disable())}}),L.Draw.Polyline=L.Draw.Feature.extend({statics:{TYPE:"polyline"},Poly:L.Polyline,options:{allowIntersection:!0,repeatMode:!1,drawError:{color:"#b00b00",timeout:2500},icon:new L.DivIcon({iconSize:new L.Point(8,8),className:"leaflet-div-icon leaflet-editing-icon"}),touchIcon:new L.DivIcon({iconSize:new L.Point(20,20),className:"leaflet-div-icon leaflet-editing-icon leaflet-touch-icon"}),guidelineDistance:20,maxGuideLineLength:4e3,shapeOptions:{stroke:!0,color:"#3388ff",weight:4,opacity:.5,fill:!1,clickable:!0},metric:!0,feet:!0,nautic:!1,showLength:!0,zIndexOffset:2e3,factor:1,maxPoints:0},initialize:function(t,e){L.Browser.touch&&(this.options.icon=this.options.touchIcon),this.options.drawError.message=L.drawLocal.draw.handlers.polyline.error,e&&e.drawError&&(e.drawError=L.Util.extend({},this.options.drawError,e.drawError)),this.type=L.Draw.Polyline.TYPE,L.Draw.Feature.prototype.initialize.call(this,t,e)},addHooks:function(){L.Draw.Feature.prototype.addHooks.call(this),this._map&&(this._markers=[],this._markerGroup=new L.LayerGroup,this._map.addLayer(this._markerGroup),this._poly=new L.Polyline([],this.options.shapeOptions),this._tooltip.updateContent(this._getTooltipText()),this._mouseMarker||(this._mouseM Line truncated
className:"leaflet-div-icon leaflet-editing-icon leaflet-edit-resize"}),touchMoveIcon:new L.DivIcon({iconSize:new L.Point(20,20),className:"leaflet-div-icon leaflet-editing-icon leaflet-edit-move leaflet-touch-icon"}),touchResizeIcon:new L.DivIcon({iconSize:new L.Point(20,20),className:"leaflet-div-icon leaflet-editing-icon leaflet-edit-resize leaflet-touch-icon"})},initialize:function(t,e){L.Browser.touch&&(this.options.moveIcon=this.options.touchMoveIcon,this.options.resizeIcon=this.options.touchResizeIcon),this._shape=t,L.Util.setOptions(this,e)},addHooks:function(){var t=this._shape;this._shape._map&&(this._map=this._shape._map,t.setStyle(t.options.editing),t._map&&(this._map=t._map,this._markerGroup||this._initMarkers(),this._map.addLayer(this._markerGroup)))},removeHooks:function(){var t=this._shape;if(t.setStyle(t.options.original),t._map){this._unbindMarker(this._moveMarker);for(var e=0,i=this._resizeMarkers.length;e<i;e++)this._unbindMarker(this._resizeMarkers[e]);this._resizeMarkers=null,this._map.removeLayer(this._markerGroup),delete this._markerGroup}this._map=null},updateMarkers:function(){this._markerGroup.clearLayers(),this._initMarkers()},_initMarkers:function(){this._markerGroup||(this._markerGroup=new L.LayerGroup),this._createMoveMarker(),this._createResizeMarker()},_createMoveMarker:function(){},_createResizeMarker:function(){},_createMarker:function(t,e){var i=new L.Marker.Touch(t,{draggable:!0,icon:e,zIndexOffset:10});return this._bindMarker(i),this._markerGroup.addLayer(i),i},_bindMarker:function(t){t.on("dragstart",this._onMarkerDragStart,this).on("drag",this._onMarkerDrag,this).on("dragend",this._onMarkerDragEnd,this).on("touchstart",this._onTouchStart,this).on("touchmove",this._onTouchMove,this).on("MSPointerMove",this._onTouchMove,this).on("touchend",this._onTouchEnd,this).on("MSPointerUp",this._onTouchEnd,this)},_unbindMarker:function(t){t.off("dragstart",this._onMarkerDragStart,this).off("drag",this._onMarkerDrag,this).off("dragend",this._onMarkerDragEnd,this).off("touchstart",this._onTouchStart,this).off("touchmove",this._onTouchMove,this).off("MSPointerMove",this._onTouchMove,this).off("touchend",this._onTouchEnd,this).off("MSPointerUp",this._onTouchEnd,this)},_onMarkerDragStart:function(t){t.target.setOpacity(0),this._shape.fire("editstart")},_fireEdit:function(){this._shape.edited=!0,this._shape.fire("edit")},_onMarkerDrag:function(t){var e=t.target,i=e.getLatLng();e===this._moveMarker?this._move(i):this._resize(i),this._shape.redraw(),this._shape.fire("editdrag")},_onMarkerDragEnd:function(t){t.target.setOpacity(1),this._fireEdit()},_onTouchStart:function(t){if(L.Edit.SimpleShape.prototype._onMarkerDragStart.call(this,t),"function"==typeof this._getCorners){var e=this._getCorners(),i=t.target,o=i._cornerIndex;i.setOpacity(0),this._oppositeCorner=e[(o+2)%4],this._toggleCornerMarkers(0,o)}this._shape.fire("editstart")},_onTouchMove:function(t){var e=this._map.mouseEventToLayerPoint(t.originalEvent.touches[0]),i=this._map.layerPointToLatLng(e);return t.target===this._moveMarker?this._move(i):this._resize(i),this._shape.redraw(),!1},_onTouchEnd:function(t){t.target.setOpacity(1),this.updateMarkers(),this._fireEdit()},_move:function(){},_resize:function(){}}),L.Edit=L.Edit||{},L.Edit.Rectangle=L.Edit.SimpleShape.extend({_createMoveMarker:function(){var t=this._shape.getBounds(),e=t.getCenter();this._moveMarker=this._createMarker(e,this.options.moveIcon)},_createResizeMarker:function(){var t=this._getCorners();this._resizeMarkers=[];for(var e=0,i=t.length;e<i;e++)this._resizeMarkers.push(this._createMarker(t[e],this.options.resizeIcon)),this._resizeMarkers[e]._cornerIndex=e},_onMarkerDragStart:function(t){L.Edit.SimpleShape.prototype._onMarkerDragStart.call(this,t);var e=this._getCorners(),i=t.target,o=i._cornerIndex;this._oppositeCorner=e[(o+2)%4],this._toggleCornerMarkers(0,o)},_onMarkerDragEnd:function(t){var e,i,o=t.target;o===this._moveMarker&&(e=this._shape.getBounds(),i=e.getCenter(),o.setLatLng(i)),this._toggleCornerMarkers(1),this._repositionCornerMarkers(),L.Edit.SimpleShape.prototype._onMarkerDragEnd.call(this,t)},_move:function(t){for(var e,i=this._shape._defaultShape?this._shape._defaultShape():this._shape.getLatLngs(),o=this._shape.getBounds(),a=o.getCenter(),n=[],s=0,r=i.length;s<r;s++)e=[i[s].lat-a.lat,i[s].lng-a.lng],n.push([t.lat+e[0],t.lng+e[1]]);this._shape.setLatLngs(n),this._repositionCornerMarkers(),this._map.fire(L.Draw.Event.EDITMOVE,{layer:this._shape})},_resize:function(t){var e;this._shape.setBounds(L.latLngBounds(t,this._oppositeCorner)),e=this._shape.getBounds(),this._moveMarker.setLatLng(e.getCenter()),this._map.fire(L.Draw.Event.EDITRESIZE,{layer:this._shape})},_getCorners:function(){var t=this._shape.getBounds();return[t.getNorthWest(),t.getNorthEast(),t.getSouthEast(),t.getSouthWest()]},_toggleCornerMarkers:function(t){for(var e=0,i=this._resizeMarkers.length;e<i;e++)this._resizeMarkers[e].setOpacity(t)},_repositionCornerMarkers:function(){for( Line truncated
this._selectedPathOptions&&(e instanceof L.Marker?this._toggleMarkerHighlight(e):(e.setStyle(e.options.previousOptions),delete e.options.previousOptions)),e instanceof L.Marker?(e.dragging.disable(),e.off("dragend",this._onMarkerDragEnd,this).off("touchmove",this._onTouchMove,this).off("MSPointerMove",this._onTouchMove,this).off("touchend",this._onMarkerDragEnd,this).off("MSPointerUp",this._onMarkerDragEnd,this)):e.editing.disable()},_onMouseMove:function(t){this._tooltip.updatePosition(t.latlng)},_onMarkerDragEnd:function(t){var e=t.target;e.edited=!0,this._map.fire(L.Draw.Event.EDITMOVE,{layer:e})},_onTouchMove:function(t){var e=t.originalEvent.changedTouches[0],i=this._map.mouseEventToLayerPoint(e),o=this._map.layerPointToLatLng(i);t.target.setLatLng(o)},_hasAvailableLayers:function(){return 0!==this._featureGroup.getLayers().length}}),L.EditToolbar.Delete=L.Handler.extend({statics:{TYPE:"remove"},initialize:function(t,e){if(L.Handler.prototype.initialize.call(this,t),L.Util.setOptions(this,e),this._deletableLayers=this.options.featureGroup,!(this._deletableLayers instanceof L.FeatureGroup))throw new Error("options.featureGroup must be a L.FeatureGroup");this.type=L.EditToolbar.Delete.TYPE;var i=L.version.split(".");1===parseInt(i[0],10)&&parseInt(i[1],10)>=2?L.EditToolbar.Delete.include(L.Evented.prototype):L.EditToolbar.Delete.include(L.Mixin.Events)},enable:function(){!this._enabled&&this._hasAvailableLayers()&&(this.fire("enabled",{handler:this.type}),this._map.fire(L.Draw.Event.DELETESTART,{handler:this.type}),L.Handler.prototype.enable.call(this),this._deletableLayers.on("layeradd",this._enableLayerDelete,this).on("layerremove",this._disableLayerDelete,this))},disable:function(){this._enabled&&(this._deletableLayers.off("layeradd",this._enableLayerDelete,this).off("layerremove",this._disableLayerDelete,this),L.Handler.prototype.disable.call(this),this._map.fire(L.Draw.Event.DELETESTOP,{handler:this.type}),this.fire("disabled",{handler:this.type}))},addHooks:function(){var t=this._map;t&&(t.getContainer().focus(),this._deletableLayers.eachLayer(this._enableLayerDelete,this),this._deletedLayers=new L.LayerGroup,this._tooltip=new L.Draw.Tooltip(this._map),this._tooltip.updateContent({text:L.drawLocal.edit.handlers.remove.tooltip.text}),this._map.on("mousemove",this._onMouseMove,this))},removeHooks:function(){this._map&&(this._deletableLayers.eachLayer(this._disableLayerDelete,this),this._deletedLayers=null,this._tooltip.dispose(),this._tooltip=null,this._map.off("mousemove",this._onMouseMove,this))},revertLayers:function(){this._deletedLayers.eachLayer(function(t){this._deletableLayers.addLayer(t),t.fire("revert-deleted",{layer:t})},this)},save:function(){this._map.fire(L.Draw.Event.DELETED,{layers:this._deletedLayers})},removeAllLayers:function(){this._deletableLayers.eachLayer(function(t){this._removeLayer({layer:t})},this),this.save()},_enableLayerDelete:function(t){(t.layer||t.target||t).on("click",this._removeLayer,this)},_disableLayerDelete:function(t){var e=t.layer||t.target||t;e.off("click",this._removeLayer,this),this._deletedLayers.removeLayer(e)},_removeLayer:function(t){var e=t.layer||t.target||t;this._deletableLayers.removeLayer(e),this._deletedLayers.addLayer(e),e.fire("deleted")},_onMouseMove:function(t){this._tooltip.updatePosition(t.latlng)},_hasAvailableLayers:function(){return 0!==this._deletableLayers.getLayers().length}})}(window,document);
\ No newline at end of file
-1000
View File
@@ -1,1000 +0,0 @@
#!/usr/bin/env node
/* eslint-disable */
//prettier-ignore
(()=>{var QXe=Object.create;var A6=Object.defineProperty;var FXe=Object.getOwnPropertyDescriptor;var NXe=Object.getOwnPropertyNames;var OXe=Object.getPrototypeOf,LXe=Object.prototype.hasOwnProperty;var Ae=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var tt=(t,e)=>()=>(t&&(e=t(t=0)),e);var H=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),lr=(t,e)=>{for(var r in e)A6(t,r,{get:e[r],enumerable:!0})},_Xe=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of NXe(e))!LXe.call(t,a)&&a!==r&&A6(t,a,{get:()=>e[a],enumerable:!(s=FXe(e,a))||s.enumerable});return t};var st=(t,e,r)=>(r=t!=null?QXe(OXe(t)):{},_Xe(e||!t||!t.__esModule?A6(r,"default",{value:t,enumerable:!0}):r,t));var Oi={};lr(Oi,{SAFE_TIME:()=>bae,S_IFDIR:()=>fT,S_IFLNK:()=>hT,S_IFMT:()=>Rh,S_IFREG:()=>nS});var Rh,fT,nS,hT,bae,Dae=tt(()=>{Rh=61440,fT=16384,nS=32768,hT=40960,bae=456789e3});var vr={};lr(vr,{EBADF:()=>ha,EBUSY:()=>MXe,EEXIST:()=>VXe,EINVAL:()=>HXe,EISDIR:()=>qXe,ENOENT:()=>jXe,ENOSYS:()=>UXe,ENOTDIR:()=>GXe,ENOTEMPTY:()=>YXe,EOPNOTSUPP:()=>KXe,EROFS:()=>WXe,ERR_DIR_CLOSED:()=>p6});function ou(t,e){return Object.assign(new Error(`${t}: ${e}`),{code:t})}function MXe(t){return ou("EBUSY",t)}function UXe(t,e){return ou("ENOSYS",`${t}, ${e}`)}function HXe(t){return ou("EINVAL",`invalid argument, ${t}`)}function ha(t){return ou("EBADF",`bad file descriptor, ${t}`)}function jXe(t){return ou("ENOENT",`no such file or directory, ${t}`)}function GXe(t){return ou("ENOTDIR",`not a directory, ${t}`)}function qXe(t){return ou("EISDIR",`illegal operation on a directory, ${t}`)}function VXe(t){return ou("EEXIST",`file already exists, ${t}`)}function WXe(t){return ou("EROFS",`read-only filesystem, ${t}`)}function YXe(t){return ou("ENOTEMPTY",`directory not empty, ${t}`)}function KXe(t){return ou("EOPNOTSUPP",`operation not supported, ${t}`)}function p6(){return ou("ERR_DIR_CLOSED","Directory handle was closed")}var AT=tt(()=>{});var Lc={};lr(Lc,{BigIntStatsEntry:()=>iw,DEFAULT_MODE:()=>m6,DirEntry:()=>d6,StatEntry:()=>nw,areStatsEqual:()=>y6,clearStats:()=>pT,convertToBigIntStats:()=>JXe,makeDefaultStats:()=>Pae,makeEmptyStats:()=>zXe});function Pae(){return new nw}function zXe(){return pT(Pae())}function pT(t){for(let e in t)if(Object.hasOwn(t,e)){let r=t[e];typeof r=="number"?t[e]=0:typeof r=="bigint"?t[e]=BigInt(0):g6.types.isDate(r)&&(t[e]=new Date(0))}return t}function JXe(t){let e=new iw;for(let r in t)if(Object.hasOwn(t,r)){let s=t[r];typeof s=="number"?e[r]=BigInt(Math.floor(s)):g6.types.isDate(s)&&(e[r]=new Date(s))}return e.atimeNs=e.atimeMs*BigInt(1e6)+BigInt(Math.floor(t.atimeMs%1*1e3))*BigInt(1e3),e.mtimeNs=e.mtimeMs*BigInt(1e6)+BigInt(Math.floor(t.mtimeMs%1*1e3))*BigInt(1e3),e.ctimeNs=e.ctimeMs*BigInt(1e6)+BigInt(Math.floor(t.ctimeMs%1*1e3))*BigInt(1e3),e.birthtimeNs=e.birthtimeMs*BigInt(1e6)+BigInt(Math.floor(t.birthtimeMs%1*1e3))*BigInt(1e3),e}function y6(t,e){if(t.atimeMs!==e.atimeMs||t.birthtimeMs!==e.birthtimeMs||t.blksize!==e.blksize||t.blocks!==e.blocks||t.ctimeMs!==e.ctimeMs||t.dev!==e.dev||t.gid!==e.gid||t.ino!==e.ino||t.isBlockDevice()!==e.isBlockDevice()||t.isCharacterDevice()!==e.isCharacterDevice()||t.isDirectory()!==e.isDirectory()||t.isFIFO()!==e.isFIFO()||t.isFile()!==e.isFile()||t.isSocket()!==e.isSocket()||t.isSymbolicLink()!==e.isSymbolicLink()||t.mode!==e.mode||t.mtimeMs!==e.mtimeMs||t.nlink!==e.nlink||t.rdev!==e.rdev||t.size!==e.size||t.uid!==e.uid)return!1;let r=t,s=e;return!(r.atimeNs!==s.atimeNs||r.mtimeNs!==s.mtimeNs||r.ctimeNs!==s.ctimeNs||r.birthtimeNs!==s.birthtimeNs)}var g6,m6,d6,nw,iw,E6=tt(()=>{g6=st(Ae("util")),m6=33188,d6=class{constructor(){this.name="";this.path="";this.mode=0}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},nw=class{constructor(){this.uid=0;this.gid=0;this.size=0;this.blksize=0;this.atimeMs=0;this.mtimeMs=0;this.ctimeMs=0;this.birthtimeMs=0;this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=0;this.ino=0;this.mode=m6;this.nlink=1;this.rdev=0;this.blocks=1}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},iw=class{constructor(){this.uid=BigInt(0);this.gid=BigInt(0);this.size=BigInt(0);this.blksize=BigInt(0);this.atimeMs=BigInt(0);this.mtimeMs=BigInt(0);this.ctimeMs=BigInt(0);this.birthtimeMs=BigInt(0);this.atimeNs=BigInt(0);this.mtimeNs=BigInt(0);this.ctimeNs=BigInt(0);this.birthtimeNs=BigInt(0);this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);thisLine truncated
`).length,s=e.length-r;return r>s?`\r
`:`
`}function ty(t,e){return e.replace(/\r?\n/g,l$e(t))}var Lae,_ae,Sp,Th,ry=tt(()=>{Lae=Ae("crypto"),_ae=Ae("os");C6();_c();Sp=class{constructor(e){this.pathUtils=e}async*genTraversePromise(e,{stableSort:r=!1}={}){let s=[e];for(;s.length>0;){let a=s.shift();if((await this.lstatPromise(a)).isDirectory()){let l=await this.readdirPromise(a);if(r)for(let f of l.sort())s.push(this.pathUtils.join(a,f));else throw new Error("Not supported")}else yield a}}async checksumFilePromise(e,{algorithm:r="sha512"}={}){let s=await this.openPromise(e,"r");try{let n=Buffer.allocUnsafeSlow(65536),l=(0,Lae.createHash)(r),f=0;for(;(f=await this.readPromise(s,n,0,65536))!==0;)l.update(f===65536?n:n.slice(0,f));return l.digest("hex")}finally{await this.closePromise(s)}}async removePromise(e,{recursive:r=!0,maxRetries:s=5}={}){let a;try{a=await this.lstatPromise(e)}catch(n){if(n.code==="ENOENT")return;throw n}if(a.isDirectory()){if(r){let n=await this.readdirPromise(e);await Promise.all(n.map(l=>this.removePromise(this.pathUtils.resolve(e,l))))}for(let n=0;n<=s;n++)try{await this.rmdirPromise(e);break}catch(l){if(l.code!=="EBUSY"&&l.code!=="ENOTEMPTY")throw l;n<s&&await new Promise(f=>setTimeout(f,n*100))}}else await this.unlinkPromise(e)}removeSync(e,{recursive:r=!0}={}){let s;try{s=this.lstatSync(e)}catch(a){if(a.code==="ENOENT")return;throw a}if(s.isDirectory()){if(r)for(let a of this.readdirSync(e))this.removeSync(this.pathUtils.resolve(e,a));this.rmdirSync(e)}else this.unlinkSync(e)}async mkdirpPromise(e,{chmod:r,utimes:s}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let l=2;l<=a.length;++l){let f=a.slice(0,l).join(this.pathUtils.sep);if(!this.existsSync(f)){try{await this.mkdirPromise(f)}catch(h){if(h.code==="EEXIST")continue;throw h}if(n??=f,r!=null&&await this.chmodPromise(f,r),s!=null)await this.utimesPromise(f,s[0],s[1]);else{let h=await this.statPromise(this.pathUtils.dirname(f));await this.utimesPromise(f,h.atime,h.mtime)}}}return n}mkdirpSync(e,{chmod:r,utimes:s}={}){if(e=this.resolve(e),e===this.pathUtils.dirname(e))return;let a=e.split(this.pathUtils.sep),n;for(let l=2;l<=a.length;++l){let f=a.slice(0,l).join(this.pathUtils.sep);if(!this.existsSync(f)){try{this.mkdirSync(f)}catch(h){if(h.code==="EEXIST")continue;throw h}if(n??=f,r!=null&&this.chmodSync(f,r),s!=null)this.utimesSync(f,s[0],s[1]);else{let h=this.statSync(this.pathUtils.dirname(f));this.utimesSync(f,h.atime,h.mtime)}}}return n}async copyPromise(e,r,{baseFs:s=this,overwrite:a=!0,stableSort:n=!1,stableTime:l=!1,linkStrategy:f=null}={}){return await Rae(this,e,s,r,{overwrite:a,stableSort:n,stableTime:l,linkStrategy:f})}copySync(e,r,{baseFs:s=this,overwrite:a=!0}={}){let n=s.lstatSync(r),l=this.existsSync(e);if(n.isDirectory()){this.mkdirpSync(e);let h=s.readdirSync(r);for(let A of h)this.copySync(this.pathUtils.join(e,A),s.pathUtils.join(r,A),{baseFs:s,overwrite:a})}else if(n.isFile()){if(!l||a){l&&this.removeSync(e);let h=s.readFileSync(r);this.writeFileSync(e,h)}}else if(n.isSymbolicLink()){if(!l||a){l&&this.removeSync(e);let h=s.readlinkSync(r);this.symlinkSync(dT(this.pathUtils,h),e)}}else throw new Error(`Unsupported file type (file: ${r}, mode: 0o${n.mode.toString(8).padStart(6,"0")})`);let f=n.mode&511;this.chmodSync(e,f)}async changeFilePromise(e,r,s={}){return Buffer.isBuffer(r)?this.changeFileBufferPromise(e,r,s):this.changeFileTextPromise(e,r,s)}async changeFileBufferPromise(e,r,{mode:s}={}){let a=Buffer.alloc(0);try{a=await this.readFilePromise(e)}catch{}Buffer.compare(a,r)!==0&&await this.writeFilePromise(e,r,{mode:s})}async changeFileTextPromise(e,r,{automaticNewlines:s,mode:a}={}){let n="";try{n=await this.readFilePromise(e,"utf8")}catch{}let l=s?ty(n,r):r;n!==l&&await this.writeFilePromise(e,l,{mode:a})}changeFileSync(e,r,s={}){return Buffer.isBuffer(r)?this.changeFileBufferSync(e,r,s):this.changeFileTextSync(e,r,s)}changeFileBufferSync(e,r,{mode:s}={}){let a=Buffer.alloc(0);try{a=this.readFileSync(e)}catch{}Buffer.compare(a,r)!==0&&this.writeFileSync(e,r,{mode:s})}changeFileTextSync(e,r,{automaticNewlines:s=!1,mode:a}={}){let n="";try{n=this.readFileSync(e,"utf8")}catch{}let l=s?ty(n,r):r;n!==l&&this.writeFileSync(e,l,{mode:a})}async movePromise(e,r){try{await this.renamePromise(e,r)}catch(s){if(s.code==="EXDEV")await this.copyPromise(r,e),await this.removePromise(e);else throw s}}moveSync(e,r){try{this.renameSync(e,r)}catch(s){if(s.code==="EXDEV")this.copySync(r,e),this.removeSync(e);else throw s}}async lockPromise(e,r){let s=`${e}.flock`,a=1e3/60,n=Date.now(),l=null,f=async()=>{let h;try{[h]=await this.readJsonPromise(s)}catch{return Date.now()-n<500}try{return process.kill(h,0),!0}catch{return!1}};for(;l===null;)try{l=await this.openPromise(s,"wx")}catch(h){if(h.code==="EEXIST"){if(!await f())try{await this.unlinkPromise(s);continue}catch{}if(Date.now()-n<60*1e3)await new Promise(A=>setTimeout(A,a));else throw new Error(`Couldn't acquire a lock in a reasonable time (via ${s})`)}else Line truncated
`)}writeJsonSync(e,r,{compact:s=!1}={}){let a=s?0:2;return this.writeFileSync(e,`${JSON.stringify(r,null,a)}
`)}async preserveTimePromise(e,r){let s=await this.lstatPromise(e),a=await r();typeof a<"u"&&(e=a),await this.lutimesPromise(e,s.atime,s.mtime)}async preserveTimeSync(e,r){let s=this.lstatSync(e),a=r();typeof a<"u"&&(e=a),this.lutimesSync(e,s.atime,s.mtime)}},Th=class extends Sp{constructor(){super(Y)}}});var fo,bp=tt(()=>{ry();fo=class extends Sp{getExtractHint(e){return this.baseFs.getExtractHint(e)}resolve(e){return this.mapFromBase(this.baseFs.resolve(this.mapToBase(e)))}getRealPath(){return this.mapFromBase(this.baseFs.getRealPath())}async openPromise(e,r,s){return this.baseFs.openPromise(this.mapToBase(e),r,s)}openSync(e,r,s){return this.baseFs.openSync(this.mapToBase(e),r,s)}async opendirPromise(e,r){return Object.assign(await this.baseFs.opendirPromise(this.mapToBase(e),r),{path:e})}opendirSync(e,r){return Object.assign(this.baseFs.opendirSync(this.mapToBase(e),r),{path:e})}async readPromise(e,r,s,a,n){return await this.baseFs.readPromise(e,r,s,a,n)}readSync(e,r,s,a,n){return this.baseFs.readSync(e,r,s,a,n)}async writePromise(e,r,s,a,n){return typeof r=="string"?await this.baseFs.writePromise(e,r,s):await this.baseFs.writePromise(e,r,s,a,n)}writeSync(e,r,s,a,n){return typeof r=="string"?this.baseFs.writeSync(e,r,s):this.baseFs.writeSync(e,r,s,a,n)}async closePromise(e){return this.baseFs.closePromise(e)}closeSync(e){this.baseFs.closeSync(e)}createReadStream(e,r){return this.baseFs.createReadStream(e!==null?this.mapToBase(e):e,r)}createWriteStream(e,r){return this.baseFs.createWriteStream(e!==null?this.mapToBase(e):e,r)}async realpathPromise(e){return this.mapFromBase(await this.baseFs.realpathPromise(this.mapToBase(e)))}realpathSync(e){return this.mapFromBase(this.baseFs.realpathSync(this.mapToBase(e)))}async existsPromise(e){return this.baseFs.existsPromise(this.mapToBase(e))}existsSync(e){return this.baseFs.existsSync(this.mapToBase(e))}accessSync(e,r){return this.baseFs.accessSync(this.mapToBase(e),r)}async accessPromise(e,r){return this.baseFs.accessPromise(this.mapToBase(e),r)}async statPromise(e,r){return this.baseFs.statPromise(this.mapToBase(e),r)}statSync(e,r){return this.baseFs.statSync(this.mapToBase(e),r)}async fstatPromise(e,r){return this.baseFs.fstatPromise(e,r)}fstatSync(e,r){return this.baseFs.fstatSync(e,r)}lstatPromise(e,r){return this.baseFs.lstatPromise(this.mapToBase(e),r)}lstatSync(e,r){return this.baseFs.lstatSync(this.mapToBase(e),r)}async fchmodPromise(e,r){return this.baseFs.fchmodPromise(e,r)}fchmodSync(e,r){return this.baseFs.fchmodSync(e,r)}async chmodPromise(e,r){return this.baseFs.chmodPromise(this.mapToBase(e),r)}chmodSync(e,r){return this.baseFs.chmodSync(this.mapToBase(e),r)}async fchownPromise(e,r,s){return this.baseFs.fchownPromise(e,r,s)}fchownSync(e,r,s){return this.baseFs.fchownSync(e,r,s)}async chownPromise(e,r,s){return this.baseFs.chownPromise(this.mapToBase(e),r,s)}chownSync(e,r,s){return this.baseFs.chownSync(this.mapToBase(e),r,s)}async renamePromise(e,r){return this.baseFs.renamePromise(this.mapToBase(e),this.mapToBase(r))}renameSync(e,r){return this.baseFs.renameSync(this.mapToBase(e),this.mapToBase(r))}async copyFilePromise(e,r,s=0){return this.baseFs.copyFilePromise(this.mapToBase(e),this.mapToBase(r),s)}copyFileSync(e,r,s=0){return this.baseFs.copyFileSync(this.mapToBase(e),this.mapToBase(r),s)}async appendFilePromise(e,r,s){return this.baseFs.appendFilePromise(this.fsMapToBase(e),r,s)}appendFileSync(e,r,s){return this.baseFs.appendFileSync(this.fsMapToBase(e),r,s)}async writeFilePromise(e,r,s){return this.baseFs.writeFilePromise(this.fsMapToBase(e),r,s)}writeFileSync(e,r,s){return this.baseFs.writeFileSync(this.fsMapToBase(e),r,s)}async unlinkPromise(e){return this.baseFs.unlinkPromise(this.mapToBase(e))}unlinkSync(e){return this.baseFs.unlinkSync(this.mapToBase(e))}async utimesPromise(e,r,s){return this.baseFs.utimesPromise(this.mapToBase(e),r,s)}utimesSync(e,r,s){return this.baseFs.utimesSync(this.mapToBase(e),r,s)}async lutimesPromise(e,r,s){return this.baseFs.lutimesPromise(this.mapToBase(e),r,s)}lutimesSync(e,r,s){return this.baseFs.lutimesSync(this.mapToBase(e),r,s)}async mkdirPromise(e,r){return this.baseFs.mkdirPromise(this.mapToBase(e),r)}mkdirSync(e,r){return this.baseFs.mkdirSync(this.mapToBase(e),r)}async rmdirPromise(e,r){return this.baseFs.rmdirPromise(this.mapToBase(e),r)}rmdirSync(e,r){return this.baseFs.rmdirSync(this.mapToBase(e),r)}async rmPromise(e,r){return this.baseFs.rmPromise(this.mapToBase(e),r)}rmSync(e,r){return this.baseFs.rmSync(this.mapToBase(e),r)}async linkPromise(e,r){return this.baseFs.linkPromise(this.mapToBase(e),this.mapToBase(r))}linkSync(e,r){return this.baseFs.linkSync(this.mapToBase(e),this.mapToBase(r))}async symlinkPromise(e,r,s){let a=this.mapToBase(r);if(this.pathUtils.isAbsolute(e))return this.baseFs.symlinkPromise(this.mapToBase(e),a,s);let n=this.mapToBase(this.pathUtils.join(this.pathUtils.dirname(r),e)),l=this.baseFs.pathUtils.relative(this.baseFs.pathUtils.dirname(a),n);return this.baseFs.symlinkP Line truncated
`,La=Pr(`\\
`,!1),HA=function(){return""},Ma="\\",Ua=Pr("\\",!1),jA=/^[\\$"`]/,Fr=ws(["\\","$",'"',"`"],!1,!1),Zo=function(O){return O},Ec="\\a",Ge=Pr("\\a",!1),Hr=function(){return"a"},oh="\\b",GA=Pr("\\b",!1),qA=function(){return"\b"},Zu=/^[Ee]/,Xu=ws(["E","e"],!1,!1),Vl=function(){return"\x1B"},ve="\\f",Jt=Pr("\\f",!1),Wl=function(){return"\f"},as="\\n",To=Pr("\\n",!1),Vt=function(){return`
`},ei="\\r",Ha=Pr("\\r",!1),As=function(){return"\r"},cs="\\t",Ic=Pr("\\t",!1),Un=function(){return" "},Ei="\\v",$u=Pr("\\v",!1),Ud=function(){return"\v"},wc=/^[\\'"?]/,Cc=ws(["\\","'",'"',"?"],!1,!1),Bc=function(O){return String.fromCharCode(parseInt(O,16))},it="\\x",vc=Pr("\\x",!1),ah="\\u",Yl=Pr("\\u",!1),Yn="\\U",ja=Pr("\\U",!1),VA=function(O){return String.fromCodePoint(parseInt(O,16))},WA=/^[0-7]/,Ga=ws([["0","7"]],!1,!1),ll=/^[0-9a-fA-f]/,rr=ws([["0","9"],["a","f"],["A","f"]],!1,!1),ti=fh(),qa="{}",Sc=Pr("{}",!1),ks=function(){return"{}"},Kl="-",ef=Pr("-",!1),zl="+",bc=Pr("+",!1),ls=".",Ys=Pr(".",!1),ul=function(O,J,se){return{type:"number",value:(O==="-"?-1:1)*parseFloat(J.join("")+"."+se.join(""))}},ch=function(O,J){return{type:"number",value:(O==="-"?-1:1)*parseInt(J.join(""))}},Jl=function(O){return{type:"variable",...O}},zi=function(O){return{type:"variable",name:O}},ri=function(O){return O},Zl="*",et=Pr("*",!1),dt="/",_t=Pr("/",!1),Sr=function(O,J,se){return{type:J==="*"?"multiplication":"division",right:se}},ne=function(O,J){return J.reduce((se,Ie)=>({left:se,...Ie}),O)},Be=function(O,J,se){return{type:J==="+"?"addition":"subtraction",right:se}},_e="$((",bt=Pr("$((",!1),xt="))",jt=Pr("))",!1),Ir=function(O){return O},Nn="$(",Qi=Pr("$(",!1),ps=function(O){return O},ni="${",Dc=Pr("${",!1),mI=":-",Iv=Pr(":-",!1),Xo=function(O,J){return{name:O,defaultValue:J}},yI=":-}",Hd=Pr(":-}",!1),wv=function(O){return{name:O,defaultValue:[]}},$o=":+",jd=Pr(":+",!1),Gd=function(O,J){return{name:O,alternativeValue:J}},tf=":+}",qd=Pr(":+}",!1),gm=function(O){return{name:O,alternativeValue:[]}},mm=function(O){return{name:O}},ym="$",EI=Pr("$",!1),lh=function(O){return e.isGlobPattern(O)},ea=function(O){return O},fl=/^[a-zA-Z0-9_]/,Vd=ws([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),Em=function(){return BI()},hl=/^[$@*?#a-zA-Z0-9_\-]/,Al=ws(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),II=/^[()}<>$|&; \t"']/,YA=ws(["(",")","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),wI=/^[<>&; \t"']/,CI=ws(["<",">","&",";"," "," ",'"',"'"],!1,!1),KA=/^[ \t]/,zA=ws([" "," "],!1,!1),K=0,Gt=0,JA=[{line:1,column:1}],ta=0,uh=[],Dt=0,rf;if("startRule"in e){if(!(e.startRule in s))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=s[e.startRule]}function BI(){return t.substring(Gt,K)}function Im(){return hh(Gt,K)}function Cv(O,J){throw J=J!==void 0?J:hh(Gt,K),ZA([wm(O)],t.substring(Gt,K),J)}function Wd(O,J){throw J=J!==void 0?J:hh(Gt,K),Ui(O,J)}function Pr(O,J){return{type:"literal",text:O,ignoreCase:J}}function ws(O,J,se){return{type:"class",parts:O,inverted:J,ignoreCase:se}}function fh(){return{type:"any"}}function Pc(){return{type:"end"}}function wm(O){return{type:"other",description:O}}function nf(O){var J=JA[O],se;if(J)return J;for(se=O-1;!JA[se];)se--;for(J=JA[se],J={line:J.line,column:J.column};se<O;)t.charCodeAt(se)===10?(J.line++,J.column=1):J.column++,se++;return JA[O]=J,J}function hh(O,J){var se=nf(O),Ie=nf(J);return{start:{offset:O,line:se.line,column:se.column},end:{offset:J,line:Ie.line,column:Ie.column}}}function Qt(O){K<ta||(K>ta&&(ta=K,uh=[]),uh.push(O))}function Ui(O,J){return new sy(O,null,null,J)}function ZA(O,J,se){return new sy(sy.buildMessage(O,J),O,J,se)}function xc(){var O,J,se;for(O=K,J=[],se=qt();se!==r;)J.push(se),se=qt();return J!==r?(se=Va(),se===r&&(se=null),se!==r?(Gt=O,J=n(se),O=J):(K=O,O=r)):(K=O,O=r),O}function Va(){var O,J,se,Ie,Xe;if(O=K,J=Yd(),J!==r){for(se=[],Ie=qt();Ie!==r;)se.push(Ie),Ie=qt();se!==r?(Ie=Cm(),Ie!==r?(Xe=kc(),Xe===r&&(Xe=null),Xe!==r?(Gt=O,J=l(J,Ie,Xe),O=J):(K=O,O=r)):(K=O,O=r)):(K=O,O=r)}else K=O,O=r;if(O===r)if(O=K,J=Yd(),J!==r){for(se=[],Ie=qt();Ie!==r;)se.push(Ie),Ie=qt();se!==r?(Ie=Cm(),Ie===r&&(Ie=null),Ie!==r?(Gt=O,J=f(J,Ie),O=J):(K=O,O=r)):(K=O,O=r)}else K=O,O=r;return O}function kc(){var O,J,se,Ie,Xe;for(O=K,J=[],se=qt();se!==r;)J.push(se),se=qt();if(J!==r)if(se=Va(),se!==r){for(Ie=[],Xe=qt();Xe!==r;)Ie.push(Xe),Xe=qt();Ie!==r?(Gt=O,J=h(se),O=J):(K=O,O=r)}else K=O,O=r;else K=O,O=r;return O}function Cm(){var O;return t.charCodeAt(K)===59?(O=A,K++):(O=r,Dt===0&&Qt(m)),O===r&&(t.charCodeAt(K)===38?(O=w,K++):(O=r,Dt===0&&Qt(v))),O}function Yd(){var O,J,se;return O=K,J=XA(),J!==r?(se=Bm(),se===r&&(se=null),se!==r?(Gt=O,J=D(J,se),O=J):(K=O,O=r)):(K=O,O=r),O}function Bm(){var O,J,se,Ie,Xe,It,Nr;for(O=K,J=[],se=qt();se!==r;)J.push(se),se=qt();if(J!==r)if(se=vI(),se!==r){for(Ie=[],Xe=qt();Xe!==r;)Ie.push(Xe),Xe=qt();if(Ie!==r)if(Xe=Yd(),Xe!==r){for(It=[],Nr=qt();Nr!==r;)It.push(Nr),Nr=qt();It!==r?(Gt=O,J=I(se,Xe),O=J):(K=O,O=r)}else K=O,O=r;else K=O,O=r}else K=O,O=r;else K=O,O=r;return O}function vI(){var O;return t.substr(K,2)===R?(O=R,K+=2):(O=r,Dt===0&&Qt(N)),O===r&&(t.substr(K,2)===U?(O=U,K+=2):(O=r,Dt===0&&Qt(V))),O}function XA(){var O,J,se;return O=K,J=Ah(),J!==r?(se=vm(),se===r&&(se=null),se!==r?(Gt=O,J=ee(J,se),O=J):(K=O,O=r)):(K=O,O=r),O}function vm(){var O,J,se,Ie,Xe,It,Nr;for(O=K,J=[],se=qt();se!==r;)J.push(se),se=qt();if(J!==r)Line truncated
`,"\\n"],["\r","\\r"],[" ","\\t"],["\v","\\v"],["\0","\\0"]]),j$e=new Map([["\\","\\\\"],["$","\\$"],['"','\\"'],...Array.from(tle,([t,e])=>[t,`"$'${e}'"`])]),rle=t=>tle.get(t)??`\\x${t.charCodeAt(0).toString(16).padStart(2,"0")}`,G$e=t=>j$e.get(t)??`"$'${rle(t)}'"`});var sle=H((uqt,ile)=>{"use strict";function q$e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function ay(t,e,r,s){this.message=t,this.expected=e,this.found=r,this.location=s,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,ay)}q$e(ay,Error);ay.buildMessage=function(t,e){var r={literal:function(A){return'"'+a(A.text)+'"'},class:function(A){var m="",w;for(w=0;w<A.parts.length;w++)m+=A.parts[w]instanceof Array?n(A.parts[w][0])+"-"+n(A.parts[w][1]):n(A.parts[w]);return"["+(A.inverted?"^":"")+m+"]"},any:function(A){return"any character"},end:function(A){return"end of input"},other:function(A){return A.description}};function s(A){return A.charCodeAt(0).toString(16).toUpperCase()}function a(A){return A.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(m){return"\\x0"+s(m)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(m){return"\\x"+s(m)})}function n(A){return A.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(m){return"\\x0"+s(m)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(m){return"\\x"+s(m)})}function l(A){return r[A.type](A)}function f(A){var m=new Array(A.length),w,v;for(w=0;w<A.length;w++)m[w]=l(A[w]);if(m.sort(),m.length>0){for(w=1,v=1;w<m.length;w++)m[w-1]!==m[w]&&(m[v]=m[w],v++);m.length=v}switch(m.length){case 1:return m[0];case 2:return m[0]+" or "+m[1];default:return m.slice(0,-1).join(", ")+", or "+m[m.length-1]}}function h(A){return A?'"'+a(A)+'"':"end of input"}return"Expected "+f(t)+" but "+h(e)+" found."};function V$e(t,e){e=e!==void 0?e:{};var r={},s={resolution:Fe},a=Fe,n="/",l=Ce("/",!1),f=function(Me,x){return{from:Me,descriptor:x}},h=function(Me){return{descriptor:Me}},A="@",m=Ce("@",!1),w=function(Me,x){return{fullName:Me,description:x}},v=function(Me){return{fullName:Me}},D=function(){return xe()},I=/^[^\/@]/,R=Ee(["/","@"],!0,!1),N=/^[^\/]/,U=Ee(["/"],!0,!1),V=0,ee=0,te=[{line:1,column:1}],ie=0,ae=[],ge=0,de;if("startRule"in e){if(!(e.startRule in s))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=s[e.startRule]}function xe(){return t.substring(ee,V)}function we(){return ot(ee,V)}function d(Me,x){throw x=x!==void 0?x:ot(ee,V),Ne([De(Me)],t.substring(ee,V),x)}function be(Me,x){throw x=x!==void 0?x:ot(ee,V),rt(Me,x)}function Ce(Me,x){return{type:"literal",text:Me,ignoreCase:x}}function Ee(Me,x,C){return{type:"class",parts:Me,inverted:x,ignoreCase:C}}function he(){return{type:"any"}}function $(){return{type:"end"}}function De(Me){return{type:"other",description:Me}}function Te(Me){var x=te[Me],C;if(x)return x;for(C=Me-1;!te[C];)C--;for(x=te[C],x={line:x.line,column:x.column};C<Me;)t.charCodeAt(C)===10?(x.line++,x.column=1):x.column++,C++;return te[Me]=x,x}function ot(Me,x){var C=Te(Me),P=Te(x);return{start:{offset:Me,line:C.line,column:C.column},end:{offset:x,line:P.line,column:P.column}}}function j(Me){V<ie||(V>ie&&(ie=V,ae=[]),ae.push(Me))}function rt(Me,x){return new ay(Me,null,null,x)}function Ne(Me,x,C){return new ay(ay.buildMessage(Me,x),Me,x,C)}function Fe(){var Me,x,C,P;return Me=V,x=Pe(),x!==r?(t.charCodeAt(V)===47?(C=n,V++):(C=r,ge===0&&j(l)),C!==r?(P=Pe(),P!==r?(ee=Me,x=f(x,P),Me=x):(V=Me,Me=r)):(V=Me,Me=r)):(V=Me,Me=r),Me===r&&(Me=V,x=Pe(),x!==r&&(ee=Me,x=h(x)),Me=x),Me}function Pe(){var Me,x,C,P;return Me=V,x=He(),x!==r?(t.charCodeAt(V)===64?(C=A,V++):(C=r,ge===0&&j(m)),C!==r?(P=ft(),P!==r?(ee=Me,x=w(x,P),Me=x):(V=Me,Me=r)):(V=Me,Me=r)):(V=Me,Me=r),Me===r&&(Me=V,x=He(),x!==r&&(ee=Me,x=v(x)),Me=x),Me}function He(){var Me,x,C,P,E;return Me=V,t.charCodeAt(V)===64?(x=A,V++):(x=r,ge===0&&j(m)),x!==r?(C=Qe(),C!==r?(t.charCodeAt(V)===47?(P=n,V++):(P=r,ge===0&&j(l)),P!==r?(E=Qe(),E!==r?(ee=Me,x=D(),Me=x):(V=Me,Me=r)):(V=Me,Me=r)):(V=Me,Me=r)):(V=Me,Me=r),Me===r&&(Me=V,x=Qe(),x!==r&&(ee=Me,x=D()),Me=x),Me}function Qe(){var Me,x,C;if(Me=V,x=[],I.test(t.charAt(V))?(C=t.charAt(V),V++):(C=r,ge===0&&j(R)),C!==r)for(;C!==r;)x.push(C),I.test(t.charAt(V))?(C=t.charAt(V),V++):(C=r,ge===0&&j(R));else x=r;return x!==r&&(ee=Me,x=D()),Me=x,Me}function ft(){var Me,x,C;if(Me=V,x=[],N.test(t.charAt(V))?(C=t.charAt(V),V++):(C=r,ge===0&&j(U)),C!==r)for(;C!==r;)x.push(C),N.test(t.charAt(V))?(C=t.charAt(V),V++):(C=r,ge===0&&j(U));else x=r;return x!==r&&(ee=Me,x=D()),Me=x,Me}if(de=a(),de!==r&&V===t.length)return de;throw de!==r&&V<t.length&&j($()),Ne(ae,ie<t.length?t.charAt(ie):null,ie<t.length?ot(ie,ie+1):ot(ie,ie))}ile.exports={SyntaxError:ay,parse:V$e}});function kT(t){let e=t.match(/^\*{1,Line truncated
`+r.mark.snippet),n+" "+a):n}function e(r,s){Error.call(this),this.name="YAMLException",this.reason=r,this.mark=s,this.message=t(this,!1),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}return e.prototype=Object.create(Error.prototype),e.prototype.constructor=e,e.prototype.toString=function(s){return this.name+": "+t(this,s)},j6=e,j6}function Y$e(){if(ule)return G6;ule=1;let t=uS();function e(a,n,l,f,h){let A="",m="",w=Math.floor(h/2)-1;return f-n>w&&(A=" ... ",n=f-w+A.length),l-f>w&&(m=" ...",l=f+w-m.length),{str:A+a.slice(n,l).replace(/\t/g,"\u2192")+m,pos:f-n+A.length}}function r(a,n){return t.repeat(" ",n-a.length)+a}function s(a,n){if(n=Object.create(n||null),!a.buffer)return null;n.maxLength||(n.maxLength=79),typeof n.indent!="number"&&(n.indent=1),typeof n.linesBefore!="number"&&(n.linesBefore=3),typeof n.linesAfter!="number"&&(n.linesAfter=2);let l=/\r?\n|\r|\0/g,f=[0],h=[],A,m=-1;for(;A=l.exec(a.buffer);)h.push(A.index),f.push(A.index+A[0].length),a.position<=A.index&&m<0&&(m=f.length-2);m<0&&(m=f.length-1);let w="",v=Math.min(a.line+n.linesAfter,h.length).toString().length,D=n.maxLength-(n.indent+v+3);for(let R=1;R<=n.linesBefore&&!(m-R<0);R++){let N=e(a.buffer,f[m-R],h[m-R],a.position-(f[m]-f[m-R]),D);w=t.repeat(" ",n.indent)+r((a.line-R+1).toString(),v)+" | "+N.str+`
`+w}let I=e(a.buffer,f[m],h[m],a.position,D);w+=t.repeat(" ",n.indent)+r((a.line+1).toString(),v)+" | "+I.str+`
`,w+=t.repeat("-",n.indent+v+3+I.pos)+`^
`;for(let R=1;R<=n.linesAfter&&!(m+R>=h.length);R++){let N=e(a.buffer,f[m+R],h[m+R],a.position-(f[m]-f[m+R]),D);w+=t.repeat(" ",n.indent)+r((a.line+R+1).toString(),v)+" | "+N.str+`
`}return w.replace(/\n$/,"")}return G6=s,G6}function Za(){if(fle)return q6;fle=1;let t=fS(),e=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],r=["scalar","sequence","mapping"];function s(n){let l={};return n!==null&&Object.keys(n).forEach(function(f){n[f].forEach(function(h){l[String(h)]=f})}),l}function a(n,l){if(l=l||{},Object.keys(l).forEach(function(f){if(e.indexOf(f)===-1)throw new t('Unknown option "'+f+'" is met in definition of "'+n+'" YAML type.')}),this.options=l,this.tag=n,this.kind=l.kind||null,this.resolve=l.resolve||function(){return!0},this.construct=l.construct||function(f){return f},this.instanceOf=l.instanceOf||null,this.predicate=l.predicate||null,this.represent=l.represent||null,this.representName=l.representName||null,this.defaultStyle=l.defaultStyle||null,this.multi=l.multi||!1,this.styleAliases=s(l.styleAliases||null),r.indexOf(this.kind)===-1)throw new t('Unknown kind "'+this.kind+'" is specified for "'+n+'" YAML type.')}return q6=a,q6}function Qle(){if(hle)return V6;hle=1;let t=fS(),e=Za();function r(n,l){let f=[];return n[l].forEach(function(h){let A=f.length;f.forEach(function(m,w){m.tag===h.tag&&m.kind===h.kind&&m.multi===h.multi&&(A=w)}),f[A]=h}),f}function s(){let n={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}};function l(f){f.multi?(n.multi[f.kind].push(f),n.multi.fallback.push(f)):n[f.kind][f.tag]=n.fallback[f.tag]=f}for(let f=0,h=arguments.length;f<h;f+=1)arguments[f].forEach(l);return n}function a(n){return this.extend(n)}return a.prototype.extend=function(l){let f=[],h=[];if(l instanceof e)h.push(l);else if(Array.isArray(l))h=h.concat(l);else if(l&&(Array.isArray(l.implicit)||Array.isArray(l.explicit)))l.implicit&&(f=f.concat(l.implicit)),l.explicit&&(h=h.concat(l.explicit));else throw new t("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");f.forEach(function(m){if(!(m instanceof e))throw new t("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(m.loadKind&&m.loadKind!=="scalar")throw new t("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(m.multi)throw new t("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")}),h.forEach(function(m){if(!(m instanceof e))throw new t("Specified list of YAML types (or a single Type object) contains a non-Type object.")});let A=Object.create(a.prototype);return A.implicit=(this.implicit||[]).concat(f),A.explicit=(this.explicit||[]).concat(h),A.compiledImplicit=r(A,"implicit"),A.compiledExplicit=r(A,"explicit"),A.compiledTypeMap=s(A.compiledImplicit,A.compiledExplicit),A},V6=a,V6}function Fle(){if(Ale)return W6;Ale=1;let t=Za();return W6=new t("tag:yaml.org,2002:str",{kind:"scalar",construct:function(e){return e!==null?e:""}}),W6}function Nle(){if(ple)return Y6;ple=1;let t=Za();return Y6=new t("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(e){return e!==null?e:[]}}),Y6}function Ole(){if(dle)return K6;dle=1;let t=Za();return K6=new t("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return e!==null?e:{}}}),K6}function Lle(){if(gle)return z6;gle=1;let t=Qle();return z6=new t({explicit:[Fle(),Nle(),Ole()]}),z6}function _le(){if(mle)return J6;mle=1;let t=Za();function e(a){if(a===null)return!0;let n=a.length;return n===1&&a==="~"||n===4&&(a==="null"||a==="Null"||a==="NULL")}function r(){return null}function s(a){return a===null}return J6=new t("tag:yaml.org,2002:null",{kind:"scalar",resolve:e,construct:r,predicate:s,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"},empty:function(){return""}},defaultStyle:"lowercase"}),J6}function Mle(){if(yle)return Z6;yle=1;let t=Za();function e(a){if(a===null)return!1;let n=a.length;return n===4&&(a==="true"||a==="True"||a==="TRUE")||n===5&&(a==="false"||a==="False"||a==="FALSE")}function r(a){return a==="true"||a==="True"||a==="TRUE"}function s(a){return Object.prototype.toString.call(a)==="[object Boolean]"}return Z6=new t("tag:yaml.org,2002:bool",{kind:"scalar",resolve:e,construct:r,predicate:s,represent:{lowercase:function(a){return a?"true":"false"},uppercase:function(a){return a?"TRUE":"FALSE"},camelcase:function(a){return a?"True":"False"}},defaultStyle:"lowercase"}),Z6}function Ule(){if(Ele)return X6;Ele=1;let t=uS(),e=Za();function r(A){return A>=48&&A<=57||A>=65&&A<=70||A>=97&&A<=102}function s(A){return A>=48&&A<=55}function a(A){return A>=48&&A<=57}function n(A){if(A===null)return!1;let m=A.length,w=0,v=!1;if(!m)return!1;let D=A[w];if((D==="-"||D==="+")&&(D=A[++w]),D==="0"){if(w+1===m)return!0;if(D=A[++w],D==="b"){for(w++;w<m;w++){if(D=A[w],D!=="0"&&D!=="1")return!1;v=!0}return v&&isFinite(l(A))}if(D==="x"){for(w++;w<m;w++){if(!r(A.cha Line truncated
\r`;function r(l){if(l===null)return!1;let f=0,h=l.length,A=e;for(let m=0;m<h;m++){let w=A.indexOf(l.charAt(m));if(!(w>64)){if(w<0)return!1;f+=6}}return f%8===0}function s(l){let f=l.replace(/[\r\n=]/g,""),h=f.length,A=e,m=0,w=[];for(let D=0;D<h;D++)D%4===0&&D&&(w.push(m>>16&255),w.push(m>>8&255),w.push(m&255)),m=m<<6|A.indexOf(f.charAt(D));let v=h%4*6;return v===0?(w.push(m>>16&255),w.push(m>>8&255),w.push(m&255)):v===18?(w.push(m>>10&255),w.push(m>>2&255)):v===12&&w.push(m>>4&255),new Uint8Array(w)}function a(l){let f="",h=0,A=l.length,m=e;for(let v=0;v<A;v++)v%3===0&&v&&(f+=m[h>>18&63],f+=m[h>>12&63],f+=m[h>>6&63],f+=m[h&63]),h=(h<<8)+l[v];let w=A%3;return w===0?(f+=m[h>>18&63],f+=m[h>>12&63],f+=m[h>>6&63],f+=m[h&63]):w===2?(f+=m[h>>10&63],f+=m[h>>4&63],f+=m[h<<2&63],f+=m[64]):w===1&&(f+=m[h>>2&63],f+=m[h<<4&63],f+=m[64],f+=m[64]),f}function n(l){return Object.prototype.toString.call(l)==="[object Uint8Array]"}return iH=new t("tag:yaml.org,2002:binary",{kind:"scalar",resolve:r,construct:s,predicate:n,represent:a}),iH}function Yle(){if(ble)return sH;ble=1;let t=Za(),e=Object.prototype.hasOwnProperty,r=Object.prototype.toString;function s(n){if(n===null)return!0;let l=[],f=n;for(let h=0,A=f.length;h<A;h+=1){let m=f[h],w=!1;if(r.call(m)!=="[object Object]")return!1;let v;for(v in m)if(e.call(m,v))if(!w)w=!0;else return!1;if(!w)return!1;if(l.indexOf(v)===-1)l.push(v);else return!1}return!0}function a(n){return n!==null?n:[]}return sH=new t("tag:yaml.org,2002:omap",{kind:"sequence",resolve:s,construct:a}),sH}function Kle(){if(Dle)return oH;Dle=1;let t=Za(),e=Object.prototype.toString;function r(a){if(a===null)return!0;let n=a,l=new Array(n.length);for(let f=0,h=n.length;f<h;f+=1){let A=n[f];if(e.call(A)!=="[object Object]")return!1;let m=Object.keys(A);if(m.length!==1)return!1;l[f]=[m[0],A[m[0]]]}return!0}function s(a){if(a===null)return[];let n=a,l=new Array(n.length);for(let f=0,h=n.length;f<h;f+=1){let A=n[f],m=Object.keys(A);l[f]=[m[0],A[m[0]]]}return l}return oH=new t("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:r,construct:s}),oH}function zle(){if(Ple)return aH;Ple=1;let t=Za(),e=Object.prototype.hasOwnProperty;function r(a){if(a===null)return!0;let n=a;for(let l in n)if(e.call(n,l)&&n[l]!==null)return!1;return!0}function s(a){return a!==null?a:{}}return aH=new t("tag:yaml.org,2002:set",{kind:"mapping",resolve:r,construct:s}),aH}function uH(){return xle||(xle=1,cH=Gle().extend({implicit:[qle(),Vle()],explicit:[Wle(),Yle(),Kle(),zle()]})),cH}function K$e(){if(kle)return TT;kle=1;let t=uS(),e=fS(),r=Y$e(),s=uH(),a=Object.prototype.hasOwnProperty,n=1,l=2,f=3,h=4,A=1,m=2,w=3,v=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,D=/[\x85\u2028\u2029]/,I=/[,\[\]{}]/,R=/^(?:!|!!|![0-9A-Za-z-]+!)$/,N=/^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i;function U(_){return Object.prototype.toString.call(_)}function V(_){return _===10||_===13}function ee(_){return _===9||_===32}function te(_){return _===9||_===32||_===10||_===13}function ie(_){return _===44||_===91||_===93||_===123||_===125}function ae(_){if(_>=48&&_<=57)return _-48;let Ue=_|32;return Ue>=97&&Ue<=102?Ue-97+10:-1}function ge(_){return _===120?2:_===117?4:_===85?8:0}function de(_){return _>=48&&_<=57?_-48:-1}function xe(_){switch(_){case 48:return"\0";case 97:return"\x07";case 98:return"\b";case 116:return" ";case 9:return" ";case 110:return`
`;case 118:return"\v";case 102:return"\f";case 114:return"\r";case 101:return"\x1B";case 32:return" ";case 34:return'"';case 47:return"/";case 92:return"\\";case 78:return"\x85";case 95:return"\xA0";case 76:return"\u2028";case 80:return"\u2029";default:return""}}function we(_){return _<=65535?String.fromCharCode(_):String.fromCharCode((_-65536>>10)+55296,(_-65536&1023)+56320)}function d(_,Ue,lt){Ue==="__proto__"?Object.defineProperty(_,Ue,{configurable:!0,enumerable:!0,writable:!0,value:lt}):_[Ue]=lt}let be=new Array(256),Ce=new Array(256);for(let _=0;_<256;_++)be[_]=xe(_)?1:0,Ce[_]=xe(_);function Ee(_,Ue){this.input=_,this.filename=Ue.filename||null,this.schema=Ue.schema||s,this.onWarning=Ue.onWarning||null,this.legacy=Ue.legacy||!1,this.json=Ue.json||!1,this.listener=Ue.listener||null,this.maxDepth=typeof Ue.maxDepth=="number"?Ue.maxDepth:100,this.maxTotalMergeKeys=typeof Ue.maxTotalMergeKeys=="number"?Ue.maxTotalMergeKeys:1e4,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=_.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.depth=0,this.totalMergeKeys=0,this.firstTabInLine=-1,this.documents=[],this.anchorMapTransactions=[]}function he(_,Ue){let lt={name:_.filename,buffer:_.input.slice(0,-1),position:_.position,line:_.line,column:_.position-_.lineStart};return lt.snippet=r(lt),new e(Ue,lt)}function $(_,Ue){throw he(_,Ue)}function De(_,Ue){_.onWarning&&_.onWarning.call(null,he(_,Ue))}function Te(_,Ue,lt){let Bt=_.anchorMapTransactions;if(Bt.length!==0){let ct=Bt[Bt.length-1];a.call(ct,Ue)||(ct[Ue]={existed:a.call(_.anchorMap,Ue),value:_.anchorMap[Ue]})}_.anchorMap[Ue]=lt}function ot(_){_.anchorMapTransactions.push(Object.create(null))}function j(_){let Ue=_.anchorMapTransactions.pop(),lt=_.anchorMapTransactions;if(lt.length===0)return;let Bt=lt[lt.length-1],ct=Object.keys(Ue);for(let Ft=0,le=ct.length;Ft<le;Ft+=1){let Ze=ct[Ft];a.call(Bt,Ze)||(Bt[Ze]=Ue[Ze])}}function rt(_){let Ue=_.anchorMapTransactions.pop(),lt=Object.keys(Ue);for(let Bt=lt.length-1;Bt>=0;Bt-=1){let ct=Ue[lt[Bt]];ct.existed?_.anchorMap[lt[Bt]]=ct.value:delete _.anchorMap[lt[Bt]]}}function Ne(_){return{position:_.position,line:_.line,lineStart:_.lineStart,lineIndent:_.lineIndent,firstTabInLine:_.firstTabInLine,tag:_.tag,anchor:_.anchor,kind:_.kind,result:_.result}}function Fe(_,Ue){_.position=Ue.position,_.line=Ue.line,_.lineStart=Ue.lineStart,_.lineIndent=Ue.lineIndent,_.firstTabInLine=Ue.firstTabInLine,_.tag=Ue.tag,_.anchor=Ue.anchor,_.kind=Ue.kind,_.result=Ue.result}let Pe={YAML:function(Ue,lt,Bt){Ue.version!==null&&$(Ue,"duplication of %YAML directive"),Bt.length!==1&&$(Ue,"YAML directive accepts exactly one argument");let ct=/^([0-9]+)\.([0-9]+)$/.exec(Bt[0]);ct===null&&$(Ue,"ill-formed argument of the YAML directive");let Ft=parseInt(ct[1],10),le=parseInt(ct[2],10);Ft!==1&&$(Ue,"unacceptable YAML version of the document"),Ue.version=Bt[0],Ue.checkLineBreaks=le<2,le!==1&&le!==2&&De(Ue,"unsupported YAML version of the document")},TAG:function(Ue,lt,Bt){let ct;Bt.length!==2&&$(Ue,"TAG directive accepts exactly two arguments");let Ft=Bt[0];ct=Bt[1],R.test(Ft)||$(Ue,"ill-formed tag handle (first argument) of the TAG directive"),a.call(Ue.tagMap,Ft)&&$(Ue,'there is a previously declared suffix for "'+Ft+'" tag handle'),N.test(ct)||$(Ue,"ill-formed tag prefix (second argument) of the TAG directive");try{ct=decodeURIComponent(ct)}catch{$(Ue,"tag prefix is malformed: "+ct)}Ue.tagMap[Ft]=ct}};function He(_,Ue,lt,Bt){if(Ue<lt){let ct=_.input.slice(Ue,lt);if(Bt)for(let Ft=0,le=ct.length;Ft<le;Ft+=1){let Ze=ct.charCodeAt(Ft);Ze===9||Ze>=32&&Ze<=1114111||$(_,"expected valid JSON character")}else v.test(ct)&&$(_,"the stream contains non-printable characters");_.result+=ct}}function Qe(_,Ue,lt,Bt){t.isObject(lt)||$(_,"cannot merge mappings; the provided source object is unacceptable");let ct=Object.keys(lt);for(let Ft=0,le=ct.length;Ft<le;Ft+=1){let Ze=ct[Ft];_.maxTotalMergeKeys!==-1&&++_.totalMergeKeys>_.maxTotalMergeKeys&&$(_,"merge keys exceeded maxTotalMergeKeys ("+_.maxTotalMergeKeys+")"),a.call(Ue,Ze)||(d(Ue,Ze,lt[Ze]),Bt[Ze]=!0)}}function ft(_,Ue,lt,Bt,ct,Ft,le,Ze,Tt){if(Array.isArray(ct)){ct=Array.prototype.slice.call(ct);for(let Et=0,Pt=ct.length;Et<Pt;Et+=1)Array.isArray(ct[Et])&&$(_,"nested arrays are not supported inside keys"),typeof ct=="object"&&U(ct[Et])==="[object Object]"&&(ct[Et]="[object Object]")}if(typeof ct=="object"&&U(ct)==="[object Object]"&&(ct="[object Object]"),ct=String(ct),Ue===null&&(Ue={}),Bt==="tag:yaml.org,2002:merge")if(Array.isArray(Ft))for(let Et=0,Pt=Ft.length;Et<Pt;Et+=1)Qe(_,Ue,Ft[Et],lt);else Qe(_,Ue,Ft,lt);else!_.json&&!a.call(lt,ct)&&a.call(Ue,ct)&&(_.line=le||_.line,_.lineStart=Ze||_.lineStart,_.position=Tt||_.position,$(_,"duplicated mapping key")),d(Ue,ct,Ft),delete lt[ct];return Ue}function Me(_){let Ue=_.input.charCodeAt(_.position);Ue===10?_.position++:Ue===13?(_.position++,_.input.charCodeAt(_.position)===10&&_.position+ Line truncated
`,Ue-1))}function E(_,Ue,lt){let Bt,ct,Ft,le,Ze,Tt,Et=_.kind,Pt=_.result,Lt=_.input.charCodeAt(_.position);if(te(Lt)||ie(Lt)||Lt===35||Lt===38||Lt===42||Lt===33||Lt===124||Lt===62||Lt===39||Lt===34||Lt===37||Lt===64||Lt===96)return!1;if(Lt===63||Lt===45){let Nt=_.input.charCodeAt(_.position+1);if(te(Nt)||lt&&ie(Nt))return!1}for(_.kind="scalar",_.result="",Bt=ct=_.position,Ft=!1;Lt!==0;){if(Lt===58){let Nt=_.input.charCodeAt(_.position+1);if(te(Nt)||lt&&ie(Nt))break}else if(Lt===35){let Nt=_.input.charCodeAt(_.position-1);if(te(Nt))break}else{if(_.position===_.lineStart&&C(_)||lt&&ie(Lt))break;if(V(Lt))if(le=_.line,Ze=_.lineStart,Tt=_.lineIndent,x(_,!1,-1),_.lineIndent>=Ue){Ft=!0,Lt=_.input.charCodeAt(_.position);continue}else{_.position=ct,_.line=le,_.lineStart=Ze,_.lineIndent=Tt;break}}Ft&&(He(_,Bt,ct,!1),P(_,_.line-le),Bt=ct=_.position,Ft=!1),ee(Lt)||(ct=_.position+1),Lt=_.input.charCodeAt(++_.position)}return He(_,Bt,ct,!1),_.result?!0:(_.kind=Et,_.result=Pt,!1)}function F(_,Ue){let lt,Bt,ct=_.input.charCodeAt(_.position);if(ct!==39)return!1;for(_.kind="scalar",_.result="",_.position++,lt=Bt=_.position;(ct=_.input.charCodeAt(_.position))!==0;)if(ct===39)if(He(_,lt,_.position,!0),ct=_.input.charCodeAt(++_.position),ct===39)lt=_.position,_.position++,Bt=_.position;else return!0;else V(ct)?(He(_,lt,Bt,!0),P(_,x(_,!1,Ue)),lt=Bt=_.position):_.position===_.lineStart&&C(_)?$(_,"unexpected end of the document within a single quoted scalar"):(_.position++,ee(ct)||(Bt=_.position));$(_,"unexpected end of the stream within a single quoted scalar")}function Z(_,Ue){let lt,Bt,ct,Ft=_.input.charCodeAt(_.position);if(Ft!==34)return!1;for(_.kind="scalar",_.result="",_.position++,lt=Bt=_.position;(Ft=_.input.charCodeAt(_.position))!==0;){if(Ft===34)return He(_,lt,_.position,!0),_.position++,!0;if(Ft===92){if(He(_,lt,_.position,!0),Ft=_.input.charCodeAt(++_.position),V(Ft))x(_,!1,Ue);else if(Ft<256&&be[Ft])_.result+=Ce[Ft],_.position++;else if((ct=ge(Ft))>0){let le=ct,Ze=0;for(;le>0;le--)Ft=_.input.charCodeAt(++_.position),(ct=ae(Ft))>=0?Ze=(Ze<<4)+ct:$(_,"expected hexadecimal character");_.result+=we(Ze),_.position++}else $(_,"unknown escape sequence");lt=Bt=_.position}else V(Ft)?(He(_,lt,Bt,!0),P(_,x(_,!1,Ue)),lt=Bt=_.position):_.position===_.lineStart&&C(_)?$(_,"unexpected end of the document within a double quoted scalar"):(_.position++,ee(Ft)||(Bt=_.position))}$(_,"unexpected end of the stream within a double quoted scalar")}function X(_,Ue){let lt=!0,Bt,ct,Ft,le=_.tag,Ze,Tt=_.anchor,Et,Pt,Lt,Nt,hr=Object.create(null),Xt,$t,Er,Yr=_.input.charCodeAt(_.position);if(Yr===91)Et=93,Nt=!1,Ze=[];else if(Yr===123)Et=125,Nt=!0,Ze={};else return!1;for(_.anchor!==null&&Te(_,_.anchor,Ze),Yr=_.input.charCodeAt(++_.position);Yr!==0;){if(x(_,!0,Ue),Yr=_.input.charCodeAt(_.position),Yr===Et)return _.position++,_.tag=le,_.anchor=Tt,_.kind=Nt?"mapping":"sequence",_.result=Ze,!0;if(lt?Yr===44&&$(_,"expected the node content, but found ','"):$(_,"missed comma between flow collection entries"),$t=Xt=Er=null,Pt=Lt=!1,Yr===63){let Tn=_.input.charCodeAt(_.position+1);te(Tn)&&(Pt=Lt=!0,_.position++,x(_,!0,Ue))}Bt=_.line,ct=_.lineStart,Ft=_.position,ur(_,Ue,n,!1,!0),$t=_.tag,Xt=_.result,x(_,!0,Ue),Yr=_.input.charCodeAt(_.position),(Lt||_.line===Bt)&&Yr===58&&(Pt=!0,Yr=_.input.charCodeAt(++_.position),x(_,!0,Ue),ur(_,Ue,n,!1,!0),Er=_.result),Nt?ft(_,Ze,hr,$t,Xt,Er,Bt,ct,Ft):Pt?Ze.push(ft(_,null,hr,$t,Xt,Er,Bt,ct,Ft)):Ze.push(Xt),x(_,!0,Ue),Yr=_.input.charCodeAt(_.position),Yr===44?(lt=!0,Yr=_.input.charCodeAt(++_.position)):lt=!1}$(_,"unexpected end of the stream within a flow collection")}function re(_,Ue){let lt,Bt=A,ct=!1,Ft=!1,le=Ue,Ze=0,Tt=!1,Et,Pt=_.input.charCodeAt(_.position);if(Pt===124)lt=!1;else if(Pt===62)lt=!0;else return!1;for(_.kind="scalar",_.result="";Pt!==0;)if(Pt=_.input.charCodeAt(++_.position),Pt===43||Pt===45)A===Bt?Bt=Pt===43?w:m:$(_,"repeat of a chomping mode identifier");else if((Et=de(Pt))>=0)Et===0?$(_,"bad explicit indentation width of a block scalar; it cannot be less than one"):Ft?$(_,"repeat of an indentation width identifier"):(le=Ue+Et-1,Ft=!0);else break;if(ee(Pt)){do Pt=_.input.charCodeAt(++_.position);while(ee(Pt));if(Pt===35)do Pt=_.input.charCodeAt(++_.position);while(!V(Pt)&&Pt!==0)}for(;Pt!==0;){for(Me(_),_.lineIndent=0,Pt=_.input.charCodeAt(_.position);(!Ft||_.lineIndent<le)&&Pt===32;)_.lineIndent++,Pt=_.input.charCodeAt(++_.position);if(!Ft&&_.lineIndent>le&&(le=_.lineIndent),V(Pt)){Ze++;continue}if(!Ft&&le===0&&$(_,"missing indentation for block scalar"),_.lineIndent<le){Bt===w?_.result+=t.repeat(`
`,ct?1+Ze:Ze):Bt===A&&ct&&(_.result+=`
`);break}lt?ee(Pt)?(Tt=!0,_.result+=t.repeat(`
`,ct?1+Ze:Ze)):Tt?(Tt=!1,_.result+=t.repeat(`
`,Ze+1)):Ze===0?ct&&(_.result+=" "):_.result+=t.repeat(`
`,Ze):_.result+=t.repeat(`
`,ct?1+Ze:Ze),ct=!0,Ft=!0,Ze=0;let Lt=_.position;for(;!V(Pt)&&Pt!==0;)Pt=_.input.charCodeAt(++_.position);He(_,Lt,_.position,!1)}return!0}function ce(_,Ue){let lt=_.tag,Bt=_.anchor,ct=[],Ft=!1;if(_.firstTabInLine!==-1)return!1;_.anchor!==null&&Te(_,_.anchor,ct);let le=_.input.charCodeAt(_.position);for(;le!==0&&(_.firstTabInLine!==-1&&(_.position=_.firstTabInLine,$(_,"tab characters must not be used in indentation")),le===45);){let Ze=_.input.charCodeAt(_.position+1);if(!te(Ze))break;if(Ft=!0,_.position++,x(_,!0,-1)&&_.lineIndent<=Ue){ct.push(null),le=_.input.charCodeAt(_.position);continue}let Tt=_.line;if(ur(_,Ue,f,!1,!0),ct.push(_.result),x(_,!0,-1),le=_.input.charCodeAt(_.position),(_.line===Tt||_.lineIndent>Ue)&&le!==0)$(_,"bad indentation of a sequence entry");else if(_.lineIndent<Ue)break}return Ft?(_.tag=lt,_.anchor=Bt,_.kind="sequence",_.result=ct,!0):!1}function ke(_,Ue,lt){let Bt,ct,Ft,le,Ze=_.tag,Tt=_.anchor,Et={},Pt=Object.create(null),Lt=null,Nt=null,hr=null,Xt=!1,$t=!1;if(_.firstTabInLine!==-1)return!1;_.anchor!==null&&Te(_,_.anchor,Et);let Er=_.input.charCodeAt(_.position);for(;Er!==0;){!Xt&&_.firstTabInLine!==-1&&(_.position=_.firstTabInLine,$(_,"tab characters must not be used in indentation"));let Yr=_.input.charCodeAt(_.position+1),Tn=_.line;if((Er===63||Er===58)&&te(Yr))Er===63?(Xt&&(ft(_,Et,Pt,Lt,Nt,null,ct,Ft,le),Lt=Nt=hr=null),$t=!0,Xt=!0,Bt=!0):Xt?(Xt=!1,Bt=!0):$(_,"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"),_.position+=1,Er=Yr;else{if(ct=_.line,Ft=_.lineStart,le=_.position,!ur(_,lt,l,!1,!0))break;if(_.line===Tn){for(Er=_.input.charCodeAt(_.position);ee(Er);)Er=_.input.charCodeAt(++_.position);if(Er===58)Er=_.input.charCodeAt(++_.position),te(Er)||$(_,"a whitespace character is expected after the key-value separator within a block mapping"),Xt&&(ft(_,Et,Pt,Lt,Nt,null,ct,Ft,le),Lt=Nt=hr=null),$t=!0,Xt=!1,Bt=!1,Lt=_.tag,Nt=_.result;else if($t)$(_,"can not read an implicit mapping pair; a colon is missed");else return _.tag=Ze,_.anchor=Tt,!0}else if($t)$(_,"can not read a block mapping entry; a multiline key may not be an implicit key");else return _.tag=Ze,_.anchor=Tt,!0}if((_.line===Tn||_.lineIndent>Ue)&&(Xt&&(ct=_.line,Ft=_.lineStart,le=_.position),ur(_,Ue,h,!0,Bt)&&(Xt?Nt=_.result:hr=_.result),Xt||(ft(_,Et,Pt,Lt,Nt,hr,ct,Ft,le),Lt=Nt=hr=null),x(_,!0,-1),Er=_.input.charCodeAt(_.position)),(_.line===Tn||_.lineIndent>Ue)&&Er!==0)$(_,"bad indentation of a mapping entry");else if(_.lineIndent<Ue)break}return Xt&&ft(_,Et,Pt,Lt,Nt,null,ct,Ft,le),$t&&(_.tag=Ze,_.anchor=Tt,_.kind="mapping",_.result=Et),$t}function Le(_){let Ue=!1,lt=!1,Bt,ct,Ft=_.input.charCodeAt(_.position);if(Ft!==33)return!1;_.tag!==null&&$(_,"duplication of a tag property"),Ft=_.input.charCodeAt(++_.position),Ft===60?(Ue=!0,Ft=_.input.charCodeAt(++_.position)):Ft===33?(lt=!0,Bt="!!",Ft=_.input.charCodeAt(++_.position)):Bt="!";let le=_.position;if(Ue){do Ft=_.input.charCodeAt(++_.position);while(Ft!==0&&Ft!==62);_.position<_.length?(ct=_.input.slice(le,_.position),Ft=_.input.charCodeAt(++_.position)):$(_,"unexpected end of the stream within a verbatim tag")}else{for(;Ft!==0&&!te(Ft);)Ft===33&&(lt?$(_,"tag suffix cannot contain exclamation marks"):(Bt=_.input.slice(le-1,_.position+1),R.test(Bt)||$(_,"named tag handle cannot contain such characters"),lt=!0,le=_.position+1)),Ft=_.input.charCodeAt(++_.position);ct=_.input.slice(le,_.position),I.test(ct)&&$(_,"tag suffix cannot contain flow indicator characters")}ct&&!N.test(ct)&&$(_,"tag name cannot contain such characters: "+ct);try{ct=decodeURIComponent(ct)}catch{$(_,"tag name is malformed: "+ct)}return Ue?_.tag=ct:a.call(_.tagMap,Bt)?_.tag=_.tagMap[Bt]+ct:Bt==="!"?_.tag="!"+ct:Bt==="!!"?_.tag="tag:yaml.org,2002:"+ct:$(_,'undeclared tag handle "'+Bt+'"'),!0}function pt(_){let Ue=_.input.charCodeAt(_.position);if(Ue!==38)return!1;_.anchor!==null&&$(_,"duplication of an anchor property"),Ue=_.input.charCodeAt(++_.position);let lt=_.position;for(;Ue!==0&&!te(Ue)&&!ie(Ue);)Ue=_.input.charCodeAt(++_.position);return _.position===lt&&$(_,"name of an anchor node must contain at least one character"),_.anchor=_.input.slice(lt,_.position),!0}function St(_){let Ue=_.input.charCodeAt(_.position);if(Ue!==42)return!1;Ue=_.input.charCodeAt(++_.position);let lt=_.position;for(;Ue!==0&&!te(Ue)&&!ie(Ue);)Ue=_.input.charCodeAt(++_.position);_.position===lt&&$(_,"name of an alias node must contain at least one character");let Bt=_.input.slice(lt,_.position);return a.call(_.anchorMap,Bt)||$(_,'unidentified alias "'+Bt+'"'),_.result=_.anchorMap[Bt],x(_,!0,-1),!0}function er(_,Ue,lt,Bt){let ct=Ne(_);return ot(_),Fe(_,Ue),_.tag=null,_.anchor=null,_.kind=null,_.result=null,ke(_,lt,Bt)&&_.kind==="mapping"?(j(_),!0):(rt(_),Fe(_,ct),!1)}function ur(_,Ue,lt,Bt,ct){let Ft,le,Ze=1,Tt=!1,Et=!1,Pt=null,Lt,Nt,hr;_.depth>=_.maxDepth&&$(_,"nesting exceeded maxDepth ("+_.maxDepth+")"),_.depth+=1,_.listener!==null&&_.listener("open",_),_.tag=null,_.anc Line truncated
`),_.charCodeAt(0)===65279&&(_=_.slice(1)));let lt=new Ee(_,Ue),Bt=_.indexOf("\0");for(Bt!==-1&&(lt.position=Bt,$(lt,"null byte is not allowed in input")),lt.input+="\0";lt.input.charCodeAt(lt.position)===32;)lt.lineIndent+=1,lt.position+=1;for(;lt.position<lt.length-1;)Ht(lt);return lt.documents}function Ur(_,Ue,lt){Ue!==null&&typeof Ue=="object"&&typeof lt>"u"&&(lt=Ue,Ue=null);let Bt=Cn(_,lt);if(typeof Ue!="function")return Bt;for(let ct=0,Ft=Bt.length;ct<Ft;ct+=1)Ue(Bt[ct])}function kr(_,Ue){let lt=Cn(_,Ue);if(lt.length!==0){if(lt.length===1)return lt[0];throw new e("expected a single document in the stream, but found more")}}return TT.loadAll=Ur,TT.load=kr,TT}function z$e(){if(Rle)return lH;Rle=1;let t=uS(),e=fS(),r=uH(),s=Object.prototype.toString,a=Object.prototype.hasOwnProperty,n=65279,l=9,f=10,h=13,A=32,m=33,w=34,v=35,D=37,I=38,R=39,N=42,U=44,V=45,ee=58,te=61,ie=62,ae=63,ge=64,de=91,xe=93,we=96,d=123,be=124,Ce=125,Ee={};Ee[0]="\\0",Ee[7]="\\a",Ee[8]="\\b",Ee[9]="\\t",Ee[10]="\\n",Ee[11]="\\v",Ee[12]="\\f",Ee[13]="\\r",Ee[27]="\\e",Ee[34]='\\"',Ee[92]="\\\\",Ee[133]="\\N",Ee[160]="\\_",Ee[8232]="\\L",Ee[8233]="\\P";let he=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],$=/^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;function De(le,Ze){if(Ze===null)return{};let Tt={},Et=Object.keys(Ze);for(let Pt=0,Lt=Et.length;Pt<Lt;Pt+=1){let Nt=Et[Pt],hr=String(Ze[Nt]);Nt.slice(0,2)==="!!"&&(Nt="tag:yaml.org,2002:"+Nt.slice(2));let Xt=le.compiledTypeMap.fallback[Nt];Xt&&a.call(Xt.styleAliases,hr)&&(hr=Xt.styleAliases[hr]),Tt[Nt]=hr}return Tt}function Te(le){let Ze,Tt,Et=le.toString(16).toUpperCase();if(le<=255)Ze="x",Tt=2;else if(le<=65535)Ze="u",Tt=4;else if(le<=4294967295)Ze="U",Tt=8;else throw new e("code point within a string may not be greater than 0xFFFFFFFF");return"\\"+Ze+t.repeat("0",Tt-Et.length)+Et}let ot=1,j=2;function rt(le){this.schema=le.schema||r,this.indent=Math.max(1,le.indent||2),this.noArrayIndent=le.noArrayIndent||!1,this.skipInvalid=le.skipInvalid||!1,this.flowLevel=t.isNothing(le.flowLevel)?-1:le.flowLevel,this.styleMap=De(this.schema,le.styles||null),this.sortKeys=le.sortKeys||!1,this.lineWidth=le.lineWidth||80,this.noRefs=le.noRefs||!1,this.noCompatMode=le.noCompatMode||!1,this.condenseFlow=le.condenseFlow||!1,this.quotingType=le.quotingType==='"'?j:ot,this.forceQuotes=le.forceQuotes||!1,this.replacer=typeof le.replacer=="function"?le.replacer:null,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function Ne(le,Ze){let Tt=t.repeat(" ",Ze),Et=0,Pt="",Lt=le.length;for(;Et<Lt;){let Nt,hr=le.indexOf(`
`,Et);hr===-1?(Nt=le.slice(Et),Et=Lt):(Nt=le.slice(Et,hr+1),Et=hr+1),Nt.length&&Nt!==`
`&&(Pt+=Tt),Pt+=Nt}return Pt}function Fe(le,Ze){return`
`+t.repeat(" ",le.indent*Ze)}function Pe(le,Ze){for(let Tt=0,Et=le.implicitTypes.length;Tt<Et;Tt+=1)if(le.implicitTypes[Tt].resolve(Ze))return!0;return!1}function He(le){return le===A||le===l}function Qe(le){return le>=32&&le<=126||le>=161&&le<=55295&&le!==8232&&le!==8233||le>=57344&&le<=65533&&le!==n||le>=65536&&le<=1114111}function ft(le){return Qe(le)&&le!==n&&le!==h&&le!==f}function Me(le,Ze,Tt){let Et=ft(le),Pt=Et&&!He(le);return(Tt?Et:Et&&le!==U&&le!==de&&le!==xe&&le!==d&&le!==Ce)&&le!==v&&!(Ze===ee&&!Pt)||ft(Ze)&&!He(Ze)&&le===v||Ze===ee&&Pt}function x(le){return Qe(le)&&le!==n&&!He(le)&&le!==V&&le!==ae&&le!==ee&&le!==U&&le!==de&&le!==xe&&le!==d&&le!==Ce&&le!==v&&le!==I&&le!==N&&le!==m&&le!==be&&le!==te&&le!==ie&&le!==R&&le!==w&&le!==D&&le!==ge&&le!==we}function C(le){return!He(le)&&le!==ee}function P(le,Ze){let Tt=le.charCodeAt(Ze),Et;return Tt>=55296&&Tt<=56319&&Ze+1<le.length&&(Et=le.charCodeAt(Ze+1),Et>=56320&&Et<=57343)?(Tt-55296)*1024+Et-56320+65536:Tt}function E(le){return/^\n* /.test(le)}let F=1,Z=2,X=3,re=4,ce=5;function ke(le,Ze,Tt,Et,Pt,Lt,Nt,hr){let Xt,$t=0,Er=null,Yr=!1,Tn=!1,yc=Et!==-1,Ro=-1,La=x(P(le,0))&&C(P(le,le.length-1));if(Ze||Nt)for(Xt=0;Xt<le.length;$t>=65536?Xt+=2:Xt++){if($t=P(le,Xt),!Qe($t))return ce;La=La&&Me($t,Er,hr),Er=$t}else{for(Xt=0;Xt<le.length;$t>=65536?Xt+=2:Xt++){if($t=P(le,Xt),$t===f)Yr=!0,yc&&(Tn=Tn||Xt-Ro-1>Et&&le[Ro+1]!==" ",Ro=Xt);else if(!Qe($t))return ce;La=La&&Me($t,Er,hr),Er=$t}Tn=Tn||yc&&Xt-Ro-1>Et&&le[Ro+1]!==" "}return!Yr&&!Tn?La&&!Nt&&!Pt(le)?F:Lt===j?ce:Z:Tt>9&&E(le)?ce:Nt?Lt===j?ce:Z:Tn?re:X}function Le(le,Ze,Tt,Et,Pt){le.dump=function(){if(Ze.length===0)return le.quotingType===j?'""':"''";if(!le.noCompatMode&&(he.indexOf(Ze)!==-1||$.test(Ze)))return le.quotingType===j?'"'+Ze+'"':"'"+Ze+"'";let Lt=le.indent*Math.max(1,Tt),Nt=le.lineWidth===-1?-1:Math.max(Math.min(le.lineWidth,40),le.lineWidth-Lt),hr=Et||le.flowLevel>-1&&Tt>=le.flowLevel;function Xt($t){return Pe(le,$t)}switch(ke(Ze,hr,le.indent,Nt,Xt,le.quotingType,le.forceQuotes&&!Et,Pt)){case F:return Ze;case Z:return"'"+Ze.replace(/'/g,"''")+"'";case X:return"|"+pt(Ze,le.indent)+St(Ne(Ze,Lt));case re:return">"+pt(Ze,le.indent)+St(Ne(er(Ze,Nt),Lt));case ce:return'"'+Ht(Ze)+'"';default:throw new e("impossible error: invalid scalar style")}}()}function pt(le,Ze){let Tt=E(le)?String(Ze):"",Et=le[le.length-1]===`
`,Lt=Et&&(le[le.length-2]===`
`||le===`
`)?"+":Et?"":"-";return Tt+Lt+`
`}function St(le){return le[le.length-1]===`
`?le.slice(0,-1):le}function er(le,Ze){let Tt=/(\n+)([^\n]*)/g,Et=function(){let hr=le.indexOf(`
`);return hr=hr!==-1?hr:le.length,Tt.lastIndex=hr,ur(le.slice(0,hr),Ze)}(),Pt=le[0]===`
`||le[0]===" ",Lt,Nt;for(;Nt=Tt.exec(le);){let hr=Nt[1],Xt=Nt[2];Lt=Xt[0]===" ",Et+=hr+(!Pt&&!Lt&&Xt!==""?`
`:"")+ur(Xt,Ze),Pt=Lt}return Et}function ur(le,Ze){if(le===""||le[0]===" ")return le;let Tt=/ [^ ]/g,Et,Pt=0,Lt,Nt=0,hr=0,Xt="";for(;Et=Tt.exec(le);)hr=Et.index,hr-Pt>Ze&&(Lt=Nt>Pt?Nt:hr,Xt+=`
`+le.slice(Pt,Lt),Pt=Lt+1),Nt=hr;return Xt+=`
`,le.length-Pt>Ze&&Nt>Pt?Xt+=le.slice(Pt,Nt)+`
`+le.slice(Nt+1):Xt+=le.slice(Pt),Xt.slice(1)}function Ht(le){let Ze="",Tt=0;for(let Et=0;Et<le.length;Tt>=65536?Et+=2:Et++){Tt=P(le,Et);let Pt=Ee[Tt];!Pt&&Qe(Tt)?(Ze+=le[Et],Tt>=65536&&(Ze+=le[Et+1])):Ze+=Pt||Te(Tt)}return Ze}function Cn(le,Ze,Tt){let Et="",Pt=le.tag;for(let Lt=0,Nt=Tt.length;Lt<Nt;Lt+=1){let hr=Tt[Lt];le.replacer&&(hr=le.replacer.call(Tt,String(Lt),hr)),(lt(le,Ze,hr,!1,!1)||typeof hr>"u"&&lt(le,Ze,null,!1,!1))&&(Et!==""&&(Et+=","+(le.condenseFlow?"":" ")),Et+=le.dump)}le.tag=Pt,le.dump="["+Et+"]"}function Ur(le,Ze,Tt,Et){let Pt="",Lt=le.tag;for(let Nt=0,hr=Tt.length;Nt<hr;Nt+=1){let Xt=Tt[Nt];le.replacer&&(Xt=le.replacer.call(Tt,String(Nt),Xt)),(lt(le,Ze+1,Xt,!0,!0,!1,!0)||typeof Xt>"u"&&lt(le,Ze+1,null,!0,!0,!1,!0))&&((!Et||Pt!=="")&&(Pt+=Fe(le,Ze)),le.dump&&f===le.dump.charCodeAt(0)?Pt+="-":Pt+="- ",Pt+=le.dump)}le.tag=Lt,le.dump=Pt||"[]"}function kr(le,Ze,Tt){let Et="",Pt=le.tag,Lt=Object.keys(Tt);for(let Nt=0,hr=Lt.length;Nt<hr;Nt+=1){let Xt="";Et!==""&&(Xt+=", "),le.condenseFlow&&(Xt+='"');let $t=Lt[Nt],Er=Tt[$t];le.replacer&&(Er=le.replacer.call(Tt,$t,Er)),lt(le,Ze,$t,!1,!1)&&(le.dump.length>1024&&(Xt+="? "),Xt+=le.dump+(le.condenseFlow?'"':"")+":"+(le.condenseFlow?"":" "),lt(le,Ze,Er,!1,!1)&&(Xt+=le.dump,Et+=Xt))}le.tag=Pt,le.dump="{"+Et+"}"}function _(le,Ze,Tt,Et){let Pt="",Lt=le.tag,Nt=Object.keys(Tt);if(le.sortKeys===!0)Nt.sort();else if(typeof le.sortKeys=="function")Nt.sort(le.sortKeys);else if(le.sortKeys)throw new e("sortKeys must be a boolean or a function");for(let hr=0,Xt=Nt.length;hr<Xt;hr+=1){let $t="";(!Et||Pt!=="")&&($t+=Fe(le,Ze));let Er=Nt[hr],Yr=Tt[Er];if(le.replacer&&(Yr=le.replacer.call(Tt,Er,Yr)),!lt(le,Ze+1,Er,!0,!0,!0))continue;let Tn=le.tag!==null&&le.tag!=="?"||le.dump&&le.dump.length>1024;Tn&&(le.dump&&f===le.dump.charCodeAt(0)?$t+="?":$t+="? "),$t+=le.dump,Tn&&($t+=Fe(le,Ze)),lt(le,Ze+1,Yr,!0,Tn)&&(le.dump&&f===le.dump.charCodeAt(0)?$t+=":":$t+=": ",$t+=le.dump,Pt+=$t)}le.tag=Lt,le.dump=Pt||"{}"}function Ue(le,Ze,Tt){let Et=Tt?le.explicitTypes:le.implicitTypes;for(let Pt=0,Lt=Et.length;Pt<Lt;Pt+=1){let Nt=Et[Pt];if((Nt.instanceOf||Nt.predicate)&&(!Nt.instanceOf||typeof Ze=="object"&&Ze instanceof Nt.instanceOf)&&(!Nt.predicate||Nt.predicate(Ze))){if(Tt?Nt.multi&&Nt.representName?le.tag=Nt.representName(Ze):le.tag=Nt.tag:le.tag="?",Nt.represent){let hr=le.styleMap[Nt.tag]||Nt.defaultStyle,Xt;if(s.call(Nt.represent)==="[object Function]")Xt=Nt.represent(Ze,hr);else if(a.call(Nt.represent,hr))Xt=Nt.represent[hr](Ze,hr);else throw new e("!<"+Nt.tag+'> tag resolver accepts not "'+hr+'" style');le.dump=Xt}return!0}}return!1}function lt(le,Ze,Tt,Et,Pt,Lt,Nt){le.tag=null,le.dump=Tt,Ue(le,Tt,!1)||Ue(le,Tt,!0);let hr=s.call(le.dump),Xt=Et;Et&&(Et=le.flowLevel<0||le.flowLevel>Ze);let $t=hr==="[object Object]"||hr==="[object Array]",Er,Yr;if($t&&(Er=le.duplicates.indexOf(Tt),Yr=Er!==-1),(le.tag!==null&&le.tag!=="?"||Yr||le.indent!==2&&Ze>0)&&(Pt=!1),Yr&&le.usedDuplicates[Er])le.dump="*ref_"+Er;else{if($t&&Yr&&!le.usedDuplicates[Er]&&(le.usedDuplicates[Er]=!0),hr==="[object Object]")Et&&Object.keys(le.dump).length!==0?(_(le,Ze,le.dump,Pt),Yr&&(le.dump="&ref_"+Er+le.dump)):(kr(le,Ze,le.dump),Yr&&(le.dump="&ref_"+Er+" "+le.dump));else if(hr==="[object Array]")Et&&le.dump.length!==0?(le.noArrayIndent&&!Nt&&Ze>0?Ur(le,Ze-1,le.dump,Pt):Ur(le,Ze,le.dump,Pt),Yr&&(le.dump="&ref_"+Er+le.dump)):(Cn(le,Ze,le.dump),Yr&&(le.dump="&ref_"+Er+" "+le.dump));else if(hr==="[object String]")le.tag!=="?"&&Le(le,le.dump,Ze,Lt,Xt);else{if(hr==="[object Undefined]")return!1;if(le.skipInvalid)return!1;throw new e("unacceptable kind of an object to dump "+hr)}if(le.tag!==null&&le.tag!=="?"){let Tn=encodeURI(le.tag[0]==="!"?le.tag.slice(1):le.tag).replace(/!/g,"%21");le.tag[0]==="!"?Tn="!"+Tn:Tn.slice(0,18)==="tag:yaml.org,2002:"?Tn="!!"+Tn.slice(18):Tn="!<"+Tn+">",le.dump=Tn+" "+le.dump}}return!0}function Bt(le,Ze){let Tt=[],Et=[];ct(le,Tt,Et);let Pt=Et.length;for(let Lt=0;Lt<Pt;Lt+=1)Ze.duplicates.push(Tt[Et[Lt]]);Ze.usedDuplicates=new Array(Pt)}function ct(le,Ze,Tt){if(le!==null&&typeof le=="object"){let Et=Ze.indexOf(le);if(Et!==-1)Tt.indexOf(Et)===-1&&Tt.push(Et);else if(Ze.push(le),Array.isArray(le))for(let Pt=0,Lt=le.length;Pt<Lt;Pt+=1)ct(le[Pt],Ze,Tt);else{let Pt=Object.keys(le);for(let Lt=0,Nt=Pt.length;Lt<Nt;Lt+=1)ct(le[Pt[Lt]],Ze,Tt)}}}function Ft(le,Ze){Ze=Ze||{};let Tt=new rt(Ze);Tt.noRefs||Bt(le,Tt);let Et=le;return Tt.replacer&&(Et=Tt.replacer.call({"":Et},"",Et)),lt(Tt,0,Et,!0,!0)?Tt.dump+`
`:""}return lH.dump=Ft,lH}function J$e(){if(Tle)return pa;Tle=1;let t=K$e(),e=z$e();function r(s,a){return function(){throw new Error("Function yaml."+s+" is removed in js-yaml 4. Use yaml."+a+" instead, which is now safe by default.")}}return pa.Type=Za(),pa.Schema=Qle(),pa.FAILSAFE_SCHEMA=Lle(),pa.JSON_SCHEMA=jle(),pa.CORE_SCHEMA=Gle(),pa.DEFAULT_SCHEMA=uH(),pa.load=t.load,pa.loadAll=t.loadAll,pa.dump=e.dump,pa.YAMLException=fS(),pa.types={binary:Wle(),float:Hle(),map:Ole(),null:_le(),pairs:Kle(),set:zle(),timestamp:qle(),bool:Mle(),int:Ule(),merge:Vle(),omap:Yle(),seq:Nle(),str:Fle()},pa.safeLoad=r("safeLoad","load"),pa.safeLoadAll=r("safeLoadAll","loadAll"),pa.safeDump=r("safeDump","dump"),pa}var pa,TT,S0,cle,j6,lle,G6,ule,q6,fle,V6,hle,W6,Ale,Y6,ple,K6,dle,z6,gle,J6,mle,Z6,yle,X6,Ele,$6,Ile,eH,wle,tH,Cle,rH,Ble,nH,vle,iH,Sle,sH,ble,oH,Dle,aH,Ple,cH,xle,kle,lH,Rle,Tle,Z$e,X$e,hqt,Aqt,Jle,pqt,dqt,gqt,Zle,mqt,yqt,Eqt,Iqt,wqt,Cqt,Bqt,Xle=tt(()=>{pa={},TT={},S0={};lH={};Z$e=J$e(),X$e=W$e(Z$e),{Type:hqt,Schema:Aqt,FAILSAFE_SCHEMA:Jle,JSON_SCHEMA:pqt,CORE_SCHEMA:dqt,DEFAULT_SCHEMA:gqt,load:Zle,loadAll:mqt,dump:yqt,YAMLException:Eqt,types:Iqt,safeLoad:wqt,safeLoadAll:Cqt,safeDump:Bqt}=X$e});var eue=H((Sqt,$le)=>{"use strict";function $$e(t,e){function r(){this.constructor=t}r.prototype=e.prototype,t.prototype=new r}function cy(t,e,r,s){this.message=t,this.expected=e,this.found=r,this.location=s,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,cy)}$$e(cy,Error);cy.buildMessage=function(t,e){var r={literal:function(A){return'"'+a(A.text)+'"'},class:function(A){var m="",w;for(w=0;w<A.parts.length;w++)m+=A.parts[w]instanceof Array?n(A.parts[w][0])+"-"+n(A.parts[w][1]):n(A.parts[w]);return"["+(A.inverted?"^":"")+m+"]"},any:function(A){return"any character"},end:function(A){return"end of input"},other:function(A){return A.description}};function s(A){return A.charCodeAt(0).toString(16).toUpperCase()}function a(A){return A.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(m){return"\\x0"+s(m)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(m){return"\\x"+s(m)})}function n(A){return A.replace(/\\/g,"\\\\").replace(/\]/g,"\\]").replace(/\^/g,"\\^").replace(/-/g,"\\-").replace(/\0/g,"\\0").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/[\x00-\x0F]/g,function(m){return"\\x0"+s(m)}).replace(/[\x10-\x1F\x7F-\x9F]/g,function(m){return"\\x"+s(m)})}function l(A){return r[A.type](A)}function f(A){var m=new Array(A.length),w,v;for(w=0;w<A.length;w++)m[w]=l(A[w]);if(m.sort(),m.length>0){for(w=1,v=1;w<m.length;w++)m[w-1]!==m[w]&&(m[v]=m[w],v++);m.length=v}switch(m.length){case 1:return m[0];case 2:return m[0]+" or "+m[1];default:return m.slice(0,-1).join(", ")+", or "+m[m.length-1]}}function h(A){return A?'"'+a(A)+'"':"end of input"}return"Expected "+f(t)+" but "+h(e)+" found."};function eet(t,e){e=e!==void 0?e:{};var r={},s={Start:Yl},a=Yl,n=function(ne){return[].concat(...ne)},l="-",f=Un("-",!1),h=function(ne){return ne},A=function(ne){return Object.assign({},...ne)},m="#",w=Un("#",!1),v=$u(),D=function(){return{}},I=":",R=Un(":",!1),N=function(ne,Be){return{[ne]:Be}},U=",",V=Un(",",!1),ee=function(ne,Be){return Be},te=function(ne,Be,_e){return Object.assign({},...[ne].concat(Be).map(bt=>({[bt]:_e})))},ie=function(ne){return ne},ae=function(ne){return ne},ge=wc("correct indentation"),de=" ",xe=Un(" ",!1),we=function(ne){return ne.length===Sr*_t},d=function(ne){return ne.length===(Sr+1)*_t},be=function(){return Sr++,!0},Ce=function(){return Sr--,!0},Ee=function(){return Ha()},he=wc("pseudostring"),$=/^[^\r\n\t ?:,\][{}#&*!|>'"%@`\-]/,De=Ei(["\r",`
`," "," ","?",":",",","]","[","{","}","#","&","*","!","|",">","'",'"',"%","@","`","-"],!0,!1),Te=/^[^\r\n\t ,\][{}:#"']/,ot=Ei(["\r",`
`," "," ",",","]","[","{","}",":","#",'"',"'"],!0,!1),j=function(){return Ha().replace(/^ *| *$/g,"")},rt="--",Ne=Un("--",!1),Fe=/^[a-zA-Z\/0-9]/,Pe=Ei([["a","z"],["A","Z"],"/",["0","9"]],!1,!1),He=/^[^\r\n\t :,]/,Qe=Ei(["\r",`
`," "," ",":",","],!0,!1),ft="null",Me=Un("null",!1),x=function(){return null},C="true",P=Un("true",!1),E=function(){return!0},F="false",Z=Un("false",!1),X=function(){return!1},re=wc("string"),ce='"',ke=Un('"',!1),Le=function(){return""},pt=function(ne){return ne},St=function(ne){return ne.join("")},er=/^[^"\\\0-\x1F\x7F]/,ur=Ei(['"',"\\",["\0",""],"\x7F"],!0,!1),Ht='\\"',Cn=Un('\\"',!1),Ur=function(){return'"'},kr="\\\\",_=Un("\\\\",!1),Ue=function(){return"\\"},lt="\\/",Bt=Un("\\/",!1),ct=function(){return"/"},Ft="\\b",le=Un("\\b",!1),Ze=function(){return"\b"},Tt="\\f",Et=Un("\\f",!1),Pt=function(){return"\f"},Lt="\\n",Nt=Un("\\n",!1),hr=function(){return`
`},Xt="\\r",$t=Un("\\r",!1),Er=function(){return"\r"},Yr="\\t",Tn=Un("\\t",!1),yc=function(){return" "},Ro="\\u",La=Un("\\u",!1),HA=function(ne,Be,_e,bt){return String.fromCharCode(parseInt(`0x${ne}${Be}${_e}${bt}`))},Ma=/^[0-9a-fA-F]/,Ua=Ei([["0","9"],["a","f"],["A","F"]],!1,!1),jA=wc("blank space"),Fr=/^[ \t]/,Zo=Ei([" "," "],!1,!1),Ec=wc("white space"),Ge=/^[ \t\n\r]/,Hr=Ei([" "," ",`
`,"\r"],!1,!1),oh=`\r
`,GA=Un(`\r
`,!1),qA=`
`,Zu=Un(`
`,!1),Xu="\r",Vl=Un("\r",!1),ve=0,Jt=0,Wl=[{line:1,column:1}],as=0,To=[],Vt=0,ei;if("startRule"in e){if(!(e.startRule in s))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=s[e.startRule]}function Ha(){return t.substring(Jt,ve)}function As(){return Bc(Jt,ve)}function cs(ne,Be){throw Be=Be!==void 0?Be:Bc(Jt,ve),ah([wc(ne)],t.substring(Jt,ve),Be)}function Ic(ne,Be){throw Be=Be!==void 0?Be:Bc(Jt,ve),vc(ne,Be)}function Un(ne,Be){return{type:"literal",text:ne,ignoreCase:Be}}function Ei(ne,Be,_e){return{type:"class",parts:ne,inverted:Be,ignoreCase:_e}}function $u(){return{type:"any"}}function Ud(){return{type:"end"}}function wc(ne){return{type:"other",description:ne}}function Cc(ne){var Be=Wl[ne],_e;if(Be)return Be;for(_e=ne-1;!Wl[_e];)_e--;for(Be=Wl[_e],Be={line:Be.line,column:Be.column};_e<ne;)t.charCodeAt(_e)===10?(Be.line++,Be.column=1):Be.column++,_e++;return Wl[ne]=Be,Be}function Bc(ne,Be){var _e=Cc(ne),bt=Cc(Be);return{start:{offset:ne,line:_e.line,column:_e.column},end:{offset:Be,line:bt.line,column:bt.column}}}function it(ne){ve<as||(ve>as&&(as=ve,To=[]),To.push(ne))}function vc(ne,Be){return new cy(ne,null,null,Be)}function ah(ne,Be,_e){return new cy(cy.buildMessage(ne,Be),ne,Be,_e)}function Yl(){var ne;return ne=VA(),ne}function Yn(){var ne,Be,_e;for(ne=ve,Be=[],_e=ja();_e!==r;)Be.push(_e),_e=ja();return Be!==r&&(Jt=ne,Be=n(Be)),ne=Be,ne}function ja(){var ne,Be,_e,bt,xt;return ne=ve,Be=ll(),Be!==r?(t.charCodeAt(ve)===45?(_e=l,ve++):(_e=r,Vt===0&&it(f)),_e!==r?(bt=ri(),bt!==r?(xt=Ga(),xt!==r?(Jt=ne,Be=h(xt),ne=Be):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r),ne}function VA(){var ne,Be,_e;for(ne=ve,Be=[],_e=WA();_e!==r;)Be.push(_e),_e=WA();return Be!==r&&(Jt=ne,Be=A(Be)),ne=Be,ne}function WA(){var ne,Be,_e,bt,xt,jt,Ir,Nn,Qi;if(ne=ve,Be=ri(),Be===r&&(Be=null),Be!==r){if(_e=ve,t.charCodeAt(ve)===35?(bt=m,ve++):(bt=r,Vt===0&&it(w)),bt!==r){if(xt=[],jt=ve,Ir=ve,Vt++,Nn=dt(),Vt--,Nn===r?Ir=void 0:(ve=Ir,Ir=r),Ir!==r?(t.length>ve?(Nn=t.charAt(ve),ve++):(Nn=r,Vt===0&&it(v)),Nn!==r?(Ir=[Ir,Nn],jt=Ir):(ve=jt,jt=r)):(ve=jt,jt=r),jt!==r)for(;jt!==r;)xt.push(jt),jt=ve,Ir=ve,Vt++,Nn=dt(),Vt--,Nn===r?Ir=void 0:(ve=Ir,Ir=r),Ir!==r?(t.length>ve?(Nn=t.charAt(ve),ve++):(Nn=r,Vt===0&&it(v)),Nn!==r?(Ir=[Ir,Nn],jt=Ir):(ve=jt,jt=r)):(ve=jt,jt=r);else xt=r;xt!==r?(bt=[bt,xt],_e=bt):(ve=_e,_e=r)}else ve=_e,_e=r;if(_e===r&&(_e=null),_e!==r){if(bt=[],xt=et(),xt!==r)for(;xt!==r;)bt.push(xt),xt=et();else bt=r;bt!==r?(Jt=ne,Be=D(),ne=Be):(ve=ne,ne=r)}else ve=ne,ne=r}else ve=ne,ne=r;if(ne===r&&(ne=ve,Be=ll(),Be!==r?(_e=Sc(),_e!==r?(bt=ri(),bt===r&&(bt=null),bt!==r?(t.charCodeAt(ve)===58?(xt=I,ve++):(xt=r,Vt===0&&it(R)),xt!==r?(jt=ri(),jt===r&&(jt=null),jt!==r?(Ir=Ga(),Ir!==r?(Jt=ne,Be=N(_e,Ir),ne=Be):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r),ne===r&&(ne=ve,Be=ll(),Be!==r?(_e=ks(),_e!==r?(bt=ri(),bt===r&&(bt=null),bt!==r?(t.charCodeAt(ve)===58?(xt=I,ve++):(xt=r,Vt===0&&it(R)),xt!==r?(jt=ri(),jt===r&&(jt=null),jt!==r?(Ir=Ga(),Ir!==r?(Jt=ne,Be=N(_e,Ir),ne=Be):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r),ne===r))){if(ne=ve,Be=ll(),Be!==r)if(_e=ks(),_e!==r)if(bt=ri(),bt!==r)if(xt=ef(),xt!==r){if(jt=[],Ir=et(),Ir!==r)for(;Ir!==r;)jt.push(Ir),Ir=et();else jt=r;jt!==r?(Jt=ne,Be=N(_e,xt),ne=Be):(ve=ne,ne=r)}else ve=ne,ne=r;else ve=ne,ne=r;else ve=ne,ne=r;else ve=ne,ne=r;if(ne===r)if(ne=ve,Be=ll(),Be!==r)if(_e=ks(),_e!==r){if(bt=[],xt=ve,jt=ri(),jt===r&&(jt=null),jt!==r?(t.charCodeAt(ve)===44?(Ir=U,ve++):(Ir=r,Vt===0&&it(V)),Ir!==r?(Nn=ri(),Nn===r&&(Nn=null),Nn!==r?(Qi=ks(),Qi!==r?(Jt=xt,jt=ee(_e,Qi),xt=jt):(ve=xt,xt=r)):(ve=xt,xt=r)):(ve=xt,xt=r)):(ve=xt,xt=r),xt!==r)for(;xt!==r;)bt.push(xt),xt=ve,jt=ri(),jt===r&&(jt=null),jt!==r?(t.charCodeAt(ve)===44?(Ir=U,ve++):(Ir=r,Vt===0&&it(V)),Ir!==r?(Nn=ri(),Nn===r&&(Nn=null),Nn!==r?(Qi=ks(),Qi!==r?(Jt=xt,jt=ee(_e,Qi),xt=jt):(ve=xt,xt=r)):(ve=xt,xt=r)):(ve=xt,xt=r)):(ve=xt,xt=r);else bt=r;bt!==r?(xt=ri(),xt===r&&(xt=null),xt!==r?(t.charCodeAt(ve)===58?(jt=I,ve++):(jt=r,Vt===0&&it(R)),jt!==r?(Ir=ri(),Ir===r&&(Ir=null),Ir!==r?(Nn=Ga(),Nn!==r?(Jt=ne,Be=te(_e,bt,Nn),ne=Be):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)}else ve=ne,ne=r;else ve=ne,ne=r}return ne}function Ga(){var ne,Be,_e,bt,xt,jt,Ir;if(ne=ve,Be=ve,Vt++,_e=ve,bt=dt(),bt!==r?(xt=rr(),xt!==r?(t.charCodeAt(ve)===45?(jt=l,ve++):(jt=r,Vt===0&&it(f)),jt!==r?(Ir=ri(),Ir!==r?(bt=[bt,xt,jt,Ir],_e=bt):(ve=_e,_e=r)):(ve=_e,_e=r)):(ve=_e,_e=r)):(ve=_e,_e=r),Vt--,_e!==r?(ve=Be,Be=void 0):Be=r,Be!==r?(_e=et(),_e!==r?(bt=ti(),bt!==r?(xt=Yn(),xt!==r?(jt=qa(),jt!==r?(Jt=ne,Be=ie(xt),ne=Be):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r),ne===r&&(ne=ve,Be=dt(),Be!==r?(_e=ti(),_e!==r?(bt=VA(),bt!==r?(xt=qa(),xt!==r?(Jt=ne,Be=ie(bt),ne=Be):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r)):(ve=ne,ne=r),ne===r))if(ne=ve,Be=Kl(),Be!==r){if(_e=[],bt=et(),bt!==r)for(;bt!==r;)_e.push(bt),bt=et();else _e=r;_e!==r?(Jt=ne,BeLine truncated
`;if(typeof t=="number"||typeof t=="boolean")return`${t.toString()}
`;if(typeof t=="string")return`${rue(t)}
`;if(Array.isArray(t)){if(t.length===0)return`[]
`;let s=" ".repeat(e);return`
${t.map(n=>`${s}- ${fH(n,e+1,!1)}`).join("")}`}if(typeof t=="object"&&t){let[s,a]=t instanceof QT?[t.data,!1]:[t,!0],n=" ".repeat(e),l=Object.keys(s);a&&l.sort((h,A)=>{let m=tue.indexOf(h),w=tue.indexOf(A);return m===-1&&w===-1?h<A?-1:h>A?1:0:m!==-1&&w===-1?-1:m===-1&&w!==-1?1:m-w});let f=l.filter(h=>!iue(s[h])).map((h,A)=>{let m=s[h],w=rue(h),v=fH(m,e+1,!0),D=A>0||r?n:"",I=w.length>1024?`? ${w}
${D}:`:`${w}:`,R=v.startsWith(`
`)?v:` ${v}`;return`${D}${I}${R}`}).join(e===0?`
`:"")||`
`;return r?`
${f}`:`${f}`}throw new Error(`Unsupported value type (${t})`)}function Uc(t){try{let e=fH(t,0,!1);return e!==`
`?e:""}catch(e){throw e.location&&(e.message=e.message.replace(/(\.)?$/,` (line ${e.location.start.line}, column ${e.location.start.column})$1`)),e}}function ret(t){return t.endsWith(`
`)||(t+=`
`),(0,nue.parse)(t)}function iet(t){if(net.test(t))return ret(t);let e=Zle(t,{schema:Jle,json:!0});if(e==null)return{};if(typeof e!="object")throw new Error(`Expected an indexed object, got a ${typeof e} instead. Does your file follow Yaml's rules?`);if(Array.isArray(e))throw new Error("Expected an indexed object, got an array instead. Does your file follow Yaml's rules?");return e}function Fs(t){return iet(t)}var nue,tet,tue,QT,net,sue=tt(()=>{Xle();nue=st(eue()),tet=/^(?![-?:,\][{}#&*!|>'"%@` \t\r\n]).([ \t]*(?![,\][{}:# \t\r\n]).)*$/,tue=["__metadata","version","resolution","dependencies","peerDependencies","dependenciesMeta","peerDependenciesMeta","binaries"],QT=class{constructor(e){this.data=e}};Uc.PreserveOrdering=QT;net=/^(#.*(\r?\n))*?#\s+yarn\s+lockfile\s+v1\r?\n/i});var hS={};lr(hS,{parseResolution:()=>kT,parseShell:()=>DT,parseSyml:()=>Fs,stringifyArgument:()=>U6,stringifyArgumentSegment:()=>H6,stringifyArithmeticExpression:()=>xT,stringifyCommand:()=>M6,stringifyCommandChain:()=>hw,stringifyCommandChainThen:()=>_6,stringifyCommandLine:()=>PT,stringifyCommandLineThen:()=>L6,stringifyEnvSegment:()=>bT,stringifyRedirectArgument:()=>lS,stringifyResolution:()=>RT,stringifyShell:()=>fw,stringifyShellLine:()=>fw,stringifySyml:()=>Uc,stringifyValueArgument:()=>oy});var au=tt(()=>{nle();ale();sue()});var aue=H((Rqt,hH)=>{"use strict";var set=t=>{let e=!1,r=!1,s=!1;for(let a=0;a<t.length;a++){let n=t[a];e&&/[a-zA-Z]/.test(n)&&n.toUpperCase()===n?(t=t.slice(0,a)+"-"+t.slice(a),e=!1,s=r,r=!0,a++):r&&s&&/[a-zA-Z]/.test(n)&&n.toLowerCase()===n?(t=t.slice(0,a-1)+"-"+t.slice(a-1),s=r,r=!1,e=!0):(e=n.toLowerCase()===n&&n.toUpperCase()!==n,s=r,r=n.toUpperCase()===n&&n.toLowerCase()!==n)}return t},oue=(t,e)=>{if(!(typeof t=="string"||Array.isArray(t)))throw new TypeError("Expected the input to be `string | string[]`");e=Object.assign({pascalCase:!1},e);let r=a=>e.pascalCase?a.charAt(0).toUpperCase()+a.slice(1):a;return Array.isArray(t)?t=t.map(a=>a.trim()).filter(a=>a.length).join("-"):t=t.trim(),t.length===0?"":t.length===1?e.pascalCase?t.toUpperCase():t.toLowerCase():(t!==t.toLowerCase()&&(t=set(t)),t=t.replace(/^[_.\- ]+/,"").toLowerCase().replace(/[_.\- ]+(\w|$)/g,(a,n)=>n.toUpperCase()).replace(/\d+(\w|$)/g,a=>a.toUpperCase()),r(t))};hH.exports=oue;hH.exports.default=oue});var cue=H((Tqt,oet)=>{oet.exports=[{name:"Agola CI",constant:"AGOLA",env:"AGOLA_GIT_REF",pr:"AGOLA_PULL_REQUEST_ID"},{name:"Appcircle",constant:"APPCIRCLE",env:"AC_APPCIRCLE"},{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"TF_BUILD",pr:{BUILD_REASON:"PullRequest"}},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"Codefresh",constant:"CODEFRESH",env:"CF_BUILD_ID",pr:{any:["CF_PULL_REQUEST_NUMBER","CF_PULL_REQUEST_ID"]}},{name:"Codemagic",constant:"CODEMAGIC",env:"CM_BUILD_ID",pr:"CM_PULL_REQUEST"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"Earthly",constant:"EARTHLY",env:"EARTHLY_CI"},{name:"Expo Application Services",constant:"EAS",env:"EAS_BUILD"},{name:"Gerrit",constant:"GERRIT",env:"GERRIT_PROJECT"},{name:"Gitea Actions",constant:"GITEA_ACTIONS",env:"GITEA_ACTIONS"},{name:"GitHub Actions",constant:"GITHUB_ACTIONS",env:"GITHUB_ACTIONS",pr:{GITHUB_EVENT_NAME:"pull_request"}},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI",pr:"CI_MERGE_REQUEST_ID"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Google Cloud Build",constant:"GOOGLE_CLOUD_BUILD",env:"BUILDER_OUTPUT"},{name:"Harness CI",constant:"HARNESS",env:"HARNESS_BUILD_ID"},{name:"Heroku",constant:"HEROKU",env:{env:"NODE",includes:"/app/.heroku/node/bin/node"}},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"LayerCI",constant:"LAYERCI",env:"LAYERCI",pr:"LAYERCI_PULL_REQUEST"},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Nevercode",constant:"NEVERCODE",env:"NEVERCODE",pr:{env:"NEVERCODE_PULL_REQUEST",ne:"false"}},{name:"Prow",constant:"PROW",env:"PROW_JOB_ID"},{name:"ReleaseHub",constant:"RELEASEHUB",env:"RELEASE_BUILD_ID"},{name:"Re Line truncated
${this.candidates.map(({usage:a})=>`$ ${a}`).join(`
`)}`}else if(this.candidates.length===1){let[{usage:s}]=this.candidates;this.message=`Command not found; did you mean:
$ ${s}
${gH(e)}`}else this.message=`Command not found; did you mean one of:
${this.candidates.map(({usage:s},a)=>`${`${a}.`.padStart(4)} ${s}`).join(`
`)}
${gH(e)}`}},OT=class extends Error{constructor(e,r){super(),this.input=e,this.usages=r,this.clipanion={type:"none"},this.name="AmbiguousSyntaxError",this.message=`Cannot find which to pick amongst the following alternatives:
${this.usages.map((s,a)=>`${`${a}.`.padStart(4)} ${s}`).join(`
`)}
${gH(e)}`}},gH=t=>`While running ${t.filter(e=>e!==Si.EndOfInput&&e!==Si.EndOfPartialInput).map(e=>{let r=JSON.stringify(e);return e.match(/\s/)||e.length===0||r!==`"${e}"`?r:e}).join(" ")}`});function aet(t){let e=t.split(`
`),r=e.filter(a=>a.match(/\S/)),s=r.length>0?r.reduce((a,n)=>Math.min(a,n.length-n.trimStart().length),Number.MAX_VALUE):0;return e.map(a=>a.slice(s).trimRight()).join(`
`)}function da(t,{format:e,paragraphs:r}){return t=t.replace(/\r\n?/g,`
`),t=aet(t),t=t.replace(/^\n+|\n+$/g,""),t=t.replace(/^(\s*)-([^\n]*?)\n+/gm,`$1-$2
`),t=t.replace(/\n(\n)?\n*/g,(s,a)=>a||" "),r&&(t=t.split(/\n/).map(s=>{let a=s.match(/^\s*[*-][\t ]+(.*)/);if(!a)return s.match(/(.{1,80})(?: |$)/g).join(`
`);let n=s.length-s.trimStart().length;return a[1].match(new RegExp(`(.{1,${78-n}})(?: |$)`,"g")).map((l,f)=>" ".repeat(n)+(f===0?"- ":" ")+l).join(`
`)}).join(`
`)),t=t.replace(/(`+)((?:.|[\n])*?)\1/g,(s,a,n)=>e.code(a+n+a)),t=t.replace(/(\*\*)((?:.|[\n])*?)\1/g,(s,a,n)=>e.bold(a+n+a)),t?`${t}
`:""}var mH,hue,Aue,yH=tt(()=>{mH=Array(80).fill("\u2501");for(let t=0;t<=24;++t)mH[mH.length-t]=`\x1B[38;5;${232+t}m\u2501`;hue={header:t=>`\x1B[1m\u2501\u2501\u2501 ${t}${t.length<75?` ${mH.slice(t.length+5).join("")}`:":"}\x1B[0m`,bold:t=>`\x1B[1m${t}\x1B[22m`,error:t=>`\x1B[31m\x1B[1m${t}\x1B[22m\x1B[39m`,code:t=>`\x1B[36m${t}\x1B[39m`},Aue={header:t=>t,bold:t=>t,error:t=>t,code:t=>t}});function Xa(t){return{...t,[AS]:!0}}function Nh(t,e){return typeof t>"u"?[t,e]:typeof t=="object"&&t!==null&&!Array.isArray(t)?[void 0,t]:[t,e]}function _T(t,{mergeName:e=!1}={}){let r=t.match(/^([^:]+): (.*)$/m);if(!r)return"validation failed";let[,s,a]=r;return e&&(a=a[0].toLowerCase()+a.slice(1)),a=s!=="."||!e?`${s.replace(/^\.(\[|$)/,"$1")}: ${a}`:`: ${a}`,a}function pS(t,e){return e.length===1?new ht(`${t}${_T(e[0],{mergeName:!0})}`):new ht(`${t}:
${e.map(r=>`
- ${_T(r)}`).join("")}`)}function fy(t,e,r){if(typeof r>"u")return e;let s=[],a=[],n=f=>{let h=e;return e=f,n.bind(null,h)};if(!r(e,{errors:s,coercions:a,coercion:n}))throw pS(`Invalid value for ${t}`,s);for(let[,f]of a)f();return e}var AS,Pp=tt(()=>{LT();AS=Symbol("clipanion/isOption")});var ho={};lr(ho,{KeyRelationship:()=>Oh,TypeAssertionError:()=>D0,applyCascade:()=>gS,as:()=>Pet,assert:()=>vet,assertWithErrors:()=>bet,cascade:()=>P0,fn:()=>xet,hasAtLeastOneKey:()=>SH,hasExactLength:()=>yue,hasForbiddenKeys:()=>Ket,hasKeyRelationship:()=>yS,hasMaxLength:()=>Ret,hasMinLength:()=>ket,hasMutuallyExclusiveKeys:()=>zet,hasRequiredKeys:()=>Yet,hasUniqueItems:()=>Tet,isArray:()=>MT,isAtLeast:()=>BH,isAtMost:()=>Net,isBase64:()=>Get,isBoolean:()=>get,isDate:()=>yet,isDict:()=>wet,isEnum:()=>$s,isHexColor:()=>jet,isISO8601:()=>Het,isInExclusiveRange:()=>Let,isInInclusiveRange:()=>Oet,isInstanceOf:()=>Bet,isInteger:()=>vH,isJSON:()=>qet,isLiteral:()=>due,isLowerCase:()=>_et,isMap:()=>Iet,isNegative:()=>Qet,isNullable:()=>Wet,isNumber:()=>wH,isObject:()=>gue,isOneOf:()=>CH,isOptional:()=>Vet,isPartial:()=>Cet,isPayload:()=>met,isPositive:()=>Fet,isRecord:()=>HT,isSet:()=>Eet,isString:()=>_h,isTuple:()=>UT,isUUID4:()=>Uet,isUnknown:()=>IH,isUpperCase:()=>Met,makeTrait:()=>mue,makeValidator:()=>fn,matchesRegExp:()=>xp,softAssert:()=>Det});function bi(t){return t===null?"null":t===void 0?"undefined":t===""?"an empty string":typeof t=="symbol"?`<${t.toString()}>`:Array.isArray(t)?"an array":JSON.stringify(t)}function pw(t,e){if(t.length===0)return"nothing";if(t.length===1)return bi(t[0]);let r=t.slice(0,-1),s=t[t.length-1],a=t.length>2?`, ${e} `:` ${e} `;return`${r.map(n=>bi(n)).join(", ")}${a}${bi(s)}`}function b0(t,e){var r,s,a;return typeof e=="number"?`${(r=t?.p)!==null&&r!==void 0?r:"."}[${e}]`:cet.test(e)?`${(s=t?.p)!==null&&s!==void 0?s:""}.${e}`:`${(a=t?.p)!==null&&a!==void 0?a:"."}[${JSON.stringify(e)}]`}function EH(t,e,r){return t===1?e:r}function Lr({errors:t,p:e}={},r){return t?.push(`${e??"."}: ${r}`),!1}function pet(t,e){return r=>{t[e]=r}}function Lh(t,e){return r=>{let s=t[e];return t[e]=r,Lh(t,e).bind(null,s)}}function dS(t,e,r){let s=()=>(t(r()),a),a=()=>(t(e),s);return s}function IH(){return fn({test:(t,e)=>!0})}function due(t){return fn({test:(e,r)=>e!==t?Lr(r,`Expected ${bi(t)} (got ${bi(e)})`):!0})}function _h(){return fn({test:(t,e)=>typeof t!="string"?Lr(e,`Expected a string (got ${bi(t)})`):!0})}function $s(t){let e=Array.isArray(t)?t:Object.values(t),r=e.every(a=>typeof a=="string"||typeof a=="number"),s=new Set(e);return s.size===1?due([...s][0]):fn({test:(a,n)=>s.has(a)?!0:r?Lr(n,`Expected one of ${pw(e,"or")} (got ${bi(a)})`):Lr(n,`Expected a valid enumeration value (got ${bi(a)})`)})}function get(){return fn({test:(t,e)=>{var r;if(typeof t!="boolean"){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return Lr(e,"Unbound coercion result");let s=det.get(t);if(typeof s<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,s)]),!0}return Lr(e,`Expected a boolean (got ${bi(t)})`)}return!0}})}function wH(){return fn({test:(t,e)=>{var r;if(typeof t!="number"){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return Lr(e,"Unbound coercion result");let s;if(typeof t=="string"){let a;try{a=JSON.parse(t)}catch{}if(typeof a=="number")if(JSON.stringify(a)===t)s=a;else return Lr(e,`Received a number that can't be safely represented by the runtime (${t})`)}if(typeof s<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,s)]),!0}return Lr(e,`Expected a number (got ${bi(t)})`)}return!0}})}function met(t){return fn({test:(e,r)=>{var s;if(typeof r?.coercions>"u")return Lr(r,"The isPayload predicate can only be used with coercion enabled");if(typeof r.coercion>"u")return Lr(r,"Unbound coercion result");if(typeof e!="string")return Lr(r,`Expected a string (got ${bi(e)})`);let a;try{a=JSON.parse(e)}catch{return Lr(r,`Expected a JSON string (got ${bi(e)})`)}let n={value:a};return t(a,Object.assign(Object.assign({},r),{coercion:Lh(n,"value")}))?(r.coercions.push([(s=r.p)!==null&&s!==void 0?s:".",r.coercion.bind(null,n.value)]),!0):!1}})}function yet(){return fn({test:(t,e)=>{var r;if(!(t instanceof Date)){if(typeof e?.coercions<"u"){if(typeof e?.coercion>"u")return Lr(e,"Unbound coercion result");let s;if(typeof t=="string"&&pue.test(t))s=new Date(t);else{let a;if(typeof t=="string"){let n;try{n=JSON.parse(t)}catch{}typeof n=="number"&&(a=n)}else typeof t=="number"&&(a=t);if(typeof a<"u")if(Number.isSafeInteger(a)||!Number.isSafeInteger(a*1e3))s=new Date(a*1e3);else return Lr(e,`Received a timestamp that can't be safely represented by the runtime (${t})`)}if(typeof s<"u")return e.coercions.push([(r=e.p)!==null&&r!==void 0?r:".",e.coercion.bind(null,s)]),!0}return Lr(e,`Expected a date (got ${bi(t)})`)}return!0}})}function MT(t,{delimiter:e}={}){return fn({test:(r,s)=>{var a;let n=r;if(typeof r=="string"&&typeof e<"u"&&typeof s?.coercions<"u"){iLine truncated
`;for(let s of e)r+=`
- ${s}`}super(r)}};mS={missing:(t,e)=>t.has(e),undefined:(t,e,r)=>t.has(e)&&typeof r[e]<"u",nil:(t,e,r)=>t.has(e)&&r[e]!=null,falsy:(t,e,r)=>t.has(e)&&!!r[e]};(function(t){t.Forbids="Forbids",t.Requires="Requires"})(Oh||(Oh={}));Jet={[Oh.Forbids]:{expect:!1,message:"forbids using"},[Oh.Requires]:{expect:!0,message:"requires using"}}});var At,x0=tt(()=>{Pp();At=class{constructor(){this.help=!1}static Usage(e){return e}async catch(e){throw e}async validateAndExecute(){let r=this.constructor.schema;if(Array.isArray(r)){let{isDict:a,isUnknown:n,applyCascade:l}=await Promise.resolve().then(()=>(ga(),ho)),f=l(a(n()),r),h=[],A=[];if(!f(this,{errors:h,coercions:A}))throw pS("Invalid option schema",h);for(let[,w]of A)w()}else if(r!=null)throw new Error("Invalid command schema");let s=await this.execute();return typeof s<"u"?s:0}};At.isOption=AS;At.Default=[]});function Hc(t){dH&&console.log(t)}function Iue(){let t={nodes:[]};for(let e=0;e<Gn.CustomNode;++e)t.nodes.push(Sl());return t}function Zet(t){let e=Iue(),r=[],s=e.nodes.length;for(let a of t){r.push(s);for(let n=0;n<a.nodes.length;++n)Cue(n)||e.nodes.push(stt(a.nodes[n],s));s+=a.nodes.length-Gn.CustomNode+1}for(let a of r)dw(e,Gn.InitialNode,a);return e}function vf(t,e){return t.nodes.push(e),t.nodes.length-1}function Xet(t){let e=new Set,r=s=>{if(e.has(s))return;e.add(s);let a=t.nodes[s];for(let l of Object.values(a.statics))for(let{to:f}of l)r(f);for(let[,{to:l}]of a.dynamics)r(l);for(let{to:l}of a.shortcuts)r(l);let n=new Set(a.shortcuts.map(({to:l})=>l));for(;a.shortcuts.length>0;){let{to:l}=a.shortcuts.shift(),f=t.nodes[l];for(let[h,A]of Object.entries(f.statics)){let m=Object.prototype.hasOwnProperty.call(a.statics,h)?a.statics[h]:a.statics[h]=[];for(let w of A)m.some(({to:v})=>w.to===v)||m.push(w)}for(let[h,A]of f.dynamics)a.dynamics.some(([m,{to:w}])=>h===m&&A.to===w)||a.dynamics.push([h,A]);for(let h of f.shortcuts)n.has(h.to)||(a.shortcuts.push(h),n.add(h.to))}};r(Gn.InitialNode)}function $et(t,{prefix:e=""}={}){if(dH){Hc(`${e}Nodes are:`);for(let r=0;r<t.nodes.length;++r)Hc(`${e} ${r}: ${JSON.stringify(t.nodes[r])}`)}}function ett(t,e,r=!1){Hc(`Running a vm on ${JSON.stringify(e)}`);let s=[{node:Gn.InitialNode,state:{candidateUsage:null,requiredOptions:[],errorMessage:null,ignoreOptions:!1,options:[],path:[],positionals:[],remainder:null,selectedIndex:null,partial:!1,tokens:[]}}];$et(t,{prefix:" "});let a=[Si.StartOfInput,...e];for(let n=0;n<a.length;++n){let l=a[n],f=l===Si.EndOfInput||l===Si.EndOfPartialInput,h=n-1;Hc(` Processing ${JSON.stringify(l)}`);let A=[];for(let{node:m,state:w}of s){Hc(` Current node is ${m}`);let v=t.nodes[m];if(m===Gn.ErrorNode){A.push({node:m,state:w});continue}console.assert(v.shortcuts.length===0,"Shortcuts should have been eliminated by now");let D=Object.prototype.hasOwnProperty.call(v.statics,l);if(!r||n<a.length-1||D)if(D){let I=v.statics[l];for(let{to:R,reducer:N}of I)A.push({node:R,state:typeof N<"u"?jT(DH,N,w,l,h):w}),Hc(` Static transition to ${R} found`)}else Hc(" No static transition found");else{let I=!1;for(let R of Object.keys(v.statics))if(R.startsWith(l)){if(l===R)for(let{to:N,reducer:U}of v.statics[R])A.push({node:N,state:typeof U<"u"?jT(DH,U,w,l,h):w}),Hc(` Static transition to ${N} found`);else for(let{to:N}of v.statics[R])A.push({node:N,state:{...w,remainder:R.slice(l.length)}}),Hc(` Static transition to ${N} found (partial match)`);I=!0}I||Hc(" No partial static transition found")}if(!f)for(let[I,{to:R,reducer:N}]of v.dynamics)jT(ott,I,w,l,h)&&(A.push({node:R,state:typeof N<"u"?jT(DH,N,w,l,h):w}),Hc(` Dynamic transition to ${R} found (via ${I})`))}if(A.length===0&&f&&e.length===1)return[{node:Gn.InitialNode,state:Eue}];if(A.length===0)throw new Aw(e,s.filter(({node:m})=>m!==Gn.ErrorNode).map(({state:m})=>({usage:m.candidateUsage,reason:null})));if(A.every(({node:m})=>m===Gn.ErrorNode))throw new Aw(e,A.map(({state:m})=>({usage:m.candidateUsage,reason:m.errorMessage})));s=rtt(A)}if(s.length>0){Hc(" Results:");for(let n of s)Hc(` - ${n.node} -> ${JSON.stringify(n.state)}`)}else Hc(" No results");return s}function ttt(t,e,{endToken:r=Si.EndOfInput}={}){let s=ett(t,[...e,r]);return ntt(e,s.map(({state:a})=>a))}function rtt(t){let e=0;for(let{state:r}of t)r.path.length>e&&(e=r.path.length);return t.filter(({state:r})=>r.path.length===e)}function ntt(t,e){let r=e.filter(v=>v.selectedIndex!==null),s=r.filter(v=>!v.partial);if(s.length>0&&(r=s),r.length===0)throw new Error;let a=r.filter(v=>v.selectedIndex===uy||v.requiredOptions.every(D=>D.some(I=>v.options.find(R=>R.name===I))));if(a.length===0)throw new Aw(t,r.map(v=>({usage:v.candidateUsage,reason:null})));let n=0;for(let v of a)v.path.length>n&&(n=v.path.length);let l=a.filter(v=>v.path.length===n),f=v=>v.positionals.filter(({extra:D})=>!D).length+v.options.length,h=l.map(v=>({state:v,positionalCount:f(v)})),A=0;for(let{positionalCount:v}of h)v>A&&(A=v);let m=h.filter(({positionalCount:v})=>v===A).map(({state:v Line truncated
`),this.context.stdout.write(`
`);let r=0;for(let s of this.commands)this.context.stdout.write(this.cli.usage(this.contexts[s].commandClass,{prefix:`${r++}. `.padStart(5)}));this.context.stdout.write(`
`),this.context.stdout.write(`Run again with -h=<index> to see the longer details of any of those commands.
`)}}}});async function kue(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:s,resolvedContext:a}=Tue(t);return ec.from(r,e).runExit(s,a)}async function Rue(...t){let{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:s,resolvedContext:a}=Tue(t);return ec.from(r,e).run(s,a)}function Tue(t){let e,r,s,a;switch(typeof process<"u"&&typeof process.argv<"u"&&(s=process.argv.slice(2)),t.length){case 1:r=t[0];break;case 2:t[0]&&t[0].prototype instanceof At||Array.isArray(t[0])?(r=t[0],Array.isArray(t[1])?s=t[1]:a=t[1]):(e=t[0],r=t[1]);break;case 3:Array.isArray(t[2])?(e=t[0],r=t[1],s=t[2]):t[0]&&t[0].prototype instanceof At||Array.isArray(t[0])?(r=t[0],s=t[1],a=t[2]):(e=t[0],r=t[1],a=t[2]);break;default:e=t[0],r=t[1],s=t[2],a=t[3];break}if(typeof s>"u")throw new Error("The argv parameter must be provided when running Clipanion outside of a Node context");return{resolvedOptions:e,resolvedCommandClasses:r,resolvedArgv:s,resolvedContext:a}}function xue(t){return t()}var Pue,ec,Que=tt(()=>{NT();qT();yH();bue();x0();Due();Pue=Symbol("clipanion/errorCommand");ec=class t{constructor({binaryLabel:e,binaryName:r="...",binaryVersion:s,enableCapture:a=!1,enableColors:n}={}){this.registrations=new Map,this.builder=new GT({binaryName:r}),this.binaryLabel=e,this.binaryName=r,this.binaryVersion=s,this.enableCapture=a,this.enableColors=n}static from(e,r={}){let s=new t(r),a=Array.isArray(e)?e:[e];for(let n of a)s.register(n);return s}register(e){var r;let s=new Map,a=new e;for(let h in a){let A=a[h];typeof A=="object"&&A!==null&&A[At.isOption]&&s.set(h,A)}let n=this.builder.command(),l=n.cliIndex,f=(r=e.paths)!==null&&r!==void 0?r:a.paths;if(typeof f<"u")for(let h of f)n.addPath(h);this.registrations.set(e,{specs:s,builder:n,index:l});for(let[h,{definition:A}]of s.entries())A(n,h);n.setContext({commandClass:e})}process(e,r){let{input:s,context:a,partial:n}=typeof e=="object"&&Array.isArray(e)?{input:e,context:r}:e,{contexts:l,process:f}=this.builder.compile(),h=f(s,{partial:n}),A={...t.defaultContext,...a};switch(h.selectedIndex){case uy:{let m=WT.from(h,l);return m.context=A,m.tokens=h.tokens,m}default:{let{commandClass:m}=l[h.selectedIndex],w=this.registrations.get(m);if(typeof w>"u")throw new Error("Assertion failed: Expected the command class to have been registered.");let v=new m;v.context=A,v.tokens=h.tokens,v.path=h.path;try{for(let[D,{transformer:I}]of w.specs.entries())v[D]=I(w.builder,D,h,A);return v}catch(D){throw D[Pue]=v,D}}break}}async run(e,r){var s,a;let n,l={...t.defaultContext,...r},f=(s=this.enableColors)!==null&&s!==void 0?s:l.colorDepth>1;if(!Array.isArray(e))n=e;else try{n=this.process(e,l)}catch(m){return l.stdout.write(this.error(m,{colored:f})),1}if(n.help)return l.stdout.write(this.usage(n,{colored:f,detailed:!0})),0;n.context=l,n.cli={binaryLabel:this.binaryLabel,binaryName:this.binaryName,binaryVersion:this.binaryVersion,enableCapture:this.enableCapture,enableColors:this.enableColors,definitions:()=>this.definitions(),definition:m=>this.definition(m),error:(m,w)=>this.error(m,w),format:m=>this.format(m),process:(m,w)=>this.process(m,{...l,...w}),run:(m,w)=>this.run(m,{...l,...w}),usage:(m,w)=>this.usage(m,w)};let h=this.enableCapture&&(a=Sue(l))!==null&&a!==void 0?a:xue,A;try{A=await h(()=>n.validateAndExecute().catch(m=>n.catch(m).then(()=>0)))}catch(m){return l.stdout.write(this.error(m,{colored:f,command:n})),1}return A}async runExit(e,r){process.exitCode=await this.run(e,r)}definition(e,{colored:r=!1}={}){if(!e.usage)return null;let{usage:s}=this.getUsageByRegistration(e,{detailed:!1}),{usage:a,options:n}=this.getUsageByRegistration(e,{detailed:!0,inlineOptions:!1}),l=typeof e.usage.category<"u"?da(e.usage.category,{format:this.format(r),paragraphs:!1}):void 0,f=typeof e.usage.description<"u"?da(e.usage.description,{format:this.format(r),paragraphs:!1}):void 0,h=typeof e.usage.details<"u"?da(e.usage.details,{format:this.format(r),paragraphs:!0}):void 0,A=typeof e.usage.examples<"u"?e.usage.examples.map(([m,w])=>[da(m,{format:this.format(r),paragraphs:!1}),w.replace(/\$0/g,this.binaryName)]):void 0;return{path:s,usage:a,category:l,description:f,details:h,examples:A,options:n}}definitions({colored:e=!1}={}){let r=[];for(let s of this.registrations.keys()){let a=this.definition(s,{colored:e});a&&r.push(a)}return r}usage(e=null,{colored:r,detailed:s=!1,prefix:a="$ "}={}){var n;if(e===null){for(let h of this.registrations.keys()){let A=h.paths,m=typeof h.usage<"u";if(!A||A.length===0||A.length===1&&A[0].length===0||((n=A?.some(D=>D.length===0))!==null&&n!==void 0?n:!1))if(e){e=null;break}else e=h;else if(m){e=null;continue}}e&&(s=!0)}let l=e!==null&&e instanceof At?e.constructor:e,f="";if(l)if(s){let{description:h="",details:A="",examples:m=[]}=l.usage||{};h!==""&&(f+=da(h,{format:this.format(r),paragraphs:!1}).replace(/^./,D=>D.toUpperCase()),f+=`
`),(A!==""||m.length>0)&&(f+=`${this.format(r).header("Usage")}
`,f+=`
`);let{usage:w,options:v}=this.getUsageByRegistration(l,{inlineOptions:!1});if(f+=`${this.format(r).bold(a)}${w}
`,v.length>0){f+=`
`,f+=`${this.format(r).header("Options")}
`;let D=v.reduce((I,R)=>Math.max(I,R.definition.length),0);f+=`
`;for(let{definition:I,description:R}of v)f+=` ${this.format(r).bold(I.padEnd(D))} ${da(R,{format:this.format(r),paragraphs:!1})}`}if(A!==""&&(f+=`
`,f+=`${this.format(r).header("Details")}
`,f+=`
`,f+=da(A,{format:this.format(r),paragraphs:!0})),m.length>0){f+=`
`,f+=`${this.format(r).header("Examples")}
`;for(let[D,I]of m)f+=`
`,f+=da(D,{format:this.format(r),paragraphs:!1}),f+=`${I.replace(/^/m,` ${this.format(r).bold(a)}`).replace(/\$0/g,this.binaryName)}
`}}else{let{usage:h}=this.getUsageByRegistration(l);f+=`${this.format(r).bold(a)}${h}
`}else{let h=new Map;for(let[v,{index:D}]of this.registrations.entries()){if(typeof v.usage>"u")continue;let I=typeof v.usage.category<"u"?da(v.usage.category,{format:this.format(r),paragraphs:!1}):null,R=h.get(I);typeof R>"u"&&h.set(I,R=[]);let{usage:N}=this.getUsageByIndex(D);R.push({commandClass:v,usage:N})}let A=Array.from(h.keys()).sort((v,D)=>v===null?-1:D===null?1:v.localeCompare(D,"en",{usage:"sort",caseFirst:"upper"})),m=typeof this.binaryLabel<"u",w=typeof this.binaryVersion<"u";m||w?(m&&w?f+=`${this.format(r).header(`${this.binaryLabel} - ${this.binaryVersion}`)}
`:m?f+=`${this.format(r).header(`${this.binaryLabel}`)}
`:f+=`${this.format(r).header(`${this.binaryVersion}`)}
`,f+=` ${this.format(r).bold(a)}${this.binaryName} <command>
`):f+=`${this.format(r).bold(a)}${this.binaryName} <command>
`;for(let v of A){let D=h.get(v).slice().sort((R,N)=>R.usage.localeCompare(N.usage,"en",{usage:"sort",caseFirst:"upper"})),I=v!==null?v.trim():"General commands";f+=`
`,f+=`${this.format(r).header(`${I}`)}
`;for(let{commandClass:R,usage:N}of D){let U=R.usage.description||"undocumented";f+=`
`,f+=` ${this.format(r).bold(N)}
`,f+=` ${da(U,{format:this.format(r),paragraphs:!1})}`}}f+=`
`,f+=da("You can also print more details about any of these commands by calling them with the `-h,--help` flag right after the command name.",{format:this.format(r),paragraphs:!0})}return f}error(e,r){var s,{colored:a,command:n=(s=e[Pue])!==null&&s!==void 0?s:null}=r===void 0?{}:r;(!e||typeof e!="object"||!("stack"in e))&&(e=new Error(`Execution failed with a non-error rejection (rejected value: ${JSON.stringify(e)})`));let l="",f=e.name.replace(/([a-z])([A-Z])/g,"$1 $2");f==="Error"&&(f="Internal Error"),l+=`${this.format(a).error(f)}: ${e.message}
`;let h=e.clipanion;return typeof h<"u"?h.type==="usage"&&(l+=`
`,l+=this.usage(n)):e.stack&&(l+=`${e.stack.replace(/^.*\n/,"")}
`),l}format(e){var r;return((r=e??this.enableColors)!==null&&r!==void 0?r:t.defaultContext.colorDepth>1)?hue:Aue}getUsageByRegistration(e,r){let s=this.registrations.get(e);if(typeof s>"u")throw new Error("Assertion failed: Unregistered command");return this.getUsageByIndex(s.index,r)}getUsageByIndex(e,r){return this.builder.getBuilderByIndex(e).usage(r)}};ec.defaultContext={env:process.env,stdin:process.stdin,stdout:process.stdout,stderr:process.stderr,colorDepth:vue()}});var ES,Fue=tt(()=>{x0();ES=class extends At{async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.definitions(),null,2)}
`)}};ES.paths=[["--clipanion=definitions"]]});var IS,Nue=tt(()=>{x0();IS=class extends At{async execute(){this.context.stdout.write(this.cli.usage())}};IS.paths=[["-h"],["--help"]]});function YT(t={}){return Xa({definition(e,r){var s;e.addProxy({name:(s=t.name)!==null&&s!==void 0?s:r,required:t.required})},transformer(e,r,s){return s.positionals.map(({value:a})=>a)}})}var xH=tt(()=>{Pp()});var wS,Oue=tt(()=>{x0();xH();wS=class extends At{constructor(){super(...arguments),this.args=YT()}async execute(){this.context.stdout.write(`${JSON.stringify(this.cli.process(this.args).tokens,null,2)}
`)}};wS.paths=[["--clipanion=tokens"]]});var CS,Lue=tt(()=>{x0();CS=class extends At{async execute(){var e;this.context.stdout.write(`${(e=this.cli.binaryVersion)!==null&&e!==void 0?e:"<unknown>"}
`)}};CS.paths=[["-v"],["--version"]]});var kH={};lr(kH,{DefinitionsCommand:()=>ES,HelpCommand:()=>IS,TokensCommand:()=>wS,VersionCommand:()=>CS});var _ue=tt(()=>{Fue();Nue();Oue();Lue()});function Mue(t,e,r){let[s,a]=Nh(e,r??{}),{arity:n=1}=a,l=t.split(","),f=new Set(l);return Xa({definition(h){h.addOption({names:l,arity:n,hidden:a?.hidden,description:a?.description,required:a.required})},transformer(h,A,m){let w,v=typeof s<"u"?[...s]:void 0;for(let{name:D,value:I}of m.options)f.has(D)&&(w=D,v=v??[],v.push(I));return typeof v<"u"?fy(w??A,v,a.validator):v}})}var Uue=tt(()=>{Pp()});function Hue(t,e,r){let[s,a]=Nh(e,r??{}),n=t.split(","),l=new Set(n);return Xa({definition(f){f.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(f,h,A){let m=s;for(let{name:w,value:v}of A.options)l.has(w)&&(m=v);return m}})}var jue=tt(()=>{Pp()});function Gue(t,e,r){let[s,a]=Nh(e,r??{}),n=t.split(","),l=new Set(n);return Xa({definition(f){f.addOption({names:n,allowBinding:!1,arity:0,hidden:a.hidden,description:a.description,required:a.required})},transformer(f,h,A){let m=s;for(let{name:w,value:v}of A.options)l.has(w)&&(m??(m=0),v?m+=1:m=0);return m}})}var que=tt(()=>{Pp()});function Vue(t={}){return Xa({definition(e,r){var s;e.addRest({name:(s=t.name)!==null&&s!==void 0?s:r,required:t.required})},transformer(e,r,s){let a=l=>{let f=s.positionals[l];return f.extra===bl||f.extra===!1&&l<e.arity.leading.length},n=0;for(;n<s.positionals.length&&a(n);)n+=1;return s.positionals.splice(0,n).map(({value:l})=>l)}})}var Wue=tt(()=>{qT();Pp()});function att(t,e,r){let[s,a]=Nh(e,r??{}),{arity:n=1}=a,l=t.split(","),f=new Set(l);return Xa({definition(h){h.addOption({names:l,arity:a.tolerateBoolean?0:n,hidden:a.hidden,description:a.description,required:a.required})},transformer(h,A,m,w){let v,D=s;typeof a.env<"u"&&w.env[a.env]&&(v=a.env,D=w.env[a.env]);for(let{name:I,value:R}of m.options)f.has(I)&&(v=I,D=R);return typeof D=="string"?fy(v??A,D,a.validator):D}})}function ctt(t={}){let{required:e=!0}=t;return Xa({definition(r,s){var a;r.addPositional({name:(a=t.name)!==null&&a!==void 0?a:s,required:t.required})},transformer(r,s,a){var n;for(let l=0;l<a.positionals.length;++l){if(a.positionals[l].extra===bl||e&&a.positionals[l].extra===!0||!e&&a.positionals[l].extra===!1)continue;let[f]=a.positionals.splice(l,1);return fy((n=t.name)!==null&&n!==void 0?n:s,f.value,t.validator)}}})}function Yue(t,...e){return typeof t=="string"?att(t,...e):ctt(t)}var Kue=tt(()=>{qT();Pp()});var ye={};lr(ye,{Array:()=>Mue,Boolean:()=>Hue,Counter:()=>Gue,Proxy:()=>YT,Rest:()=>Vue,String:()=>Yue,applyValidator:()=>fy,cleanValidationError:()=>_T,formatError:()=>pS,isOptionSymbol:()=>AS,makeCommandOption:()=>Xa,rerouteArguments:()=>Nh});var zue=tt(()=>{Pp();xH();Uue();jue();que();Wue();Kue()});var BS={};lr(BS,{Builtins:()=>kH,Cli:()=>ec,Command:()=>At,Option:()=>ye,UsageError:()=>ht,formatMarkdownish:()=>da,run:()=>Rue,runExit:()=>kue});var sr=tt(()=>{LT();yH();x0();Que();_ue();zue()});var Jue=H((M7t,ltt)=>{ltt.exports={name:"dotenv",version:"16.3.1",description:"Loads environment variables from .env file",main:"lib/main.js",types:"lib/main.d.ts",exports:{".":{types:"./lib/main.d.ts",require:"./lib/main.js",default:"./lib/main.js"},"./config":"./config.js","./config.js":"./config.js","./lib/env-options":"./lib/env-options.js","./lib/env-options.js":"./lib/env-options.js","./lib/cli-options":"./lib/cli-options.js","./lib/cli-options.js":"./lib/cli-options.js","./package.json":"./package.json"},scripts:{"dts-check":"tsc --project tests/types/tsconfig.json",lint:"standard","lint-readme":"standard-markdown",pretest:"npm run lint && npm run dts-check",test:"tap tests/*.js --100 -Rspec",prerelease:"npm test",release:"standard-version"},repository:{type:"git",url:"git://github.com/motdotla/dotenv.git"},funding:"https://github.com/motdotla/dotenv?sponsor=1",keywords:["dotenv","env",".env","environment","variables","config","settings"],readmeFilename:"README.md",license:"BSD-2-Clause",devDependencies:{"@definitelytyped/dtslint":"^0.0.133","@types/node":"^18.11.3",decache:"^4.6.1",sinon:"^14.0.1",standard:"^17.0.0","standard-markdown":"^7.1.0","standard-version":"^9.5.0",tap:"^16.3.0",tar:"^6.1.11",typescript:"^4.8.4"},engines:{node:">=12"},browser:{fs:!1}}});var efe=H((U7t,kp)=>{var Zue=Ae("fs"),TH=Ae("path"),utt=Ae("os"),ftt=Ae("crypto"),htt=Jue(),QH=htt.version,Att=/(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;function ptt(t){let e={},r=t.toString();r=r.replace(/\r\n?/mg,`
`);let s;for(;(s=Att.exec(r))!=null;){let a=s[1],n=s[2]||"";n=n.trim();let l=n[0];n=n.replace(/^(['"`])([\s\S]*)\1$/mg,"$2"),l==='"'&&(n=n.replace(/\\n/g,`
`),n=n.replace(/\\r/g,"\r")),e[a]=n}return e}function dtt(t){let e=$ue(t),r=po.configDotenv({path:e});if(!r.parsed)throw new Error(`MISSING_DATA: Cannot parse ${e} for an unknown reason`);let s=Xue(t).split(","),a=s.length,n;for(let l=0;l<a;l++)try{let f=s[l].trim(),h=ytt(r,f);n=po.decrypt(h.ciphertext,h.key);break}catch(f){if(l+1>=a)throw f}return po.parse(n)}function gtt(t){console.log(`[dotenv@${QH}][INFO] ${t}`)}function mtt(t){console.log(`[dotenv@${QH}][WARN] ${t}`)}function RH(t){console.log(`[dotenv@${QH}][DEBUG] ${t}`)}function Xue(t){return t&&t.DOTENV_KEY&&t.DOTENV_KEY.length>0?t.DOTENV_KEY:process.env.DOTENV_KEY&&process.env.DOTENV_KEY.length>0?process.env.DOTENV_KEY:""}function ytt(t,e){let r;try{r=new URL(e)}catch(f){throw f.code==="ERR_INVALID_URL"?new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:[email protected]/vault/.env.vault?environment=development"):f}let s=r.password;if(!s)throw new Error("INVALID_DOTENV_KEY: Missing key part");let a=r.searchParams.get("environment");if(!a)throw new Error("INVALID_DOTENV_KEY: Missing environment part");let n=`DOTENV_VAULT_${a.toUpperCase()}`,l=t.parsed[n];if(!l)throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${n} in your .env.vault file.`);return{ciphertext:l,key:s}}function $ue(t){let e=TH.resolve(process.cwd(),".env");return t&&t.path&&t.path.length>0&&(e=t.path),e.endsWith(".vault")?e:`${e}.vault`}function Ett(t){return t[0]==="~"?TH.join(utt.homedir(),t.slice(1)):t}function Itt(t){gtt("Loading env from encrypted .env.vault");let e=po._parseVault(t),r=process.env;return t&&t.processEnv!=null&&(r=t.processEnv),po.populate(r,e,t),{parsed:e}}function wtt(t){let e=TH.resolve(process.cwd(),".env"),r="utf8",s=!!(t&&t.debug);t&&(t.path!=null&&(e=Ett(t.path)),t.encoding!=null&&(r=t.encoding));try{let a=po.parse(Zue.readFileSync(e,{encoding:r})),n=process.env;return t&&t.processEnv!=null&&(n=t.processEnv),po.populate(n,a,t),{parsed:a}}catch(a){return s&&RH(`Failed to load ${e} ${a.message}`),{error:a}}}function Ctt(t){let e=$ue(t);return Xue(t).length===0?po.configDotenv(t):Zue.existsSync(e)?po._configVault(t):(mtt(`You set DOTENV_KEY but you are missing a .env.vault file at ${e}. Did you forget to build it?`),po.configDotenv(t))}function Btt(t,e){let r=Buffer.from(e.slice(-64),"hex"),s=Buffer.from(t,"base64"),a=s.slice(0,12),n=s.slice(-16);s=s.slice(12,-16);try{let l=ftt.createDecipheriv("aes-256-gcm",r,a);return l.setAuthTag(n),`${l.update(s)}${l.final()}`}catch(l){let f=l instanceof RangeError,h=l.message==="Invalid key length",A=l.message==="Unsupported state or unable to authenticate data";if(f||h){let m="INVALID_DOTENV_KEY: It must be 64 characters long (or more)";throw new Error(m)}else if(A){let m="DECRYPTION_FAILED: Please check your DOTENV_KEY";throw new Error(m)}else throw console.error("Error: ",l.code),console.error("Error: ",l.message),l}}function vtt(t,e,r={}){let s=!!(r&&r.debug),a=!!(r&&r.override);if(typeof e!="object")throw new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");for(let n of Object.keys(e))Object.prototype.hasOwnProperty.call(t,n)?(a===!0&&(t[n]=e[n]),s&&RH(a===!0?`"${n}" is already defined and WAS overwritten`:`"${n}" is already defined and was NOT overwritten`)):t[n]=e[n]}var po={configDotenv:wtt,_configVault:Itt,_parseVault:dtt,config:Ctt,decrypt:Btt,parse:ptt,populate:vtt};kp.exports.configDotenv=po.configDotenv;kp.exports._configVault=po._configVault;kp.exports._parseVault=po._parseVault;kp.exports.config=po.config;kp.exports.decrypt=po.decrypt;kp.exports.parse=po.parse;kp.exports.populate=po.populate;kp.exports=po});var rfe=H((H7t,tfe)=>{"use strict";tfe.exports=(t,...e)=>new Promise(r=>{r(t(...e))})});var hy=H((j7t,FH)=>{"use strict";var Stt=rfe(),nfe=t=>{if(t<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let e=[],r=0,s=()=>{r--,e.length>0&&e.shift()()},a=(f,h,...A)=>{r++;let m=Stt(f,...A);h(m),m.then(s,s)},n=(f,h,...A)=>{r<t?a(f,h,...A):e.push(a.bind(null,f,h,...A))},l=(f,...h)=>new Promise(A=>n(f,A,...h));return Object.defineProperties(l,{activeCount:{get:()=>r},pendingCount:{get:()=>e.length}}),l};FH.exports=nfe;FH.exports.default=nfe});function Mh(t){return`YN${t.toString(10).padStart(4,"0")}`}function KT(t){let e=Number(t.slice(2));if(typeof Tr[e]>"u")throw new Error(`Unknown message name: "${t}"`);return e}var Tr,zT=tt(()=>{Tr=(Ge=>(Ge[Ge.UNNAMED=0]="UNNAMED",Ge[Ge.EXCEPTION=1]="EXCEPTION",Ge[Ge.MISSING_PEER_DEPENDENCY=2]="MISSING_PEER_DEPENDENCY",Ge[Ge.CYCLIC_DEPENDENCIES=3]="CYCLIC_DEPENDENCIES",Ge[Ge.DISABLED_BUILD_SCRIPTS=4]="DISABLED_BUILD_SCRIPTS",Ge[Ge.BUILD_DISABLED=5]="BUILD_DISABLED",Ge[Ge.SOFT_LINK_BUILD=6]="SOFT_LINK_BUILD",Ge[Ge.MUST_BUILD=7]="MUST_BUILD",Ge[Ge.MUST_REBUILD=8]="MUST_REBUILD",Ge[Ge.BUILD_FAILED=9]="BUILD_FAILED",Ge[Ge.RESOLVER_NOT_FOUND=10]="RESOLVER_NOT_FOUND",Ge[Ge.FETCHER_NOT_FOUND=11]="FETCHER_NOT_FOUND",Ge[Ge.LINKER_NOT_FOUND=12]="LINKER_NOT_FO Line truncated
`,"\r","(",")","!","|","&","^"],!0,!1),ae=function(re){return e.queryPattern.test(re)},ge=function(re){return e.checkFn(re)},de=Qe("whitespace"),xe=/^[ \t\n\r]/,we=Fe([" "," ",`
`,"\r"],!1,!1),d=0,be=0,Ce=[{line:1,column:1}],Ee=0,he=[],$=0,De;if("startRule"in e){if(!(e.startRule in s))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');a=s[e.startRule]}function Te(){return t.substring(be,d)}function ot(){return Me(be,d)}function j(re,ce){throw ce=ce!==void 0?ce:Me(be,d),P([Qe(re)],t.substring(be,d),ce)}function rt(re,ce){throw ce=ce!==void 0?ce:Me(be,d),C(re,ce)}function Ne(re,ce){return{type:"literal",text:re,ignoreCase:ce}}function Fe(re,ce,ke){return{type:"class",parts:re,inverted:ce,ignoreCase:ke}}function Pe(){return{type:"any"}}function He(){return{type:"end"}}function Qe(re){return{type:"other",description:re}}function ft(re){var ce=Ce[re],ke;if(ce)return ce;for(ke=re-1;!Ce[ke];)ke--;for(ce=Ce[ke],ce={line:ce.line,column:ce.column};ke<re;)t.charCodeAt(ke)===10?(ce.line++,ce.column=1):ce.column++,ke++;return Ce[re]=ce,ce}function Me(re,ce){var ke=ft(re),Le=ft(ce);return{start:{offset:re,line:ke.line,column:ke.column},end:{offset:ce,line:Le.line,column:Le.column}}}function x(re){d<Ee||(d>Ee&&(Ee=d,he=[]),he.push(re))}function C(re,ce){return new Ay(re,null,null,ce)}function P(re,ce,ke){return new Ay(Ay.buildMessage(re,ce),re,ce,ke)}function E(){var re,ce,ke,Le,pt,St,er,ur;if(re=d,ce=F(),ce!==r){for(ke=[],Le=d,pt=X(),pt!==r?(t.charCodeAt(d)===124?(St=n,d++):(St=r,$===0&&x(l)),St===r&&(t.charCodeAt(d)===38?(St=f,d++):(St=r,$===0&&x(h)),St===r&&(t.charCodeAt(d)===94?(St=A,d++):(St=r,$===0&&x(m)))),St!==r?(er=X(),er!==r?(ur=F(),ur!==r?(pt=[pt,St,er,ur],Le=pt):(d=Le,Le=r)):(d=Le,Le=r)):(d=Le,Le=r)):(d=Le,Le=r);Le!==r;)ke.push(Le),Le=d,pt=X(),pt!==r?(t.charCodeAt(d)===124?(St=n,d++):(St=r,$===0&&x(l)),St===r&&(t.charCodeAt(d)===38?(St=f,d++):(St=r,$===0&&x(h)),St===r&&(t.charCodeAt(d)===94?(St=A,d++):(St=r,$===0&&x(m)))),St!==r?(er=X(),er!==r?(ur=F(),ur!==r?(pt=[pt,St,er,ur],Le=pt):(d=Le,Le=r)):(d=Le,Le=r)):(d=Le,Le=r)):(d=Le,Le=r);ke!==r?(be=re,ce=w(ce,ke),re=ce):(d=re,re=r)}else d=re,re=r;return re}function F(){var re,ce,ke,Le,pt,St;return re=d,t.charCodeAt(d)===33?(ce=v,d++):(ce=r,$===0&&x(D)),ce!==r?(ke=F(),ke!==r?(be=re,ce=I(ke),re=ce):(d=re,re=r)):(d=re,re=r),re===r&&(re=d,t.charCodeAt(d)===40?(ce=R,d++):(ce=r,$===0&&x(N)),ce!==r?(ke=X(),ke!==r?(Le=E(),Le!==r?(pt=X(),pt!==r?(t.charCodeAt(d)===41?(St=U,d++):(St=r,$===0&&x(V)),St!==r?(be=re,ce=ee(Le),re=ce):(d=re,re=r)):(d=re,re=r)):(d=re,re=r)):(d=re,re=r)):(d=re,re=r),re===r&&(re=Z())),re}function Z(){var re,ce,ke,Le,pt;if(re=d,ce=X(),ce!==r){if(ke=d,Le=[],te.test(t.charAt(d))?(pt=t.charAt(d),d++):(pt=r,$===0&&x(ie)),pt!==r)for(;pt!==r;)Le.push(pt),te.test(t.charAt(d))?(pt=t.charAt(d),d++):(pt=r,$===0&&x(ie));else Le=r;Le!==r?ke=t.substring(ke,d):ke=Le,ke!==r?(be=d,Le=ae(ke),Le?Le=void 0:Le=r,Le!==r?(be=re,ce=ge(ke),re=ce):(d=re,re=r)):(d=re,re=r)}else d=re,re=r;return re}function X(){var re,ce;for($++,re=[],xe.test(t.charAt(d))?(ce=t.charAt(d),d++):(ce=r,$===0&&x(we));ce!==r;)re.push(ce),xe.test(t.charAt(d))?(ce=t.charAt(d),d++):(ce=r,$===0&&x(we));return $--,re===r&&(ce=r,$===0&&x(de)),re}if(De=a(),De!==r&&d===t.length)return De;throw De!==r&&d<t.length&&x(He()),P(he,Ee<t.length?t.charAt(Ee):null,Ee<t.length?Me(Ee,Ee+1):Me(Ee,Ee))}Khe.exports={SyntaxError:Ay,parse:Fit}});var Jhe=H(cQ=>{var{parse:Nit}=zhe();cQ.makeParser=(t=/[a-z]+/)=>(e,r)=>Nit(e,{queryPattern:t,checkFn:r});cQ.parse=cQ.makeParser()});var Xhe=H((LVt,Zhe)=>{"use strict";Zhe.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodLine truncated
`:`
`)+r,a=s+1,s=t.indexOf(`
`,a)}while(s!==-1);return n+=t.substr(a),n};dAe.exports={stringReplaceAll:Kit,stringEncaseCRLFWithFirstIndex:zit}});var wAe=H((VVt,IAe)=>{"use strict";var Jit=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,mAe=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,Zit=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,Xit=/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi,$it=new Map([["n",`
`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function EAe(t){let e=t[0]==="u",r=t[1]==="{";return e&&!r&&t.length===5||t[0]==="x"&&t.length===3?String.fromCharCode(parseInt(t.slice(1),16)):e&&r?String.fromCodePoint(parseInt(t.slice(2,-1),16)):$it.get(t)||t}function est(t,e){let r=[],s=e.trim().split(/\s*,\s*/g),a;for(let n of s){let l=Number(n);if(!Number.isNaN(l))r.push(l);else if(a=n.match(Zit))r.push(a[2].replace(Xit,(f,h,A)=>h?EAe(h):A));else throw new Error(`Invalid Chalk template style argument: ${n} (in style '${t}')`)}return r}function tst(t){mAe.lastIndex=0;let e=[],r;for(;(r=mAe.exec(t))!==null;){let s=r[1];if(r[2]){let a=est(s,r[2]);e.push([s].concat(a))}else e.push([s])}return e}function yAe(t,e){let r={};for(let a of e)for(let n of a.styles)r[n[0]]=a.inverse?null:n.slice(1);let s=t;for(let[a,n]of Object.entries(r))if(Array.isArray(n)){if(!(a in s))throw new Error(`Unknown Chalk style: ${a}`);s=n.length>0?s[a](...n):s[a]}return s}IAe.exports=(t,e)=>{let r=[],s=[],a=[];if(e.replace(Jit,(n,l,f,h,A,m)=>{if(l)a.push(EAe(l));else if(h){let w=a.join("");a=[],s.push(r.length===0?w:yAe(t,r)(w)),r.push({inverse:f,styles:tst(h)})}else if(A){if(r.length===0)throw new Error("Found extraneous } in Chalk template literal");s.push(yAe(t,r)(a.join(""))),a=[],r.pop()}else a.push(m)}),s.push(a.join("")),r.length>0){let n=`Chalk template literal is missing ${r.length} closing bracket${r.length===1?"":"s"} (\`}\`)`;throw new Error(n)}return s.join("")}});var Cw=H((WVt,DAe)=>{"use strict";var kS=fQ(),{stdout:a5,stderr:c5}=pAe(),{stringReplaceAll:rst,stringEncaseCRLFWithFirstIndex:nst}=gAe(),{isArray:hQ}=Array,BAe=["ansi","ansi","ansi256","ansi16m"],ww=Object.create(null),ist=(t,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let r=a5?a5.level:0;t.level=e.level===void 0?r:e.level},l5=class{constructor(e){return vAe(e)}},vAe=t=>{let e={};return ist(e,t),e.template=(...r)=>bAe(e.template,...r),Object.setPrototypeOf(e,AQ.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},e.template.Instance=l5,e.template};function AQ(t){return vAe(t)}for(let[t,e]of Object.entries(kS))ww[t]={get(){let r=pQ(this,u5(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,t,{value:r}),r}};ww.visible={get(){let t=pQ(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:t}),t}};var SAe=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let t of SAe)ww[t]={get(){let{level:e}=this;return function(...r){let s=u5(kS.color[BAe[e]][t](...r),kS.color.close,this._styler);return pQ(this,s,this._isEmpty)}}};for(let t of SAe){let e="bg"+t[0].toUpperCase()+t.slice(1);ww[e]={get(){let{level:r}=this;return function(...s){let a=u5(kS.bgColor[BAe[r]][t](...s),kS.bgColor.close,this._styler);return pQ(this,a,this._isEmpty)}}}}var sst=Object.defineProperties(()=>{},{...ww,level:{enumerable:!0,get(){return this._generator.level},set(t){this._generator.level=t}}}),u5=(t,e,r)=>{let s,a;return r===void 0?(s=t,a=e):(s=r.openAll+t,a=e+r.closeAll),{open:t,close:e,openAll:s,closeAll:a,parent:r}},pQ=(t,e,r)=>{let s=(...a)=>hQ(a[0])&&hQ(a[0].raw)?CAe(s,bAe(s,...a)):CAe(s,a.length===1?""+a[0]:a.join(" "));return Object.setPrototypeOf(s,sst),s._generator=t,s._styler=e,s._isEmpty=r,s},CAe=(t,e)=>{if(t.level<=0||!e)return t._isEmpty?"":e;let r=t._styler;if(r===void 0)return e;let{openAll:s,closeAll:a}=r;if(e.indexOf("\x1B")!==-1)for(;r!==void 0;)e=rst(e,r.close,r.open),r=r.parent;let n=e.indexOf(`
`);return n!==-1&&(e=nst(e,a,s,n)),s+e+a},o5,bAe=(t,...e)=>{let[r]=e;if(!hQ(r)||!hQ(r.raw))return e.join(" ");let s=e.slice(1),a=[r.raw[0]];for(let n=1;n<r.length;n++)a.push(String(s[n-1]).replace(/[{}\\]/g,"\\$&"),String(r.raw[n]));return o5===void 0&&(o5=wAe()),o5(t,a.join(""))};Object.defineProperties(AQ.prototype,ww);var dQ=AQ();dQ.supportsColor=a5;dQ.stderr=AQ({level:c5?c5.level:0});dQ.stderr.supportsColor=c5;DAe.exports=dQ});var gQ=H(fu=>{"use strict";fu.isInteger=t=>typeof t=="number"?Number.isInteger(t):typeof t=="string"&&t.trim()!==""?Number.isInteger(Number(t)):!1;fu.find=(t,e)=>t.nodes.find(r=>r.type===e);fu.exceedsLimit=(t,e,r=1,s)=>s===!1||!fu.isInteger(t)||!fu.isInteger(e)?!1:(Number(e)-Number(t))/Number(r)>=s;fu.escapeNode=(t,e=0,r)=>{let s=t.nodes[e];s&&(r&&s.type===r||s.type==="open"||s.type==="close")&&s.escaped!==!0&&(s.value="\\"+s.value,s.escaped=!0)};fu.encloseBrace=t=>t.type!=="brace"||t.commas>>0+t.ranges>>0?!1:(t.invalid=!0,!0);fu.isInvalidBrace=t=>t.type!=="brace"?!1:t.invalid===!0||t.dollar?!0:!(t.commas>>0+t.ranges>>0)||t.open!==!0||t.close!==!0?(t.invalid=!0,!0):!1;fu.isOpenOrClose=t=>t.type==="open"||t.type==="close"?!0:t.open===!0||t.close===!0;fu.reduce=t=>t.reduce((e,r)=>(r.type==="text"&&e.push(r.value),r.type==="range"&&(r.type="text"),e),[]);fu.flatten=(...t)=>{let e=[],r=s=>{for(let a=0;a<s.length;a++){let n=s[a];Array.isArray(n)?r(n,e):n!==void 0&&e.push(n)}return e};return r(t),e}});var mQ=H((KVt,xAe)=>{"use strict";var PAe=gQ();xAe.exports=(t,e={})=>{let r=(s,a={})=>{let n=e.escapeInvalid&&PAe.isInvalidBrace(a),l=s.invalid===!0&&e.escapeInvalid===!0,f="";if(s.value)return(n||l)&&PAe.isOpenOrClose(s)?"\\"+s.value:s.value;if(s.value)return s.value;if(s.nodes)for(let h of s.nodes)f+=r(h);return f};return r(t)}});var RAe=H((zVt,kAe)=>{"use strict";kAe.exports=function(t){return typeof t=="number"?t-t===0:typeof t=="string"&&t.trim()!==""?Number.isFinite?Number.isFinite(+t):isFinite(+t):!1}});var UAe=H((JVt,MAe)=>{"use strict";var TAe=RAe(),py=(t,e,r)=>{if(TAe(t)===!1)throw new TypeError("toRegexRange: expected the first argument to be a number");if(e===void 0||t===e)return String(t);if(TAe(e)===!1)throw new TypeError("toRegexRange: expected the second argument to be a number.");let s={relaxZeros:!0,...r};typeof s.strictZeros=="boolean"&&(s.relaxZeros=s.strictZeros===!1);let a=String(s.relaxZeros),n=String(s.shorthand),l=String(s.capture),f=String(s.wrap),h=t+":"+e+"="+a+n+l+f;if(py.cache.hasOwnProperty(h))return py.cache[h].result;let A=Math.min(t,e),m=Math.max(t,e);if(Math.abs(A-m)===1){let R=t+"|"+e;return s.capture?`(${R})`:s.wrap===!1?R:`(?:${R})`}let w=_Ae(t)||_Ae(e),v={min:t,max:e,a:A,b:m},D=[],I=[];if(w&&(v.isPadded=w,v.maxLen=String(v.max).length),A<0){let R=m<0?Math.abs(m):1;I=QAe(R,Math.abs(A),v,s),A=v.a=0}return m>=0&&(D=QAe(A,m,v,s)),v.negatives=I,v.positives=D,v.result=ost(I,D,s),s.capture===!0?v.result=`(${v.result})`:s.wrap!==!1&&D.length+I.length>1&&(v.result=`(?:${v.result})`),py.cache[h]=v,v.result};function ost(t,e,r){let s=f5(t,e,"-",!1,r)||[],a=f5(e,t,"",!1,r)||[],n=f5(t,e,"-?",!0,r)||[];return s.concat(n).concat(a).join("|")}function ast(t,e){let r=1,s=1,a=NAe(t,r),n=new Set([e]);for(;t<=a&&a<=e;)n.add(a),r+=1,a=NAe(t,r);for(a=OAe(e+1,s)-1;t<a&&a<=e;)n.add(a),s+=1,a=OAe(e+1,s)-1;return n=[...n],n.sort(ust),n}function cst(t,e,r){if(t===e)return{pattern:t,count:[],digits:0};let s=lst(t,e),a=s.length,n="",l=0;for(let f=0;f<a;f++){let[h,A]=s[f];h===A?n+=h:h!=="0"||A!=="9"?n+=fst(h,A,r):l++}return l&&(n+=r.shorthand===!0?"\\d":"[0-9]"),{pattern:n,count:[l],digits:a}}function QAe(t,e,r,s){let a=ast(t,e),n=[],l=t,f;for(let h=0;h<a.length;h++){let A=a[h],m=cst(String(l),String(A),s),w="";if(!r.isPadded&&f&&f.pattern===m.pattern){f.count.length>1&&f.count.pop(),f.count.push(m.count[0]),f.string=f.pattern+LAe(f.count),l=A+1;continue}r.isPadded&&(w=hst(A,r,s)),m.string=w+m.pattern+LAe(m.count),n.push(m),l=A+1,f=m}return n}function f5(t,e,r,s,a){let n=[];for(let l of t){let{string:f}=l;!s&&!FAe(e,"string",f)&&n.push(r+f),s&&FAe(e,"string",f)&&n.push(r+f)}return n}function lst(t,e){let r=[];for(let s=0;s<t.length;s++)r.push([t[s],e[s]]);return r}function ust(t,e){return t>e?1:e>t?-1:0}function FAe(t,e,r){return t.some(s=>s[e]===r)}function NAe(t,e){return Number(String(t).slice(0,-e)+"9".repeat(e))}function OAe(t,e){return t-t%Math.pow(10,e)}function LAe(t){let[e=0,r=""]=t;return r||e>1?`{${e+(r?","+r:"")}}`:""}function fst(t,e,r){return`[${t}${e-t===1?"":"-"}${e}]`}function _Ae(t){return/^-?(0+)\d/.test(t)}function hst(t,e,r){if(!e.isPadded)return t;let s=Math.abs(e.maxLen-String(t).length),a=r.relaxZeros!==!1;switch(s){case 0:return"";case 1:return a?"0?":"0";case 2:return a?"0{0,2}":"00";default:return a?`0{0,${s}}`:`0{${s}}`}}py.cache={};py.clearCache=()=>py.cache={};MAe.exports=py});var p5=H((ZVt,KAe)=>{"use strict";var Ast=Ae("util"),GAe=UAe(),HAe=t=>t!==null&&typeof t=="object"&&!Array.isArray(t),pst=t=>e=>t===!0?Number(e):String(e),h5=t=>typeof t=="numb Line truncated
`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var ape=H((tWt,ope)=>{"use strict";var Sst=mQ(),{MAX_LENGTH:npe,CHAR_BACKSLASH:d5,CHAR_BACKTICK:bst,CHAR_COMMA:Dst,CHAR_DOT:Pst,CHAR_LEFT_PARENTHESES:xst,CHAR_RIGHT_PARENTHESES:kst,CHAR_LEFT_CURLY_BRACE:Rst,CHAR_RIGHT_CURLY_BRACE:Tst,CHAR_LEFT_SQUARE_BRACKET:ipe,CHAR_RIGHT_SQUARE_BRACKET:spe,CHAR_DOUBLE_QUOTE:Qst,CHAR_SINGLE_QUOTE:Fst,CHAR_NO_BREAK_SPACE:Nst,CHAR_ZERO_WIDTH_NOBREAK_SPACE:Ost}=rpe(),Lst=(t,e={})=>{if(typeof t!="string")throw new TypeError("Expected a string");let r=e||{},s=typeof r.maxLength=="number"?Math.min(npe,r.maxLength):npe;if(t.length>s)throw new SyntaxError(`Input length (${t.length}), exceeds max characters (${s})`);let a={type:"root",input:t,nodes:[]},n=[a],l=a,f=a,h=0,A=t.length,m=0,w=0,v,D={},I=()=>t[m++],R=N=>{if(N.type==="text"&&f.type==="dot"&&(f.type="text"),f&&f.type==="text"&&N.type==="text"){f.value+=N.value;return}return l.nodes.push(N),N.parent=l,N.prev=f,f=N,N};for(R({type:"bos"});m<A;)if(l=n[n.length-1],v=I(),!(v===Ost||v===Nst)){if(v===d5){R({type:"text",value:(e.keepEscaping?v:"")+I()});continue}if(v===spe){R({type:"text",value:"\\"+v});continue}if(v===ipe){h++;let N=!0,U;for(;m<A&&(U=I());){if(v+=U,U===ipe){h++;continue}if(U===d5){v+=I();continue}if(U===spe&&(h--,h===0))break}R({type:"text",value:v});continue}if(v===xst){l=R({type:"paren",nodes:[]}),n.push(l),R({type:"text",value:v});continue}if(v===kst){if(l.type!=="paren"){R({type:"text",value:v});continue}l=n.pop(),R({type:"text",value:v}),l=n[n.length-1];continue}if(v===Qst||v===Fst||v===bst){let N=v,U;for(e.keepQuotes!==!0&&(v="");m<A&&(U=I());){if(U===d5){v+=U+I();continue}if(U===N){e.keepQuotes===!0&&(v+=U);break}v+=U}R({type:"text",value:v});continue}if(v===Rst){w++;let U={type:"brace",open:!0,close:!1,dollar:f.value&&f.value.slice(-1)==="$"||l.dollar===!0,depth:w,commas:0,ranges:0,nodes:[]};l=R(U),n.push(l),R({type:"open",value:v});continue}if(v===Tst){if(l.type!=="brace"){R({type:"text",value:v});continue}let N="close";l=n.pop(),l.close=!0,R({type:N,value:v}),w--,l=n[n.length-1];continue}if(v===Dst&&w>0){if(l.ranges>0){l.ranges=0;let N=l.nodes.shift();l.nodes=[N,{type:"text",value:Sst(l)}]}R({type:"comma",value:v}),l.commas++;continue}if(v===Pst&&w>0&&l.commas===0){let N=l.nodes;if(w===0||N.length===0){R({type:"text",value:v});continue}if(f.type==="dot"){if(l.range=[],f.value+=v,f.type="range",l.nodes.length!==3&&l.nodes.length!==5){l.invalid=!0,l.ranges=0,f.type="text";continue}l.ranges++,l.args=[];continue}if(f.type==="range"){N.pop();let U=N[N.length-1];U.value+=f.value+v,f=U,l.ranges--;continue}R({type:"dot",value:v});continue}R({type:"text",value:v})}do if(l=n.pop(),l.type!=="root"){l.nodes.forEach(V=>{V.nodes||(V.type==="open"&&(V.isOpen=!0),V.type==="close"&&(V.isClose=!0),V.nodes||(V.type="text"),V.invalid=!0)});let N=n[n.length-1],U=N.nodes.indexOf(l);N.nodes.splice(U,1,...l.nodes)}while(n.length>0);return R({type:"eos"}),a};ope.exports=Lst});var upe=H((rWt,lpe)=>{"use strict";var cpe=mQ(),_st=ZAe(),Mst=epe(),Ust=ape(),Dl=(t,e={})=>{let r=[];if(Array.isArray(t))for(let s of t){let a=Dl.create(s,e);Array.isArray(a)?r.push(...a):r.push(a)}else r=[].concat(Dl.create(t,e));return e&&e.expand===!0&&e.nodupes===!0&&(r=[...new Set(r)]),r};Dl.parse=(t,e={})=>Ust(t,e);Dl.stringify=(t,e={})=>cpe(typeof t=="string"?Dl.parse(t,e):t,e);Dl.compile=(t,e={})=>(typeof t=="string"&&(t=Dl.parse(t,e)),_st(t,e));Dl.expand=(t,e={})=>{typeof t=="string"&&(t=Dl.parse(t,e));let r=Mst(t,e);return e.noempty===!0&&(r=r.filter(Boolean)),e.nodupes===!0&&(r=[...new Set(r)]),r};Dl.create=(t,e={})=>t===""||t.length<3?[t]:e.expand!==!0?Dl.compile(t,e):Dl.expand(t,e);lpe.exports=Dl});var TS=H((nWt,dpe)=>{"use strict";var Hst=Ae("path"),Hh="\\\\/",fpe=`[^${Hh}]`,Rp="\\.",jst="\\+",Gst="\\?",EQ="\\/",qst="(?=.)",hpe="[^/]",g5=`(?:${EQ}|$)`,Ape=`(?:^|${EQ})`,m5=`${Rp}{1,2}${g5}`,Vst=`(?!${Rp})`,Wst=`(?!${Ape}${m5})`,Yst=`(?!${Rp}{0,1}${g5})`,Kst=`(?!${m5})`,zst=`[^.${EQ}]`,Jst=`${hpe}*?`,ppe={DOT_LITERAL:Rp,PLUS_LITERAL:jst,QMARK_LITERAL:Gst,SLASH_LITERAL:EQ,ONE_CHAR:qst,QMARK:hpe,END_ANCHOR:g5,DOTS_SLASH:m5,NO_DOT:Vst,NO_DOTS:Wst,NO_DOT_SLASH:Yst,NO_DOTS_SLASH:Kst,QMARK_NO_DOT:zst,STAR:Jst,START_ANCHOR:Ape},Zst={...ppe,SLASH_LITERAL:`[${Hh}]`,QMARK:fpe,STAR:`${fpe}*?`,DOTS_SLASH:`${Rp}{1,2}(?:[${Hh}]|$)`,NO_DOT:`(?!${Rp})`,NO_DOTS:`(?!(?:^|[${Hh}])${Rp}{1,2}(?:[${Hh}]|$))`,NO_DOT_SLASH:`(?!${Rp}{0,1}(?:[${Hh}]|$))`,NO_DOTS_SLASH:`(?!${Rp}{1,2}(?:[${Hh}]|$))`,QMARK_NO_DOT:`[^.${Hh}]`,START_ANCHOR:`(?:^|[${Hh}])`,END_ANCHOR:`(?:[${Hh}]|$)`},Xst={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&' Line truncated
`),f!==-1){let h=a+l.substring(0,f);l=l.substring(f+1),a="",e!==null?this.reportInfo(null,`${e} ${h}`):this.reportInfo(null,h)}while(f!==-1);a+=l}),r.on("end",()=>{let n=s.end();n!==""&&(e!==null?this.reportInfo(null,`${e} ${n}`):this.reportInfo(null,n))}),r}}});var Zw,H9=tt(()=>{mu();Ea();Zw=class{constructor(e){this.fetchers=e}supports(e,r){return!!this.tryFetcher(e,r)}getLocalPath(e,r){return this.getFetcher(e,r).getLocalPath(e,r)}async fetch(e,r){return await this.getFetcher(e,r).fetch(e,r)}tryFetcher(e,r){let s=this.fetchers.find(a=>a.supports(e,r));return s||null}getFetcher(e,r){let s=this.fetchers.find(a=>a.supports(e,r));if(!s)throw new Zt(11,`${hn(r.project.configuration,e)} isn't supported by any available fetcher`);return s}}});var Dy,j9=tt(()=>{Ea();Dy=class{constructor(e){this.resolvers=e.filter(r=>r)}supportsDescriptor(e,r){return!!this.tryResolverByDescriptor(e,r)}supportsLocator(e,r){return!!this.tryResolverByLocator(e,r)}shouldPersistResolution(e,r){return this.getResolverByLocator(e,r).shouldPersistResolution(e,r)}bindDescriptor(e,r,s){return this.getResolverByDescriptor(e,s).bindDescriptor(e,r,s)}getResolutionDependencies(e,r){return this.getResolverByDescriptor(e,r).getResolutionDependencies(e,r)}async getCandidates(e,r,s){return await this.getResolverByDescriptor(e,s).getCandidates(e,r,s)}async getSatisfying(e,r,s,a){return this.getResolverByDescriptor(e,a).getSatisfying(e,r,s,a)}async resolve(e,r){return await this.getResolverByLocator(e,r).resolve(e,r)}tryResolverByDescriptor(e,r){let s=this.resolvers.find(a=>a.supportsDescriptor(e,r));return s||null}getResolverByDescriptor(e,r){let s=this.resolvers.find(a=>a.supportsDescriptor(e,r));if(!s)throw new Error(`${xi(r.project.configuration,e)} isn't supported by any available resolver`);return s}tryResolverByLocator(e,r){let s=this.resolvers.find(a=>a.supportsLocator(e,r));return s||null}getResolverByLocator(e,r){let s=this.resolvers.find(a=>a.supportsLocator(e,r));if(!s)throw new Error(`${hn(r.project.configuration,e)} isn't supported by any available resolver`);return s}}});var Xw,G9=tt(()=>{Mt();Ea();Xw=class{supports(e){return!!e.reference.startsWith("virtual:")}getLocalPath(e,r){let s=e.reference.indexOf("#");if(s===-1)throw new Error("Invalid virtual package reference");let a=e.reference.slice(s+1),n=mo(e,a);return r.fetcher.getLocalPath(n,r)}async fetch(e,r){let s=e.reference.indexOf("#");if(s===-1)throw new Error("Invalid virtual package reference");let a=e.reference.slice(s+1),n=mo(e,a),l=await r.fetcher.fetch(n,r);return await this.ensureVirtualLink(e,l,r)}getLocatorFilename(e){return Yw(e)}async ensureVirtualLink(e,r,s){let a=r.packageFs.getRealPath(),n=s.project.configuration.get("virtualFolder"),l=this.getLocatorFilename(e),f=Mo.makeVirtualPath(n,l,a),h=new Qh(f,{baseFs:r.packageFs,pathUtils:Y});return{...r,packageFs:h}}}});var UF,qge=tt(()=>{UF=class t{static{this.protocol="virtual:"}static isVirtualDescriptor(e){return!!e.range.startsWith(t.protocol)}static isVirtualLocator(e){return!!e.reference.startsWith(t.protocol)}supportsDescriptor(e,r){return t.isVirtualDescriptor(e)}supportsLocator(e,r){return t.isVirtualLocator(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,s){throw new Error('Assertion failed: calling "bindDescriptor" on a virtual descriptor is unsupported')}getResolutionDependencies(e,r){throw new Error('Assertion failed: calling "getResolutionDependencies" on a virtual descriptor is unsupported')}async getCandidates(e,r,s){throw new Error('Assertion failed: calling "getCandidates" on a virtual descriptor is unsupported')}async getSatisfying(e,r,s,a){throw new Error('Assertion failed: calling "getSatisfying" on a virtual descriptor is unsupported')}async resolve(e,r){throw new Error('Assertion failed: calling "resolve" on a virtual locator is unsupported')}}});var $w,q9=tt(()=>{Mt();by();$w=class{supports(e){return!!e.reference.startsWith(Gi.protocol)}getLocalPath(e,r){return this.getWorkspace(e,r).cwd}async fetch(e,r){let s=this.getWorkspace(e,r).cwd;return{packageFs:new Jn(s),prefixPath:Rt.dot,localPath:s}}getWorkspace(e,r){return r.project.getWorkspaceByCwd(e.reference.slice(Gi.protocol.length))}}});function sb(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Vge(t){return typeof t>"u"?3:sb(t)?0:Array.isArray(t)?1:2}function Y9(t,e){return Object.hasOwn(t,e)}function aut(t){return sb(t)&&Y9(t,"onConflict")&&typeof t.onConflict=="string"}function cut(t){if(typeof t>"u")return{onConflict:"default",value:t};if(!aut(t))return{onConflict:"default",value:t};if(Y9(t,"value"))return t;let{onConflict:e,...r}=t;return{onConflict:e,value:r}}function Wge(t,e){let r=sb(t)&&Y9(t,e)?t[e]:void 0;return cut(r)}function eC(t,e){return[t,e,Yge]}function K9(t){return Array.isArray(t)?t[2]===Yge:!1}function V9(t,e){if(sb(t)){let r={};for(let s of Object.keys(t))r[s]=V9(t[s],e);return eC(e,r)}return Array.isArray(t)?eC(e,t.map(r=>V9(r,e))):eC(e,t)}function W9(t,e,r,s,a){let n,l=[],f=a,h=0;for(let m=a-Line truncated
Please report this to https://github.com/szmarczak/http2-wrapper/`);I(R)}return}s[0].resolve(D);return}}if(l in this.queue){if(f in this.queue[l]){this.queue[l][f].listeners.push(...s),this._tryToCreateNewSession(l,f);return}}else this.queue[l]={};let h=()=>{l in this.queue&&this.queue[l][f]===A&&(delete this.queue[l][f],Object.keys(this.queue[l]).length===0&&delete this.queue[l])},A=()=>{let m=`${f}:${l}`,w=!1;try{let v=Sft.connect(e,{createConnection:this.createConnection,settings:this.settings,session:this.tlsSessionCache.get(m),...r});v[oc]=0,v[sC]=!1;let D=()=>v[oc]<v.remoteSettings.maxConcurrentStreams,I=!0;v.socket.once("session",N=>{this.tlsSessionCache.set(m,N)}),v.once("error",N=>{for(let{reject:U}of s)U(N);this.tlsSessionCache.delete(m)}),v.setTimeout(this.timeout,()=>{v.destroy()}),v.once("close",()=>{if(w){I&&this._freeSessionsCount--,this._sessionsCount--;let N=this.sessions[l];N.splice(N.indexOf(v),1),N.length===0&&delete this.sessions[l]}else{let N=new Error("Session closed without receiving a SETTINGS frame");N.code="HTTP2WRAPPER_NOSETTINGS";for(let{reject:U}of s)U(N);h()}this._tryToCreateNewSession(l,f)});let R=()=>{if(!(!(l in this.queue)||!D())){for(let N of v[yu])if(N in this.queue[l]){let{listeners:U}=this.queue[l][N];for(;U.length!==0&&D();)U.shift().resolve(v);let V=this.queue[l];if(V[N].listeners.length===0&&(delete V[N],Object.keys(V).length===0)){delete this.queue[l];break}if(!D())break}}};v.on("origin",()=>{v[yu]=v.originSet,D()&&(R(),xG(this.sessions[l],v))}),v.once("remoteSettings",()=>{if(v.ref(),v.unref(),this._sessionsCount++,A.destroyed){let N=new Error("Agent has been destroyed");for(let U of s)U.reject(N);v.destroy();return}v[yu]=v.originSet;{let N=this.sessions;if(l in N){let U=N[l];U.splice(Pft(U,v,xft),0,v)}else N[l]=[v]}this._freeSessionsCount+=1,w=!0,this.emit("session",v),R(),h(),v[oc]===0&&this._freeSessionsCount>this.maxFreeSessions&&v.close(),s.length!==0&&(this.getSession(f,r,s),s.length=0),v.on("remoteSettings",()=>{R(),xG(this.sessions[l],v)})}),v[$me]=v.request,v.request=(N,U)=>{if(v[sC])throw new Error("The session is gracefully closing. No new streams are allowed.");let V=v[$me](N,U);return v.ref(),++v[oc],v[oc]===v.remoteSettings.maxConcurrentStreams&&this._freeSessionsCount--,V.once("close",()=>{if(I=D(),--v[oc],!v.destroyed&&!v.closed&&(kft(this.sessions[l],v),D()&&!v.closed)){I||(this._freeSessionsCount++,I=!0);let ee=v[oc]===0;ee&&v.unref(),ee&&(this._freeSessionsCount>this.maxFreeSessions||v[sC])?v.close():(xG(this.sessions[l],v),R())}}),V}}catch(v){for(let D of s)D.reject(v);h()}};A.listeners=s,A.completed=!1,A.destroyed=!1,this.queue[l][f]=A,this._tryToCreateNewSession(l,f)})}request(e,r,s,a){return new Promise((n,l)=>{this.getSession(e,r,[{reject:l,resolve:f=>{try{n(f.request(s,a))}catch(h){l(h)}}}])})}createConnection(e,r){return t.connect(e,r)}static connect(e,r){r.ALPNProtocols=["h2"];let s=e.port||443,a=e.hostname||e.host;return typeof r.servername>"u"&&(r.servername=a),vft.connect(s,a,r)}closeFreeSessions(){for(let e of Object.values(this.sessions))for(let r of e)r[oc]===0&&r.close()}destroy(e){for(let r of Object.values(this.sessions))for(let s of r)s.destroy(e);for(let r of Object.values(this.queue))for(let s of Object.values(r))s.destroyed=!0;this.queue={}}get freeSessions(){return eye({agent:this,isFree:!0})}get busySessions(){return eye({agent:this,isFree:!1})}};xy.kCurrentStreamsCount=oc;xy.kGracefullyClosing=sC;rye.exports={Agent:xy,globalAgent:new xy}});var TG=H((LJt,nye)=>{"use strict";var{Readable:Rft}=Ae("stream"),RG=class extends Rft{constructor(e,r){super({highWaterMark:r,autoDestroy:!1}),this.statusCode=null,this.statusMessage="",this.httpVersion="2.0",this.httpVersionMajor=2,this.httpVersionMinor=0,this.headers={},this.trailers={},this.req=null,this.aborted=!1,this.complete=!1,this.upgrade=null,this.rawHeaders=[],this.rawTrailers=[],this.socket=e,this.connection=e,this._dumped=!1}_destroy(e){this.req._request.destroy(e)}setTimeout(e,r){return this.req.setTimeout(e,r),this}_dump(){this._dumped||(this._dumped=!0,this.removeAllListeners("data"),this.resume())}_read(){this.req&&this.req._request.resume()}};nye.exports=RG});var QG=H((_Jt,iye)=>{"use strict";iye.exports=t=>{let e={protocol:t.protocol,hostname:typeof t.hostname=="string"&&t.hostname.startsWith("[")?t.hostname.slice(1,-1):t.hostname,host:t.host,hash:t.hash,search:t.search,pathname:t.pathname,href:t.href,path:`${t.pathname||""}${t.search||""}`};return typeof t.port=="string"&&t.port.length!==0&&(e.port=Number(t.port)),(t.username||t.password)&&(e.auth=`${t.username||""}:${t.password||""}`),e}});var oye=H((MJt,sye)=>{"use strict";sye.exports=(t,e,r)=>{for(let s of r)t.on(s,(...a)=>e.emit(s,...a))}});var cye=H((UJt,aye)=>{"use strict";aye.exports=t=>{switch(t){case":method":case":scheme":case":authority":case":path":return!0;default:return!1}}});var uye=H((jJt,lye)=>{"use strict";var oC=(t,e,r)=>{lye.exports[e]=class extends t{constructor(...a){super(typeof r=="string"?r: Line truncated
`).reverse(),f=r.stack.slice(r.stack.indexOf(r.message)+r.message.length).split(`
`).reverse();for(;f.length!==0&&f[0]===l[0];)l.shift();this.stack=`${this.stack.slice(0,n)}${l.reverse().join(`
`)}${f.reverse().join(`
`)}`}}};ai.RequestError=Ls;var aN=class extends Ls{constructor(e){super(`Redirected ${e.options.maxRedirects} times. Aborting.`,{},e),this.name="MaxRedirectsError"}};ai.MaxRedirectsError=aN;var cN=class extends Ls{constructor(e){super(`Response code ${e.statusCode} (${e.statusMessage})`,{},e.request),this.name="HTTPError"}};ai.HTTPError=cN;var lN=class extends Ls{constructor(e,r){super(e.message,e,r),this.name="CacheError"}};ai.CacheError=lN;var uN=class extends Ls{constructor(e,r){super(e.message,e,r),this.name="UploadError"}};ai.UploadError=uN;var fN=class extends Ls{constructor(e,r,s){super(e.message,e,s),this.name="TimeoutError",this.event=e.event,this.timings=r}};ai.TimeoutError=fN;var gb=class extends Ls{constructor(e,r){super(e.message,e,r),this.name="ReadError"}};ai.ReadError=gb;var hN=class extends Ls{constructor(e){super(`Unsupported protocol "${e.url.protocol}"`,{},e),this.name="UnsupportedProtocolError"}};ai.UnsupportedProtocolError=hN;var _ht=["socket","connect","continue","information","upgrade","timeout"],AN=class extends Wye.Duplex{constructor(e,r={},s){super({autoDestroy:!1,highWaterMark:0}),this[cC]=0,this[uC]=0,this.requestInitialized=!1,this[iN]=new Set,this.redirects=[],this[fC]=!1,this[sN]=!1,this[db]=[],this.retryCount=0,this._progressCallbacks=[];let a=()=>this._unlockWrite(),n=()=>this._lockWrite();this.on("pipe",A=>{A.prependListener("data",a),A.on("data",n),A.prependListener("end",a),A.on("end",n)}),this.on("unpipe",A=>{A.off("data",a),A.off("data",n),A.off("end",a),A.off("end",n)}),this.on("pipe",A=>{A instanceof nq.IncomingMessage&&(this.options.headers={...A.headers,...this.options.headers})});let{json:l,body:f,form:h}=r;if((l||f||h)&&this._lockWrite(),ai.kIsNormalizedAlready in r)this.options=r;else try{this.options=this.constructor.normalizeArguments(e,r,s)}catch(A){gt.default.nodeStream(r.body)&&r.body.destroy(),this.destroy(A);return}(async()=>{var A;try{this.options.body instanceof mht.ReadStream&&await Nht(this.options.body);let{url:m}=this.options;if(!m)throw new TypeError("Missing `url` property");if(this.requestUrl=m.toString(),decodeURI(this.requestUrl),await this._finalizeBody(),await this._makeRequest(),this.destroyed){(A=this[Go])===null||A===void 0||A.destroy();return}for(let w of this[db])w();this[db].length=0,this.requestInitialized=!0}catch(m){if(m instanceof Ls){this._beforeError(m);return}this.destroyed||this.destroy(m)}})()}static normalizeArguments(e,r,s){var a,n,l,f,h;let A=r;if(gt.default.object(e)&&!gt.default.urlInstance(e))r={...s,...e,...r};else{if(e&&r&&r.url!==void 0)throw new TypeError("The `url` option is mutually exclusive with the `input` argument");r={...s,...r},e!==void 0&&(r.url=e),gt.default.urlInstance(r.url)&&(r.url=new V0.URL(r.url.toString()))}if(r.cache===!1&&(r.cache=void 0),r.dnsCache===!1&&(r.dnsCache=void 0),gt.assert.any([gt.default.string,gt.default.undefined],r.method),gt.assert.any([gt.default.object,gt.default.undefined],r.headers),gt.assert.any([gt.default.string,gt.default.urlInstance,gt.default.undefined],r.prefixUrl),gt.assert.any([gt.default.object,gt.default.undefined],r.cookieJar),gt.assert.any([gt.default.object,gt.default.string,gt.default.undefined],r.searchParams),gt.assert.any([gt.default.object,gt.default.string,gt.default.undefined],r.cache),gt.assert.any([gt.default.object,gt.default.number,gt.default.undefined],r.timeout),gt.assert.any([gt.default.object,gt.default.undefined],r.context),gt.assert.any([gt.default.object,gt.default.undefined],r.hooks),gt.assert.any([gt.default.boolean,gt.default.undefined],r.decompress),gt.assert.any([gt.default.boolean,gt.default.undefined],r.ignoreInvalidCookies),gt.assert.any([gt.default.boolean,gt.default.undefined],r.followRedirect),gt.assert.any([gt.default.number,gt.default.undefined],r.maxRedirects),gt.assert.any([gt.default.boolean,gt.default.undefined],r.throwHttpErrors),gt.assert.any([gt.default.boolean,gt.default.undefined],r.http2),gt.assert.any([gt.default.boolean,gt.default.undefined],r.allowGetBody),gt.assert.any([gt.default.string,gt.default.undefined],r.localAddress),gt.assert.any([Xye.isDnsLookupIpVersion,gt.default.undefined],r.dnsLookupIpVersion),gt.assert.any([gt.default.object,gt.default.undefined],r.https),gt.assert.any([gt.default.boolean,gt.default.undefined],r.rejectUnauthorized),r.https&&(gt.assert.any([gt.default.boolean,gt.default.undefined],r.https.rejectUnauthorized),gt.assert.any([gt.default.function_,gt.default.undefined],r.https.checkServerIdentity),gt.assert.any([gt.default.string,gt.default.object,gt.default.array,gt.default.undefined],r.https.certificateAuthority),gt.assert.any([gt.default.string,gt.default.object,gt.default.array,gt.default.undefined],r.https.key),gt.assert.any([gt.default.string,gt.default.object,gt.default.array,gt.default.undefined],r.https.certificate),gt.assert.any([gt.default.string,gt.default.undefined],r.https.passphrase),gt.assert.any([gt.default.string,gt.default.buffer,gt.default.array,gt.default.undefined],r.httpLine truncated
`)[3];return BAt(e)}function Iq(){return typeof IN.default.availableParallelism<"u"?IN.default.availableParallelism():Math.max(1,IN.default.cpus().length)}var IN,gAt,kEe,mAt,yAt,REe,TEe,wAt,CAt,wN=tt(()=>{Mt();IN=st(Ae("os"));CN();Au();gAt=Number(process.versions.node.split(".")[0]),kEe=new Map([["darwin","open"],["linux","xdg-open"],["win32","explorer.exe"]]).get(process.platform),mAt=typeof kEe<"u"?async t=>{try{return await wq(kEe,[t],{cwd:Y.cwd()}),!0}catch{return!1}}:void 0,yAt="/usr/bin/ldd";wAt=/^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack|<anonymous>|\/|[a-z]:\\|\\\\).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i,CAt=/\((\S*)(?::(\d+))(?::(\d+))\)/});function Dq(t,e,r,s,a){let n=ob(r);if(s.isArray||s.type==="ANY"&&Array.isArray(n))return Array.isArray(n)?n.map((l,f)=>Cq(t,`${e}[${f}]`,l,s,a)):String(n).split(/,/).map(l=>Cq(t,e,l,s,a));if(Array.isArray(n))throw new Error(`Non-array configuration settings "${e}" cannot be an array`);return Cq(t,e,r,s,a)}function Cq(t,e,r,s,a){let n=ob(r);switch(s.type){case"ANY":return HF(n);case"SHAPE":return PAt(t,e,r,s,a);case"MAP":return xAt(t,e,r,s,a)}if(n===null&&!s.isNullable&&s.default!==null)throw new Error(`Non-nullable configuration settings "${e}" cannot be set to null`);if("values"in s&&s.values?.includes(n))return n;let f=(()=>{if(s.type==="BOOLEAN"&&typeof n!="string")return qS(n);if(typeof n!="string")throw new Error(`Expected configuration setting "${e}" to be a string, got ${typeof n}`);let h=$Q(n,{env:t.env});switch(s.type){case"ABSOLUTE_PATH":{let A=a,m=z9(r);return m&&m[0]!=="<"&&(A=Y.dirname(m)),Y.resolve(A,me.toPortablePath(h))}case"LOCATOR_LOOSE":return Op(h,!1);case"NUMBER":return parseInt(h);case"LOCATOR":return Op(h);case"BOOLEAN":return qS(h);case"DURATION":return eF(h,s.unit);default:return h}})();if("values"in s&&s.values&&!s.values.includes(f))throw new Error(`Invalid value, expected one of ${s.values.join(", ")}`);return f}function PAt(t,e,r,s,a){let n=ob(r);if(typeof n!="object"||Array.isArray(n))throw new ht(`Object configuration settings "${e}" must be an object`);let l=Pq(t,s,{ignoreArrays:!0});if(n===null)return l;for(let[f,h]of Object.entries(n)){let A=`${e}.${f}`;if(!s.properties[f])throw new ht(`Unrecognized configuration settings found: ${e}.${f} - run "yarn config" to see the list of settings supported in Yarn`);l.set(f,Dq(t,A,h,s.properties[f],a))}return l}function xAt(t,e,r,s,a){let n=ob(r),l=new Map;if(typeof n!="object"||Array.isArray(n))throw new ht(`Map configuration settings "${e}" must be an object`);if(n===null)return l;for(let[f,h]of Object.entries(n)){let A=s.normalizeKeys?s.normalizeKeys(f):f,m=`${e}['${A}']`,w=s.valueDefinition;l.set(A,Dq(t,m,h,w,a))}return l}function Pq(t,e,{ignoreArrays:r=!1}={}){switch(e.type){case"SHAPE":{if(e.isArray&&!r)return[];let s=new Map;for(let[a,n]of Object.entries(e.properties))s.set(a,Pq(t,n));return s}case"MAP":return e.isArray&&!r?[]:new Map;case"ABSOLUTE_PATH":return e.default===null?null:t.projectCwd===null?Array.isArray(e.default)?e.default.map(s=>Y.normalize(s)):Y.isAbsolute(e.default)?Y.normalize(e.default):e.isNullable?null:void 0:Array.isArray(e.default)?e.default.map(s=>Y.resolve(t.projectCwd,s)):Y.resolve(t.projectCwd,e.default);case"DURATION":return eF(e.default,e.unit);default:return e.default}}function vN(t,e,r){if(e.type==="SECRET"&&typeof t=="string"&&r.hideSecrets)return DAt;if(e.type==="ABSOLUTE_PATH"&&typeof t=="string"&&r.getNativePaths)return me.fromPortablePath(t);if(e.isArray&&Array.isArray(t)){let s=[];for(let a of t)s.push(vN(a,e,r));return s}if(e.type==="MAP"&&t instanceof Map){if(t.size===0)return;let s=new Map;for(let[a,n]of t.entries()){let l=vN(n,e.valueDefinition,r);typeof l<"u"&&s.set(a,l)}return s}if(e.type==="SHAPE"&&t instanceof Map){if(t.size===0)return;let s=new Map;for(let[a,n]of t.entries()){let l=e.properties[a],f=vN(n,l,r);typeof f<"u"&&s.set(a,f)}return s}return t}function kAt(){let t={};for(let[e,r]of Object.entries(process.env))e=e.toLowerCase(),e.startsWith(SN)&&(e=(0,FEe.default)(e.slice(SN.length)),t[e]=r);return t}function vq(){let t=`${SN}rc_filename`;for(let[e,r]of Object.entries(process.env))if(e.toLowerCase()===t&&typeof r=="string")return r;return Sq}async function QEe(t){try{return await fe.readFilePromise(t)}catch{return Buffer.of()}}async function RAt(t,e){return Buffer.compare(...await Promise.all([QEe(t),QEe(e)]))===0}async function TAt(t,e){let[r,s]=await Promise.all([fe.statPromise(t),fe.statPromise(e)]);return r.dev===s.dev&&r.ino===s.ino}async function FAt({configuration:t,selfPath:e}){let r=t.get("yarnPath");return t.get("ignorePath")||r===null||r===e||await QAt(r,e)?null:r}var FEe,jp,NEe,OEe,LEe,Bq,SAt,wb,bAt,Gp,SN,Sq,DAt,hC,_Ee,bq,bN,BN,QAt,$e,Cb=tt(()=>{Mt();au();FEe=st(aue()),jp=st(ly());sr();NEe=st(efe()),OEe=Ae("module"),LEe=st(hy()),Bq=Ae("stream");Tge();Jw();H9();j9();G9();qge();q9();by();zge();GF();pu();G0();EN();Au();wN();_p();Ea();SAt=function(){if(!jp.GITHUB_ACTIONS||!process.env.GITHUB_EVE Line truncated
`);return{stdout:n,stderr:l}}makeResolver(){let e=[];for(let r of this.plugins.values())for(let s of r.resolvers||[])e.push(new s);return new Dy([new UF,new Gi,...e])}makeFetcher(){let e=[];for(let r of this.plugins.values())for(let s of r.fetchers||[])e.push(new s);return new Zw([new Xw,new $w,...e])}getLinkers(){let e=[];for(let r of this.plugins.values())for(let s of r.linkers||[])e.push(new s);return e}getSupportedArchitectures(){let e=Ib(),r=this.get("supportedArchitectures"),s=r.get("os");s!==null&&(s=s.map(l=>l==="current"?e.os:l));let a=r.get("cpu");a!==null&&(a=a.map(l=>l==="current"?e.cpu:l));let n=r.get("libc");return n!==null&&(n=kl(n,l=>l==="current"?e.libc??kl.skip:l)),{os:s,cpu:a,libc:n}}isInteractive({interactive:e,stdout:r}){return r.isTTY?e??this.get("preferInteractive"):!1}async getPackageExtensions(){if(this.packageExtensions!==null)return this.packageExtensions;this.packageExtensions=new Map;let e=this.packageExtensions,r=(s,a,{userProvided:n=!1}={})=>{if(!Vc(s.range))throw new Error("Only semver ranges are allowed as keys for the packageExtensions setting");let l=new nr;l.load(a,{yamlCompatibilityMode:!0});let f=GS(e,s.identHash),h=[];f.push([s.range,h]);let A={status:"inactive",userProvided:n,parentDescriptor:s};for(let m of l.dependencies.values())h.push({...A,type:"Dependency",descriptor:m});for(let m of l.peerDependencies.values())h.push({...A,type:"PeerDependency",descriptor:m});for(let[m,w]of l.peerDependenciesMeta)for(let[v,D]of Object.entries(w))h.push({...A,type:"PeerDependencyMeta",selector:m,key:v,value:D})};await this.triggerHook(s=>s.registerPackageExtensions,this,r);for(let[s,a]of this.get("packageExtensions"))r(q0(s,!0),XQ(a),{userProvided:!0});return e}normalizeLocator(e){return Vc(e.reference)?mo(e,`${this.get("defaultProtocol")}${e.reference}`):Gp.test(e.reference)?mo(e,`${this.get("defaultProtocol")}${e.reference}`):e}normalizeDependency(e){return Vc(e.range)?oi(e,`${this.get("defaultProtocol")}${e.range}`):Gp.test(e.range)?oi(e,`${this.get("defaultProtocol")}${e.range}`):e}normalizeDependencyMap(e){return new Map([...e].map(([r,s])=>[r,this.normalizeDependency(s)]))}normalizePackage(e,{packageExtensions:r}){let s=ZS(e),a=r.get(e.identHash);if(typeof a<"u"){let l=e.version;if(l!==null){for(let[f,h]of a)if(Wh(l,f))for(let A of h)switch(A.status==="inactive"&&(A.status="redundant"),A.type){case"Dependency":typeof s.dependencies.get(A.descriptor.identHash)>"u"&&(A.status="active",s.dependencies.set(A.descriptor.identHash,this.normalizeDependency(A.descriptor)));break;case"PeerDependency":typeof s.peerDependencies.get(A.descriptor.identHash)>"u"&&(A.status="active",s.peerDependencies.set(A.descriptor.identHash,A.descriptor));break;case"PeerDependencyMeta":{let m=s.peerDependenciesMeta.get(A.selector);(typeof m>"u"||!Object.hasOwn(m,A.key)||m[A.key]!==A.value)&&(A.status="active",Rl(s.peerDependenciesMeta,A.selector,()=>({}))[A.key]=A.value)}break;default:z5(A)}}}let n=l=>l.scope?`${l.scope}__${l.name}`:`${l.name}`;for(let l of s.peerDependenciesMeta.keys()){let f=nc(l);s.peerDependencies.has(f.identHash)||s.peerDependencies.set(f.identHash,oi(f,"*"))}for(let l of s.peerDependencies.values()){if(l.scope==="types")continue;let f=n(l),h=ic("types",f),A=Qn(h);s.peerDependencies.has(h.identHash)||s.peerDependenciesMeta.has(A)||s.dependencies.has(h.identHash)||(s.peerDependencies.set(h.identHash,oi(h,"*")),s.peerDependenciesMeta.set(A,{optional:!0}))}return s.dependencies=new Map(go(s.dependencies,([,l])=>Gc(l))),s.peerDependencies=new Map(go(s.peerDependencies,([,l])=>Gc(l))),s}getLimit(e){return Rl(this.limits,e,()=>(0,LEe.default)(this.get(e)))}async triggerHook(e,...r){for(let s of this.plugins.values()){let a=s.hooks;if(!a)continue;let n=e(a);n&&await n(...r)}}async triggerMultipleHooks(e,r){for(let s of r)await this.triggerHook(e,...s)}async reduceHook(e,r,...s){let a=r;for(let n of this.plugins.values()){let l=n.hooks;if(!l)continue;let f=e(l);f&&(a=await f(a,...s))}return a}async firstHook(e,...r){for(let s of this.plugins.values()){let a=s.hooks;if(!a)continue;let n=e(a);if(!n)continue;let l=await n(...r);if(typeof l<"u")return l}return null}}});var un={};lr(un,{EndStrategy:()=>Tq,ExecError:()=>DN,PipeError:()=>Bb,execvp:()=>wq,pipevp:()=>Tf});function Ry(t){return t!==null&&typeof t.fd=="number"}function xq(){}function kq(){for(let t of Ty)t.kill()}async function Tf(t,e,{cwd:r,env:s=process.env,strict:a=!1,stdin:n=null,stdout:l,stderr:f,end:h=2}){let A=["pipe","pipe","pipe"];n===null?A[0]="ignore":Ry(n)&&(A[0]=n),Ry(l)&&(A[1]=l),Ry(f)&&(A[2]=f);let m=(0,Rq.default)(t,e,{cwd:me.fromPortablePath(r),env:{...s,PWD:me.fromPortablePath(r)},stdio:A});Ty.add(m),Ty.size===1&&(process.on("SIGINT",xq),process.on("SIGTERM",kq)),!Ry(n)&&n!==null&&n.pipe(m.stdin),Ry(l)||m.stdout.pipe(l,{end:!1}),Ry(f)||m.stderr.pipe(f,{end:!1});let w=()=>{for(let v of new Set([l,f]))Ry(v)||v.end()};return new Promise((v,D)=>{m.on("error",I=>{Ty.delete(m),Ty.size===0&&(process.off("SIGINT",xq),pro Line truncated
This command will run a command using Yarn's portable shell.
Make sure to escape glob patterns, redirections, and other features that might be expanded by your own shell.
Note: To escape something from Yarn's shell, you might have to escape it twice, the first time from your own shell.
Note: Don't use this command in Yarn scripts, as Yarn's shell is automatically used.
For a list of features, visit: https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-shell/README.md.
`,examples:[["Run a simple command","$0 echo Hello"],["Run a command with a glob pattern","$0 echo '*.js'"],["Run a command with a redirection","$0 echo Hello World '>' hello.txt"],["Run a command with an escaped glob pattern (The double escape is needed in Unix shells)",`$0 echo '"*.js"'`],["Run a command with a variable (Double quotes are needed in Unix shells, to prevent them from expanding the variable)",'$0 "GREETING=Hello echo $GREETING World"']]}}async execute(){let r=this.args.length>0?`${this.commandName} ${this.args.join(" ")}`:this.commandName;return await pC(r,[],{cwd:me.toPortablePath(this.cwd),stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}}});var Tl,tIe=tt(()=>{Tl=class extends Error{constructor(e){super(e),this.name="ShellError"}}});var FN={};lr(FN,{fastGlobOptions:()=>iIe,isBraceExpansion:()=>Wq,isGlobPattern:()=>HAt,match:()=>jAt,micromatchOptions:()=>QN});function HAt(t){if(!TN.default.scan(t,QN).isGlob)return!1;try{TN.default.parse(t,QN)}catch{return!1}return!0}function jAt(t,{cwd:e,baseFs:r}){return(0,rIe.default)(t,{...iIe,cwd:me.fromPortablePath(e),fs:vT(nIe.default,new B0(r))})}function Wq(t){return TN.default.scan(t,QN).isBrace}var rIe,nIe,TN,QN,iIe,sIe=tt(()=>{Mt();rIe=st(xF()),nIe=st(Ae("fs")),TN=st(ma()),QN={strictBrackets:!0},iIe={onlyDirectories:!1,onlyFiles:!1}});function Yq(){}function Kq(){for(let t of Fy)t.kill()}function lIe(t,e,r,s){return a=>{let n=a[0]instanceof zh.Transform?"pipe":a[0],l=a[1]instanceof zh.Transform?"pipe":a[1],f=a[2]instanceof zh.Transform?"pipe":a[2],h=(0,aIe.default)(t,e,{...s,stdio:[n,l,f]});return Fy.add(h),Fy.size===1&&(process.on("SIGINT",Yq),process.on("SIGTERM",Kq)),a[0]instanceof zh.Transform&&a[0].pipe(h.stdin),a[1]instanceof zh.Transform&&h.stdout.pipe(a[1],{end:!1}),a[2]instanceof zh.Transform&&h.stderr.pipe(a[2],{end:!1}),{stdin:h.stdin,promise:new Promise(A=>{h.on("error",m=>{switch(Fy.delete(h),Fy.size===0&&(process.off("SIGINT",Yq),process.off("SIGTERM",Kq)),m.code){case"ENOENT":a[2].write(`command not found: ${t}
`),A(127);break;case"EACCES":a[2].write(`permission denied: ${t}
`),A(128);break;default:a[2].write(`uncaught error: ${m.message}
`),A(1);break}}),h.on("close",m=>{Fy.delete(h),Fy.size===0&&(process.off("SIGINT",Yq),process.off("SIGTERM",Kq)),A(m!==null?m:129)})})}}}function uIe(t){return e=>{let r=e[0]==="pipe"?new zh.PassThrough:e[0];return{stdin:r,promise:Promise.resolve().then(()=>t({stdin:r,stdout:e[1],stderr:e[2]}))}}}function NN(t,e){return Jq.start(t,e)}function oIe(t,e=null){let r=new zh.PassThrough,s=new cIe.StringDecoder,a="";return r.on("data",n=>{let l=s.write(n),f;do if(f=l.indexOf(`
`),f!==-1){let h=a+l.substring(0,f);l=l.substring(f+1),a="",t(e!==null?`${e} ${h}`:h)}while(f!==-1);a+=l}),r.on("end",()=>{let n=s.end();n!==""&&t(e!==null?`${e} ${n}`:n)}),r}function fIe(t,{prefix:e}){return{stdout:oIe(r=>t.stdout.write(`${r}
`),t.stdout.isTTY?e:null),stderr:oIe(r=>t.stderr.write(`${r}
`),t.stderr.isTTY?e:null)}}var aIe,zh,cIe,Fy,wu,zq,Jq,Zq=tt(()=>{aIe=st(O6()),zh=Ae("stream"),cIe=Ae("string_decoder"),Fy=new Set;wu=class{constructor(e){this.stream=e}close(){}get(){return this.stream}},zq=class{constructor(){this.stream=null}close(){if(this.stream===null)throw new Error("Assertion failed: No stream attached");this.stream.end()}attach(e){this.stream=e}get(){if(this.stream===null)throw new Error("Assertion failed: No stream attached");return this.stream}},Jq=class t{constructor(e,r){this.stdin=null;this.stdout=null;this.stderr=null;this.pipe=null;this.ancestor=e,this.implementation=r}static start(e,{stdin:r,stdout:s,stderr:a}){let n=new t(null,e);return n.stdin=r,n.stdout=s,n.stderr=a,n}pipeTo(e,r=1){let s=new t(this,e),a=new zq;return s.pipe=a,s.stdout=this.stdout,s.stderr=this.stderr,(r&1)===1?this.stdout=a:this.ancestor!==null&&(this.stderr=this.ancestor.stdout),(r&2)===2?this.stderr=a:this.ancestor!==null&&(this.stderr=this.ancestor.stderr),s}async exec(){let e=["ignore","ignore","ignore"];if(this.pipe)e[0]="pipe";else{if(this.stdin===null)throw new Error("Assertion failed: No input stream registered");e[0]=this.stdin.get()}let r;if(this.stdout===null)throw new Error("Assertion failed: No output stream registered");r=this.stdout,e[1]=r.get();let s;if(this.stderr===null)throw new Error("Assertion failed: No error stream registered");s=this.stderr,e[2]=s.get();let a=this.implementation(e);return this.pipe&&this.pipe.attach(a.stdin),await a.promise.then(n=>(r.close(),s.close(),n))}async run(){let e=[];for(let s=this;s;s=s.ancestor)e.push(s.exec());return(await Promise.all(e))[0]}}});var Tb={};lr(Tb,{EntryCommand:()=>Db,ShellError:()=>Tl,execute:()=>pC,globUtils:()=>FN});function hIe(t,e,r){let s=new Ql.PassThrough({autoDestroy:!0});switch(t){case 0:(e&1)===1&&r.stdin.pipe(s,{end:!1}),(e&2)===2&&r.stdin instanceof Ql.Writable&&s.pipe(r.stdin,{end:!1});break;case 1:(e&1)===1&&r.stdout.pipe(s,{end:!1}),(e&2)===2&&s.pipe(r.stdout,{end:!1});break;case 2:(e&1)===1&&r.stderr.pipe(s,{end:!1}),(e&2)===2&&s.pipe(r.stderr,{end:!1});break;default:throw new Tl(`Bad file descriptor: "${t}"`)}return s}function LN(t,e={}){let r={...t,...e};return r.environment={...t.environment,...e.environment},r.variables={...t.variables,...e.variables},r}async function qAt(t,e,r){let s=[],a=new Ql.PassThrough;return a.on("data",n=>s.push(n)),await _N(t,e,LN(r,{stdout:a})),Buffer.concat(s).toString().replace(/[\r\n]+$/,"")}async function AIe(t,e,r){let s=t.map(async n=>{let l=await Ny(n.args,e,r);return{name:n.name,value:l.join(" ")}});return(await Promise.all(s)).reduce((n,l)=>(n[l.name]=l.value,n),{})}function ON(t){return t.match(/[^ \r\n\t]+/g)||[]}async function EIe(t,e,r,s,a=s){switch(t.name){case"$":s(String(process.pid));break;case"#":s(String(e.args.length));break;case"@":if(t.quoted)for(let n of e.args)a(n);else for(let n of e.args){let l=ON(n);for(let f=0;f<l.length-1;++f)a(l[f]);s(l[l.length-1])}break;case"*":{let n=e.args.join(" ");if(t.quoted)s(n);else for(let l of ON(n))a(l)}break;case"PPID":s(String(process.ppid));break;case"RANDOM":s(String(Math.floor(Math.random()*32768)));break;default:{let n=parseInt(t.name,10),l,f=Number.isFinite(n);if(f?n>=0&&n<e.args.length&&(l=e.args[n]):Object.hasOwn(r.variables,t.name)?l=r.variables[t.name]:Object.hasOwn(r.environment,t.name)&&(l=r.environment[t.name]),typeof l<"u"&&t.alternativeValue?l=(await Ny(t.alternativeValue,e,r)).join(" "):typeof l>"u"&&(t.defaultValue?l=(await Ny(t.defaultValue,e,r)).join(" "):t.alternativeValue&&(l="")),typeof l>"u")throw f?new Tl(`Unbound argument #${n}`):new Tl(`Unbound variable "${t.name}"`);if(t.quoted)s(l);else{let h=ON(l);for(let m=0;m<h.length-1;++m)a(h[m]);let A=h[h.length-1];typeof A<"u"&&s(A)}}break}}async function xb(t,e,r){if(t.type==="number"){if(Number.isInteger(t.value))return t.value;throw new Error(`Invalid number: "${t.value}", only integers are allowed`)}else if(t.type==="variable"){let s=[];await EIe({...t,quoted:!0},e,r,n=>s.push(n));let a=Number(s.join(" "));return Number.isNaN(a)?xb({type:"variable",name:s.join(" ")},e,r):xb({type:"number",value:a},e,r)}else return VAt[t.type](await xb(t.left,e,r),await xb(t.right,e,r))}async function Ny(t,e,r){let s=new Map,a=[],n=[],l=m=>{n.push(m)},f=()=>{n.length>0&&a.push(n.join("")),n=[]},h=m=>{l(m),f()},A=(m,w,v)=>{let D=JSON.stringify({type:m,fd:w}),I=s.get(D);typeof I>"u"&&s.set(D,I=[]),I.push(v)};for(let m of t){let w=!1;switch(m.type){case"redirection":{let v=await Ny(m.args,e,r);for(let D of v)A(m.subtype,m.fd,D)}break;case"argument":for(let v of m.segments)switch(v.type){case"text":l(v.text);break;case"glob":l(v.pattern),w=!0;break;case"shell":{let D=await qAt(v.shell,e,r);if(v.quoted)l(D);else{let I=ON(D);for(let R=0;R<I.length-1;++R)h(I[R]);l(I[I.length-1])}}break;case"variable":await EIe(v,e,r,l,h);break;case"arithmetic":l(String(await xb(v.arithmetic,e,r)));break}break}if(f(),w){let v=a.pop();if(typeof v>"u")throw new Error("Assertion failed: Expected a glob pa Line truncated
`)).finally(()=>{r.stdout.isTTY&&r.stdout.write(`Job ${h}, '${l(hw(t))}' has ended
`)})),0}return await dIe(t,e,r)}async function zAt(t,e,r,{background:s=!1}={}){let a,n=f=>{a=f,r.variables["?"]=String(f)},l=async f=>{try{return await KAt(f.chain,e,r,{background:s&&typeof f.then>"u"})}catch(h){if(!(h instanceof Tl))throw h;return r.stderr.write(`${h.message}
`),1}};for(n(await l(t));t.then;){if(r.exitCode!==null)return r.exitCode;switch(t.then.type){case"&&":a===0&&n(await l(t.then.line));break;case"||":a!==0&&n(await l(t.then.line));break;default:throw new Error(`Assertion failed: Unsupported command type: "${t.then.type}"`)}t=t.then.line}return a}async function _N(t,e,r){let s=r.backgroundJobs;r.backgroundJobs=[];let a=0;for(let{command:n,type:l}of t){if(a=await zAt(n,e,r,{background:l==="&"}),r.exitCode!==null)return r.exitCode;r.variables["?"]=String(a)}return await Promise.all(r.backgroundJobs),r.backgroundJobs=s,a}function IIe(t){switch(t.type){case"variable":return t.name==="@"||t.name==="#"||t.name==="*"||Number.isFinite(parseInt(t.name,10))||"defaultValue"in t&&!!t.defaultValue&&t.defaultValue.some(e=>Rb(e))||"alternativeValue"in t&&!!t.alternativeValue&&t.alternativeValue.some(e=>Rb(e));case"arithmetic":return Xq(t.arithmetic);case"shell":return $q(t.shell);default:return!1}}function Rb(t){switch(t.type){case"redirection":return t.args.some(e=>Rb(e));case"argument":return t.segments.some(e=>IIe(e));default:throw new Error(`Assertion failed: Unsupported argument type: "${t.type}"`)}}function Xq(t){switch(t.type){case"variable":return IIe(t);case"number":return!1;default:return Xq(t.left)||Xq(t.right)}}function $q(t){return t.some(({command:e})=>{for(;e;){let r=e.chain;for(;r;){let s;switch(r.type){case"subshell":s=$q(r.subshell);break;case"command":s=r.envs.some(a=>a.args.some(n=>Rb(n)))||r.args.some(a=>Rb(a));break}if(s)return!0;if(!r.then)break;r=r.then.chain}if(!e.then)break;e=e.then.line}return!1})}async function pC(t,e=[],{baseFs:r=new pi,builtins:s={},cwd:a=me.toPortablePath(process.cwd()),env:n=process.env,stdin:l=process.stdin,stdout:f=process.stdout,stderr:h=process.stderr,variables:A={},glob:m=FN}={}){let w={};for(let[I,R]of Object.entries(n))typeof R<"u"&&(w[I]=R);let v=new Map(GAt);for(let[I,R]of Object.entries(s))v.set(I,R);l===null&&(l=new Ql.PassThrough,l.end());let D=DT(t,m);if(!$q(D)&&D.length>0&&e.length>0){let{command:I}=D[D.length-1];for(;I.then;)I=I.then.line;let R=I.chain;for(;R.then;)R=R.then.chain;R.type==="command"&&(R.args=R.args.concat(e.map(N=>({type:"argument",segments:[{type:"text",text:N}]}))))}return await _N(D,{args:e,baseFs:r,builtins:v,initialStdin:l,initialStdout:f,initialStderr:h,glob:m},{cwd:a,environment:w,exitCode:null,procedures:{},stdin:l,stdout:f,stderr:h,variables:Object.assign({},A,{"?":0}),nextBackgroundJobIndex:1,backgroundJobs:[]})}var gIe,mIe,Ql,yIe,GAt,VAt,Pb=tt(()=>{Mt();au();gIe=st(Cw()),mIe=Ae("os"),Ql=Ae("stream"),yIe=Ae("timers/promises");eIe();tIe();sIe();Zq();Zq();GAt=new Map([["cd",async([t=(0,mIe.homedir)(),...e],r,s)=>{let a=Y.resolve(s.cwd,me.toPortablePath(t));if(!(await r.baseFs.statPromise(a).catch(l=>{throw l.code==="ENOENT"?new Tl(`cd: no such file or directory: ${t}`):l})).isDirectory())throw new Tl(`cd: not a directory: ${t}`);return s.cwd=a,0}],["pwd",async(t,e,r)=>(r.stdout.write(`${me.fromPortablePath(r.cwd)}
`),0)],[":",async(t,e,r)=>0],["true",async(t,e,r)=>0],["false",async(t,e,r)=>1],["exit",async([t,...e],r,s)=>s.exitCode=parseInt(t??s.variables["?"],10)],["echo",async(t,e,r)=>(r.stdout.write(`${t.join(" ")}
`),0)],["sleep",async([t],e,r)=>{if(typeof t>"u")throw new Tl("sleep: missing operand");let s=Number(t);if(Number.isNaN(s))throw new Tl(`sleep: invalid time interval '${t}'`);return await(0,yIe.setTimeout)(1e3*s,0)}],["unset",async(t,e,r)=>{for(let s of t)delete r.environment[s],delete r.variables[s];return 0}],["__ysh_run_procedure",async(t,e,r)=>{let s=r.procedures[t[0]];return await NN(s,{stdin:new wu(r.stdin),stdout:new wu(r.stdout),stderr:new wu(r.stderr)}).run()}],["__ysh_set_redirects",async(t,e,r)=>{let s=r.stdin,a=r.stdout,n=r.stderr,l=[],f=[],h=[],A=0;for(;t[A]!=="--";){let w=t[A++],{type:v,fd:D}=JSON.parse(w),I=V=>{switch(D){case null:case 0:l.push(V);break;default:throw new Error(`Unsupported file descriptor: "${D}"`)}},R=V=>{switch(D){case null:case 1:f.push(V);break;case 2:h.push(V);break;default:throw new Error(`Unsupported file descriptor: "${D}"`)}},N=Number(t[A++]),U=A+N;for(let V=A;V<U;++A,++V)switch(v){case"<":I(()=>e.baseFs.createReadStream(Y.resolve(r.cwd,me.toPortablePath(t[V]))));break;case"<<<":I(()=>{let ee=new Ql.PassThrough;return process.nextTick(()=>{ee.write(`${t[V]}
`),ee.end()}),ee});break;case"<&":I(()=>hIe(Number(t[V]),1,r));break;case">":case">>":{let ee=Y.resolve(r.cwd,me.toPortablePath(t[V]));R(ee==="/dev/null"?new Ql.Writable({autoDestroy:!0,emitClose:!0,write(te,ie,ae){setImmediate(ae)}}):e.baseFs.createWriteStream(ee,v===">>"?{flags:"a"}:void 0))}break;case">&":R(hIe(Number(t[V]),2,r));break;default:throw new Error(`Assertion failed: Unsupported redirection type: "${v}"`)}}if(l.length>0){let w=new Ql.PassThrough;s=w;let v=D=>{if(D===l.length)w.end();else{let I=l[D]();I.pipe(w,{end:!1}),I.on("end",()=>{v(D+1)})}};v(0)}if(f.length>0){let w=new Ql.PassThrough;a=w;for(let v of f)w.pipe(v)}if(h.length>0){let w=new Ql.PassThrough;n=w;for(let v of h)w.pipe(v)}let m=await NN(kb(t.slice(A+1),e,r),{stdin:new wu(s),stdout:new wu(a),stderr:new wu(n)}).run();return await Promise.all(f.map(w=>new Promise((v,D)=>{w.on("error",I=>{D(I)}),w.on("close",()=>{v()}),w.end()}))),await Promise.all(h.map(w=>new Promise((v,D)=>{w.on("error",I=>{D(I)}),w.on("close",()=>{v()}),w.end()}))),m}]]);VAt={addition:(t,e)=>t+e,subtraction:(t,e)=>t-e,multiplication:(t,e)=>t*e,division:(t,e)=>Math.trunc(t/e)}});var wIe=H((g$t,MN)=>{function JAt(){var t=0,e=1,r=2,s=3,a=4,n=5,l=6,f=7,h=8,A=9,m=10,w=11,v=12,D=13,I=14,R=15,N=16,U=17,V=0,ee=1,te=2,ie=3,ae=4;function ge(d,be){return 55296<=d.charCodeAt(be)&&d.charCodeAt(be)<=56319&&56320<=d.charCodeAt(be+1)&&d.charCodeAt(be+1)<=57343}function de(d,be){be===void 0&&(be=0);var Ce=d.charCodeAt(be);if(55296<=Ce&&Ce<=56319&&be<d.length-1){var Ee=Ce,he=d.charCodeAt(be+1);return 56320<=he&&he<=57343?(Ee-55296)*1024+(he-56320)+65536:Ee}if(56320<=Ce&&Ce<=57343&&be>=1){var Ee=d.charCodeAt(be-1),he=Ce;return 55296<=Ee&&Ee<=56319?(Ee-55296)*1024+(he-56320)+65536:he}return Ce}function xe(d,be,Ce){var Ee=[d].concat(be).concat([Ce]),he=Ee[Ee.length-2],$=Ce,De=Ee.lastIndexOf(I);if(De>1&&Ee.slice(1,De).every(function(j){return j==s})&&[s,D,U].indexOf(d)==-1)return te;var Te=Ee.lastIndexOf(a);if(Te>0&&Ee.slice(1,Te).every(function(j){return j==a})&&[v,a].indexOf(he)==-1)return Ee.filter(function(j){return j==a}).length%2==1?ie:ae;if(he==t&&$==e)return V;if(he==r||he==t||he==e)return $==I&&be.every(function(j){return j==s})?te:ee;if($==r||$==t||$==e)return ee;if(he==l&&($==l||$==f||$==A||$==m))return V;if((he==A||he==f)&&($==f||$==h))return V;if((he==m||he==h)&&$==h)return V;if($==s||$==R)return V;if($==n)return V;if(he==v)return V;var ot=Ee.indexOf(s)!=-1?Ee.lastIndexOf(s)-1:Ee.length-2;return[D,U].indexOf(Ee[ot])!=-1&&Ee.slice(ot+1,-1).every(function(j){return j==s})&&$==I||he==R&&[N,U].indexOf($)!=-1?V:be.indexOf(a)!=-1?te:he==a&&$==a?V:ee}this.nextBreak=function(d,be){if(be===void 0&&(be=0),be<0)return 0;if(be>=d.length-1)return d.length;for(var Ce=we(de(d,be)),Ee=[],he=be+1;he<d.length;he++)if(!ge(d,he-1)){var $=we(de(d,he));if(xe(Ce,Ee,$))return he;Ee.push($)}return d.length},this.splitGraphemes=function(d){for(var be=[],Ce=0,Ee;(Ee=this.nextBreak(d,Ce))<d.length;)be.push(d.slice(Ce,Ee)),Ce=Ee;return Ce<d.length&&be.push(d.slice(Ce)),be},this.iterateGraphemes=function(d){var be=0,Ce={next:function(){var Ee,he;return(he=this.nextBreak(d,be))<d.length?(Ee=d.slice(be,he),be=he,{value:Ee,done:!1}):be<d.length?(Ee=d.slice(be),be=d.length,{value:Ee,done:!1}):{value:void 0,done:!0}}.bind(this)};return typeof Symbol<"u"&&Symbol.iterator&&(Ce[Symbol.iterator]=function(){return Ce}),Ce},this.countGraphemes=function(d){for(var be=0,Ce=0,Ee;(Ee=this.nextBreak(d,Ce))<d.length;)Ce=Ee,be++;return Ce<d.length&&be++,be};function we(d){return 1536<=d&&d<=1541||d==1757||d==1807||d==2274||d==3406||d==69821||70082<=d&&d<=70083||d==72250||72326<=d&&d<=72329||d==73030?v:d==13?t:d==10?e:0<=d&&d<=9||11<=d&&d<=12||14<=d&&d<=31||127<=d&&d<=159||d==173||d==1564||d==6158||d==8203||8206<=d&&d<=8207||d==8232||d==8233||8234<=d&&d<=8238||8288<=d&&d<=8292||d==8293||8294<=d&&d<=8303||55296<=d&&d<=57343||d==65279||65520<=d&&d<=65528||65529<=d&&d<=65531||113824<=d&&d<=113827||119155<=d&&d<=119162||d==917504||d==917505||917506<=d&&d<=917535||917632<=d&&d<=917759||918e3<=d&&d<=921599?r:768<=d&&d<=879||1155<=d&&d<=1159||1160<=d&&d<=1161||1425<=d&&d<=1469||d==1471||1473<=d&&d<=1474||1476<=d&&d<=1477||d==1479||1552<=d&&d<=1562||1611<=d&&d<=1631||d==1648||1750<=d&&d<=1756||1759<=d&&d<=1764||1767<=d&&d<=1768||1770<=d&&d<=1773||d==1809||1840<=d&&d<=1866||1958<=d&&d<=1968||2027<=d&&d<=2035||2070<=d&&d<=2073||2075<=d&&d<=2083||2085<=d&&d<=2087||2089<=d&&d<=2093||2137<=d&&d<=2139||2260<=d&&d<=2273||2275<=d&&d<=2306||d==2362||d==2364||2369<=d&&d<=2376||d==2381||2385<=d&&d<=2391||2402<=d&&d<=2403||d==2433||d==2492||d==2494||2497<=d&&d<=2500||d==2509||d==2519||2530<=d&&d<=2531||2561<=d&&d<=2562||d==2620||2625<=d&&d<=2626||2631<=d&&d<=2632||2635<=d&&d<=2637||d==2641||2672<=d&&d<=2673||d==2677||2689<=d&&d<=2690||d==2748||2753<=d&&d<=2757||2759<=d&&d<=2760||d==2765||2786<=d&&d<=2787||2810<=d&&d<=2815||d==2817||d==2876||d==2878||d==2879||2881<=d&&d<=2884||d==2893||d==2902||d==2903||2914<=d&&d<=2915||d==2946||d==3006|| Line truncated
`,end:t=>`::endgroup::
`}:HN.default.TRAVIS?{start:t=>`travis_fold:start:${t}
`,end:t=>`travis_fold:end:${t}
`}:HN.default.GITLAB?{start:t=>`section_start:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\W+/g,"_")}[collapsed=true]\r\x1B[0K${t}
`,end:t=>`section_end:${Math.floor(Date.now()/1e3)}:${t.toLowerCase().replace(/\W+/g,"_")}\r\x1B[0K`}:null,PIe=z0!==null,bIe=new Date,ept=["iTerm.app","Apple_Terminal","WarpTerminal","vscode"].includes(process.env.TERM_PROGRAM)||!!process.env.WT_SESSION,tpt=t=>t,jN=tpt({patrick:{date:[17,3],chars:["\u{1F340}","\u{1F331}"],size:40},simba:{date:[19,7],chars:["\u{1F981}","\u{1F334}"],size:40},jack:{date:[31,10],chars:["\u{1F383}","\u{1F987}"],size:40},hogsfather:{date:[31,12],chars:["\u{1F389}","\u{1F384}"],size:40},default:{chars:["=","-"],size:80}}),rpt=ept&&Object.keys(jN).find(t=>{let e=jN[t];return!(e.date&&(e.date[0]!==bIe.getDate()||e.date[1]!==bIe.getMonth()+1))})||"default";Wt=class extends jo{constructor({configuration:r,stdout:s,json:a=!1,forceSectionAlignment:n=!1,includeNames:l=!0,includePrefix:f=!0,includeFooter:h=!0,includeLogs:A=!a,includeInfos:m=A,includeWarnings:w=A}){super();this.uncommitted=new Set;this.warningCount=0;this.errorCount=0;this.timerFooter=[];this.startTime=Date.now();this.indent=0;this.level=0;this.progress=new Map;this.progressTime=0;this.progressFrame=0;this.progressTimeout=null;this.progressStyle=null;this.progressMaxScaledSize=null;if(YS(this,{configuration:r}),this.configuration=r,this.forceSectionAlignment=n,this.includeNames=l,this.includePrefix=f,this.includeFooter=h,this.includeInfos=m,this.includeWarnings=w,this.json=a,this.stdout=s,r.get("enableProgressBars")&&!a&&s.isTTY&&s.columns>22){let v=r.get("progressBarStyle")||rpt;if(!Object.hasOwn(jN,v))throw new Error("Assertion failed: Invalid progress bar style");this.progressStyle=jN[v];let D=Math.min(this.getRecommendedLength(),80);this.progressMaxScaledSize=Math.floor(this.progressStyle.size*D/80)}}static async start(r,s){let a=new this(r),n=process.emitWarning;process.emitWarning=(l,f)=>{if(typeof l!="string"){let A=l;l=A.message,f=f??A.name}let h=typeof f<"u"?`${f}: ${l}`:l;a.reportWarning(0,h)},r.includeVersion&&a.reportInfo(0,wy(r.configuration,`Yarn ${Fn}`,2));try{await s(a)}catch(l){a.reportExceptionOnce(l)}finally{await a.finalize(),process.emitWarning=n}return a}hasErrors(){return this.errorCount>0}exitCode(){return this.hasErrors()?1:0}getRecommendedLength(){let s=this.progressStyle!==null?this.stdout.columns-1:super.getRecommendedLength();return Math.max(40,s-12-this.indent*2)}startSectionSync({reportHeader:r,reportFooter:s,skipIfEmpty:a},n){let l={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(l):(l.action(),l.committed=!0);let f=Date.now();try{return n()}catch(h){throw this.reportExceptionOnce(h),h}finally{let h=Date.now();this.uncommitted.delete(l),l.committed&&s?.(h-f)}}async startSectionPromise({reportHeader:r,reportFooter:s,skipIfEmpty:a},n){let l={committed:!1,action:()=>{r?.()}};a?this.uncommitted.add(l):(l.action(),l.committed=!0);let f=Date.now();try{return await n()}catch(h){throw this.reportExceptionOnce(h),h}finally{let h=Date.now();this.uncommitted.delete(l),l.committed&&s?.(h-f)}}startTimerImpl(r,s,a){return{cb:typeof s=="function"?s:a,reportHeader:()=>{this.level+=1,this.reportInfo(null,`\u250C ${r}`),this.indent+=1,z0!==null&&!this.json&&this.includeInfos&&this.stdout.write(z0.start(r))},reportFooter:f=>{if(this.indent-=1,z0!==null&&!this.json&&this.includeInfos){this.stdout.write(z0.end(r));for(let h of this.timerFooter)h()}this.configuration.get("enableTimers")&&f>200?this.reportInfo(null,`\u2514 Completed in ${or(this.configuration,f,Ct.DURATION)}`):this.reportInfo(null,"\u2514 Completed"),this.level-=1},skipIfEmpty:(typeof s=="function"?{}:s).skipIfEmpty}}startTimerSync(r,s,a){let{cb:n,...l}=this.startTimerImpl(r,s,a);return this.startSectionSync(l,n)}async startTimerPromise(r,s,a){let{cb:n,...l}=this.startTimerImpl(r,s,a);return this.startSectionPromise(l,n)}reportSeparator(){this.indent===0?this.writeLine(""):this.reportInfo(null,"")}reportInfo(r,s){if(!this.includeInfos)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"",l=`${this.formatPrefix(n,"blueBright")}${s}`;this.json?this.reportJson({type:"info",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:s}):this.writeLine(l)}reportWarning(r,s){if(this.warningCount+=1,!this.includeWarnings)return;this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"";this.json?this.reportJson({type:"warning",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:s}):this.writeLine(`${this.formatPrefix(n,"yellowBright")}${s}`)}reportError(r,s){this.errorCount+=1,this.timerFooter.push(()=>this.reportErrorImpl(r,s)),this.reportErrorImpl(r,s)}reportErrorImpl(r,s){this.commit();let a=this.formatNameWithHyperlink(r),n=a?`${a}: `:"";this.json?this.reportJson({type:"error",name:r,displayName:this.formatName(r),indent:this.formatIndent(),data:s}):this.writeLine(`${this.formatPrefix(n,"redBright")}${s}`,{truncate:!1})}reportFold(r,s){if(!z0)return;let a=`${z0.start(r)}${s}${z0.end(r)}`;this.timerFooter.push(()=>this.stdout.write(a))}reportProgress(r){if(this.progressStyle===null)ret Line truncated
`),this.writeProgress()}writeLines(r,{truncate:s}={}){this.clearProgress({delta:r.length});for(let a of r)this.stdout.write(`${this.truncate(a,{truncate:s})}
`);this.writeProgress()}commit(){let r=this.uncommitted;this.uncommitted=new Set;for(let s of r)s.committed=!0,s.action()}clearProgress({delta:r=0,clear:s=!1}){this.progressStyle!==null&&this.progress.size+r>0&&(this.stdout.write(`\x1B[${this.progress.size+r}A`),(r>0||s)&&this.stdout.write("\x1B[0J"))}writeProgress(){if(this.progressStyle===null||(this.progressTimeout!==null&&clearTimeout(this.progressTimeout),this.progressTimeout=null,this.progress.size===0))return;let r=Date.now();r-this.progressTime>SIe&&(this.progressFrame=(this.progressFrame+1)%vIe.length,this.progressTime=r);let s=vIe[this.progressFrame];for(let a of this.progress.values()){let n="";if(typeof a.lastScaledSize<"u"){let A=this.progressStyle.chars[0].repeat(a.lastScaledSize),m=this.progressStyle.chars[1].repeat(this.progressMaxScaledSize-a.lastScaledSize);n=` ${A}${m}`}let l=this.formatName(null),f=l?`${l}: `:"",h=a.definition.title?` ${a.definition.title}`:"";this.stdout.write(`${or(this.configuration,"\u27A4","blueBright")} ${f}${s}${n}${h}
`)}this.progressTimeout=setTimeout(()=>{this.refreshProgress({force:!0})},SIe)}refreshProgress({delta:r=0,force:s=!1}={}){let a=!1,n=!1;if(s||this.progress.size===0)a=!0;else for(let l of this.progress.values()){let f=typeof l.definition.progress<"u"?Math.trunc(this.progressMaxScaledSize*l.definition.progress):void 0,h=l.lastScaledSize;l.lastScaledSize=f;let A=l.lastTitle;if(l.lastTitle=l.definition.title,f!==h||(n=A!==l.definition.title)){a=!0;break}}a&&(this.clearProgress({delta:r,clear:n}),this.writeProgress())}truncate(r,{truncate:s}={}){return this.progressStyle===null&&(s=!1),typeof s>"u"&&(s=this.configuration.get("preferTruncatedLines")),s&&(r=(0,DIe.default)(r,0,this.stdout.columns-1)),r}formatName(r){return this.includeNames?xIe(r,{configuration:this.configuration,json:this.json}):""}formatPrefix(r,s){return this.includePrefix?`${or(this.configuration,"\u27A4",s)} ${r}${this.formatIndent()}`:""}formatNameWithHyperlink(r){return this.includeNames?e7(r,{configuration:this.configuration,json:this.json}):""}formatIndent(){return this.level>0||!this.forceSectionAlignment?"\u2502 ".repeat(this.indent):`${$At} `}}});var qn={};lr(qn,{PackageManager:()=>RIe,detectPackageManager:()=>TIe,executePackageAccessibleBinary:()=>LIe,executePackageScript:()=>GN,executePackageShellcode:()=>t7,executeWorkspaceAccessibleBinary:()=>lpt,executeWorkspaceLifecycleScript:()=>NIe,executeWorkspaceScript:()=>FIe,getPackageAccessibleBinaries:()=>qN,getWorkspaceAccessibleBinaries:()=>OIe,hasPackageScript:()=>opt,hasWorkspaceScript:()=>r7,isNodeScript:()=>n7,makeScriptEnv:()=>Nb,maybeExecuteWorkspaceLifecycleScript:()=>cpt,prepareExternalProject:()=>spt});async function J0(t,e,r,s=[]){if(process.platform==="win32"){let a=`@goto #_undefined_# 2>NUL || @title %COMSPEC% & @setlocal & @"${r}" ${s.map(n=>`"${n.replace('"','""')}"`).join(" ")} %*`;await fe.writeFilePromise(Y.format({dir:t,name:e,ext:".cmd"}),a)}await fe.writeFilePromise(Y.join(t,e),`#!/bin/sh
exec "${r}" ${s.map(a=>`'${a.replace(/'/g,`'"'"'`)}'`).join(" ")} "$@"
`,{mode:493})}async function TIe(t){let e=await nr.tryFind(t);if(e?.packageManager){let s=NF(e.packageManager);if(s?.name){let a=`found ${JSON.stringify({packageManager:e.packageManager})} in manifest`,[n]=s.reference.split(".");switch(s.name){case"yarn":return{packageManagerField:!0,packageManager:Number(n)===1?"Yarn Classic":"Yarn",reason:a};case"npm":return{packageManagerField:!0,packageManager:"npm",reason:a};case"pnpm":return{packageManagerField:!0,packageManager:"pnpm",reason:a}}}}let r;try{r=await fe.readFilePromise(Y.join(t,Or.lockfile),"utf8")}catch{}return r!==void 0?r.match(/^__metadata:$/m)?{packageManager:"Yarn",reason:'"__metadata" key found in yarn.lock'}:{packageManager:"Yarn Classic",reason:'"__metadata" key not found in yarn.lock, must be a Yarn classic lockfile'}:fe.existsSync(Y.join(t,"package-lock.json"))?{packageManager:"npm",reason:`found npm's "package-lock.json" lockfile`}:fe.existsSync(Y.join(t,"pnpm-lock.yaml"))?{packageManager:"pnpm",reason:`found pnpm's "pnpm-lock.yaml" lockfile`}:null}async function Nb({project:t,locator:e,binFolder:r,ignoreCorepack:s,lifecycleScript:a,baseEnv:n=t?.configuration.env??process.env}){let l={};for(let[m,w]of Object.entries(n))typeof w<"u"&&(l[m.toLowerCase()!=="path"?m:"PATH"]=w);let f=me.fromPortablePath(r);l.BERRY_BIN_FOLDER=me.fromPortablePath(f);let h=process.env.COREPACK_ROOT&&!s?me.join(process.env.COREPACK_ROOT,"dist/yarn.js"):process.argv[1];if(await Promise.all([J0(r,"node",process.execPath),...Fn!==null?[J0(r,"run",process.execPath,[h,"run"]),J0(r,"yarn",process.execPath,[h]),J0(r,"yarnpkg",process.execPath,[h]),J0(r,"node-gyp",process.execPath,[h,"run","--top-level","node-gyp"])]:[]]),t&&(l.INIT_CWD=me.fromPortablePath(t.configuration.startingCwd),l.PROJECT_CWD=me.fromPortablePath(t.cwd)),l.PATH=l.PATH?`${f}${me.delimiter}${l.PATH}`:`${f}`,l.npm_execpath=`${f}${me.sep}yarn`,l.npm_node_execpath=`${f}${me.sep}node`,e){if(!t)throw new Error("Assertion failed: Missing project");let m=t.tryWorkspaceByLocator(e),w=m?m.manifest.version??"":t.storedPackages.get(e.locatorHash).version??"";l.npm_package_name=Qn(e),l.npm_package_version=w;let v;if(m)v=m.cwd;else{let D=t.storedPackages.get(e.locatorHash);if(!D)throw new Error(`Package for ${hn(t.configuration,e)} not found in the project`);let I=t.configuration.getLinkers(),R={project:t,report:new Wt({stdout:new Z0.PassThrough,configuration:t.configuration})},N=I.find(U=>U.supportsPackage(D,R));if(!N)throw new Error(`The package ${hn(t.configuration,D)} isn't supported by any of the available linkers`);v=await N.findPackageLocation(D,R)}l.npm_package_json=me.fromPortablePath(Y.join(v,Or.manifest))}let A=Fn!==null?`yarn/${Fn}`:`yarn/${Qp("@yarnpkg/core").version}-core`;return l.npm_config_user_agent=`${A} npm/? node/${process.version} ${process.platform} ${process.arch}`,a&&(l.npm_lifecycle_event=a),t&&await t.configuration.triggerHook(m=>m.setupScriptEnvironment,t,l,async(m,w,v)=>await J0(r,m,w,v)),l}async function spt(t,e,{configuration:r,report:s,workspace:a=null,locator:n=null}){await ipt(async()=>{await fe.mktempPromise(async l=>{let f=Y.join(l,"pack.log"),h=null,{stdout:A,stderr:m}=r.getSubprocessStreams(f,{prefix:me.fromPortablePath(t),report:s}),w=n&&kf(n)?Ww(n):n,v=w?qc(w):"an external project";A.write(`Packing ${v} from sources
`);let D=await TIe(t),I;D!==null?(A.write(`Using ${D.packageManager} for bootstrap. Reason: ${D.reason}
`),I=D.packageManager):(A.write(`No package manager configuration detected; defaulting to Yarn
`),I="Yarn");let R=I==="Yarn"&&!D?.packageManagerField;await fe.mktempPromise(async N=>{let U=await Nb({binFolder:N,ignoreCorepack:R,baseEnv:{...process.env,COREPACK_ENABLE_AUTO_PIN:"0"}}),ee=new Map([["Yarn Classic",async()=>{let ie=a!==null?["workspace",a]:[],ae=Y.join(t,Or.manifest),ge=await fe.readFilePromise(ae),de=await Tf(process.execPath,[process.argv[1],"set","version","classic","--only-if-needed","--yarn-path"],{cwd:t,env:U,stdin:h,stdout:A,stderr:m,end:1});if(de.code!==0)return de.code;await fe.writeFilePromise(ae,ge),await fe.appendFilePromise(Y.join(t,".npmignore"),`/.yarn
`),A.write(`
`),delete U.NODE_ENV;let xe=await Tf("yarn",["install"],{cwd:t,env:U,stdin:h,stdout:A,stderr:m,end:1});if(xe.code!==0)return xe.code;A.write(`
`);let we=await Tf("yarn",[...ie,"pack","--filename",me.fromPortablePath(e)],{cwd:t,env:U,stdin:h,stdout:A,stderr:m});return we.code!==0?we.code:0}],["Yarn",async()=>{let ie=a!==null?["workspace",a]:[];U.YARN_ENABLE_INLINE_BUILDS="1";let ae=Y.join(t,Or.lockfile);await fe.existsPromise(ae)||await fe.writeFilePromise(ae,"");let ge=await Tf("yarn",[...ie,"pack","--install-if-needed","--filename",me.fromPortablePath(e)],{cwd:t,env:U,stdin:h,stdout:A,stderr:m});return ge.code!==0?ge.code:0}],["npm",async()=>{if(a!==null){let be=new Z0.PassThrough,Ce=Nw(be);be.pipe(A,{end:!1});let Ee=await Tf("npm",["--version"],{cwd:t,env:U,stdin:h,stdout:be,stderr:m,end:0});if(be.end(),Ee.code!==0)return A.end(),m.end(),Ee.code;let he=(await Ce).toString().trim();if(!Wh(he,">=7.x")){let $=ic(null,"npm"),De=oi($,he),Te=oi($,">=7.x");throw new Error(`Workspaces aren't supported by ${xi(r,De)}; please upgrade to ${xi(r,Te)} (npm has been detected as the primary package manager for ${or(r,t,Ct.PATH)})`)}}let ie=a!==null?["--workspace",a]:[];delete U.npm_config_user_agent,delete U.npm_config_production,delete U.NPM_CONFIG_PRODUCTION,delete U.NODE_ENV;let ae=await Tf("npm",["install","--legacy-peer-deps"],{cwd:t,env:U,stdin:h,stdout:A,stderr:m,end:1});if(ae.code!==0)return ae.code;let ge=new Z0.PassThrough,de=Nw(ge);ge.pipe(A);let xe=await Tf("npm",["pack","--silent",...ie],{cwd:t,env:U,stdin:h,stdout:ge,stderr:m});if(xe.code!==0)return xe.code;let we=(await de).toString().trim().replace(/^.*\n/s,""),d=Y.resolve(t,me.toPortablePath(we));return await fe.renamePromise(d,e),0}]]).get(I);if(typeof ee>"u")throw new Error("Assertion failed: Unsupported workflow");let te=await ee();if(!(te===0||typeof te>"u"))throw fe.detachTemp(l),new Zt(58,`Packing the package failed (exit code ${te}, logs can be found here: ${or(r,f,Ct.PATH)})`)})})})}async function opt(t,e,{project:r}){let s=r.tryWorkspaceByLocator(t);if(s!==null)return r7(s,e);let a=r.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${hn(r.configuration,t)} not found in the project`);return await Yh.openPromise(async n=>{let l=r.configuration,f=r.configuration.getLinkers(),h={project:r,report:new Wt({stdout:new Z0.PassThrough,configuration:l})},A=f.find(D=>D.supportsPackage(a,h));if(!A)throw new Error(`The package ${hn(r.configuration,a)} isn't supported by any of the available linkers`);let m=await A.findPackageLocation(a,h),w=new Jn(m,{baseFs:n});return(await nr.find(Rt.dot,{baseFs:w})).scripts.has(e)})}async function GN(t,e,r,{cwd:s,project:a,stdin:n,stdout:l,stderr:f}){return await fe.mktempPromise(async h=>{let{manifest:A,env:m,cwd:w}=await QIe(t,{project:a,binFolder:h,cwd:s,lifecycleScript:e}),v=A.scripts.get(e);if(typeof v>"u")return 1;let D=async()=>await pC(v,r,{cwd:w,env:m,stdin:n,stdout:l,stderr:f});return await(await a.configuration.reduceHook(R=>R.wrapScriptExecution,D,a,t,e,{script:v,args:r,cwd:w,env:m,stdin:n,stdout:l,stderr:f}))()})}async function t7(t,e,r,{cwd:s,project:a,stdin:n,stdout:l,stderr:f}){return await fe.mktempPromise(async h=>{let{env:A,cwd:m}=await QIe(t,{project:a,binFolder:h,cwd:s});return await pC(e,r,{cwd:m,env:A,stdin:n,stdout:l,stderr:f})})}async function apt(t,{binFolder:e,cwd:r,lifecycleScript:s}){let a=await Nb({project:t.project,locator:t.anchoredLocator,binFolder:e,lifecycleScript:s});return await i7(e,await OIe(t)),typeof r>"u"&&(r=Y.dirname(await fe.realpathPromise(Y.join(t.cwd,"package.json")))),{manifest:t.manifest,binFolder:e,env:a,cwd:r}}async function QIe(t,{project:e,binFolder:r,cwd:s,lifecycleScript:a}){let n=e.tryWorkspaceByLocator(t);if(n!==null)return apt(n,{binFolder:r,cwd:s,lifecycleScript:a});let l=e.storedPackages.get(t.locatorHash);if(!l)throw new Error(`Package for ${hn(e.configuration,t)} not found in the project`);return await Yh.openPromise(async f=>{let h=e.configuration,A=e.configuration.getLinkers(),m={project:e,report:new Wt({stdout:new Z0.PassThrough,configuration:h})},w=A.find(N=>N.supportsPackage(l,m));if(!w)throw new Error(`The package ${hn(e.configuration,l)} isn't supported by any of the available linkers`);let v=await Nb({project:e,locator:t,binFolder:r,lifecycleScript:a});await i7(r,await qN(t,{project:e}));let D=await w.findPackageLocation(l,m),I=new Jn(D,{baseFs:f}),R=await nr.find(Rt.dot,{baseFs:I});return typeof s>"u"&&(s=D),{manifest:R,binFolder:r,env:v,cwd:s}})}async function FIe(t,e,r,{cwd:s,stdin:a,stdout:n,stderr:l}){return await GN(t.anchoredLocator,e,r,{cwd:s,project:t.project,stdin:a,stdout:n,stderr:l})}function r7(t,e){return t.manifest.scripts.has(e)}async function NIe(t,e,{cwd:r,report:s}){let{configuration:a}=t.project,n=null;await fe.mktempPromise(async l=>{let f=Y.join(l,`${e}.log`),h=`# This file contains the result of Yarn calling the "${e}" lifecycle script inside a workspace ("${me.fromPortablePath(t.cwd)}")
`,{stdout:A,stderr:m}=a.getSubprocessStreams(f,{report:s,prefix:hn(a,t.anchoredLocator),header:h});s.reportInfo(36,`Calling the "${e}" lifecycle script`);let w=await FIe(t,e,[],{cwd:r,stdin:n,stdout:A,stderr:m});if(A.end(),m.end(),w!==0)throw fe.detachTemp(l),new Zt(36,`${HS(e)} script failed (exit code ${or(a,w,Ct.NUMBER)}, logs can be found here: ${or(a,f,Ct.PATH)}); run ${or(a,`yarn ${e}`,Ct.CODE)} to investigate`)})}async function cpt(t,e,r){r7(t,e)&&await NIe(t,e,r)}function n7(t){let e=Y.extname(t);if(e.match(/\.[cm]?[jt]sx?$/))return!0;if(e===".exe"||e===".bin")return!1;let r=Buffer.alloc(4),s;try{s=fe.openSync(t,"r")}catch{return!0}try{fe.readSync(s,r,0,r.length,0)}finally{fe.closeSync(s)}let a=r.readUint32BE();return!(a===3405691582||a===3489328638||a===2135247942||(a&4294901760)===1297743872)}async function qN(t,{project:e}){let r=e.configuration,s=new Map,a=e.storedPackages.get(t.locatorHash);if(!a)throw new Error(`Package for ${hn(r,t)} not found in the project`);let n=new Z0.Writable,l=r.getLinkers(),f={project:e,report:new Wt({configuration:r,stdout:n})},h=new Set([t.locatorHash]);for(let m of a.dependencies.values()){let w=e.storedResolutions.get(m.descriptorHash);if(!w)throw new Error(`Assertion failed: The resolution (${xi(r,m)}) should have been registered`);h.add(w)}let A=await Promise.all(Array.from(h,async m=>{let w=e.storedPackages.get(m);if(!w)throw new Error(`Assertion failed: The package (${m}) should have been registered`);if(w.bin.size===0)return kl.skip;let v=l.find(I=>I.supportsPackage(w,f));if(!v)return kl.skip;let D=null;try{D=await v.findPackageLocation(w,f)}catch(I){if(I.code==="LOCATOR_NOT_INSTALLED")return kl.skip;throw I}return{dependency:w,packageLocation:D}}));for(let m of A){if(m===kl.skip)continue;let{dependency:w,packageLocation:v}=m;for(let[D,I]of w.bin){let R=Y.resolve(v,I);s.set(D,[w,me.fromPortablePath(R),n7(R)])}}return s}async function OIe(t){return await qN(t.anchoredLocator,{project:t.project})}async function i7(t,e){await Promise.all(Array.from(e,([r,[,s,a]])=>a?J0(t,r,process.execPath,[s]):J0(t,r,s,[])))}async function LIe(t,e,r,{cwd:s,project:a,stdin:n,stdout:l,stderr:f,nodeArgs:h=[],packageAccessibleBinaries:A}){A??=await qN(t,{project:a});let m=A.get(e);if(!m)throw new Error(`Binary not found (${e}) for ${hn(a.configuration,t)}`);return await fe.mktempPromise(async w=>{let[,v]=m,D=await Nb({project:a,locator:t,binFolder:w});await i7(D.BERRY_BIN_FOLDER,A);let I=n7(me.toPortablePath(v))?Tf(process.execPath,[...h,v,...r],{cwd:s,env:D,stdin:n,stdout:l,stderr:f}):Tf(v,r,{cwd:s,env:D,stdin:n,stdout:l,stderr:f}),R;try{R=await I}finally{await fe.removePromise(D.BERRY_BIN_FOLDER)}return R.code})}async function lpt(t,e,r,{cwd:s,stdin:a,stdout:n,stderr:l,packageAccessibleBinaries:f}){return await LIe(t.anchoredLocator,e,r,{project:t.project,cwd:s,stdin:a,stdout:n,stderr:l,packageAccessibleBinaries:f})}var kIe,Z0,RIe,npt,ipt,s7=tt(()=>{Mt();Mt();Kh();Pb();xl();kIe=st(hy()),Z0=Ae("stream");Jw();mu();Fb();Qb();CN();pu();Au();_p();Ea();RIe=(a=>(a.Yarn1="Yarn Classic",a.Yarn2="Yarn",a.Npm="npm",a.Pnpm="pnpm",a))(RIe||{});npt=2,ipt=(0,kIe.default)(npt)});function Cdt(t,e,r){let s=e,a=e?e.next:t.head,n=new lV(r,s,a,t);return n.next===void 0&&(t.tail=n),n.prev===void 0&&(t.head=n),t.length++,n}function Bdt(t,e){t.tail=new lV(e,t.tail,void 0,t),t.head||(t.head=t.tail),t.length++}function vdt(t,e){t.head=new lV(e,void 0,t.head,t),t.tail||(t.tail=t.head),t.length++}var pwe,lc,IO,tV,dwe,nV,Wy,CO,ywe,gO,og,jIe,Ewe,Vy,Swe,nD,Of,L7,kwe,V7,fV,Owe,hV,Vn,Us,AV,oD,SC,Yc,Hwe,iD,pV,Wc,gV,upt,fpt,_Ie,hpt,Apt,ppt,Vp,Wp,X0,VN,Ob,WN,MIe,YN,UIe,Qf,gC,yo,Lb,IC,Eo,cc,Io,o7,KN,Ba,Ss,a7,c7,HIe,l7,Jh,u7,zN,_b,Oy,Fl,Mb,dpt,gpt,mpt,ypt,gwe,Ept,Ipt,wpt,Zy,Cpt,cg,_f,Ub,di,f7,Jp,h7,Q7,F7,Jb,JN,vC,bC,A7,wC,lg,Lf,rg,Zh,CC,p7,zp,Hb,d7,sO,Ly,oO,Yy,rV,Bpt,wO,mwe,vpt,Spt,bpt,Dpt,Ppt,xpt,kpt,iV,sD,Rpt,eA,Tpt,GIe,Qpt,g7,Ky,ZN,m7,sV,Iwe,Fpt,Npt,wwe,Opt,Lpt,Cwe,_pt,Mpt,Upt,Hpt,jpt,Gpt,qpt,Vpt,Bwe,vwe,Wpt,aO,Ypt,BO,oV,zy,Kpt,_y,y7,zpt,ng,Jpt,Zpt,Xpt,ig,$pt,edt,tdt,E7,rdt,My,mO,ndt,idt,sdt,odt,xn,Dwe,vO,adt,N7,O7,cdt,Cu,Uy,Yp,I7,qIe,Xh,jb,$0,VIe,qi,Kp,eg,w7,Hy,Ms,XN,$N,C7,WIe,YIe,Gb,B7,eO,mC,tg,tO,jy,rO,nO,KIe,ldt,Jy,Zb,udt,Pwe,fdt,hdt,SO,xwe,Adt,zIe,aV,bO,cV,pdt,ddt,JIe,gdt,Rwe,mdt,ZIe,XIe,$Ie,_7,ewe,qb,cO,M7,lO,U7,H7,j7,G7,sg,yO,q7,v7,$h,Twe,ydt,Edt,Idt,wdt,lV,twe,rwe,uO,Vb,Ff,Gy,qy,Wb,S7,Nf,b7,fO,nwe,W7,Y7,hO,AO,iwe,D7,pO,Qwe,P7,DO,uV,Sdt,bdt,Fwe,Nwe,Ddt,Pdt,M$t,xdt,kdt,Rdt,Tdt,Qdt,Lwe,Fdt,Ndt,Odt,_we,K7,EO,Ldt,Mwe,_dt,Uwe,jwe,PO,Mdt,Udt,z7,Gwe,Hdt,jdt,x7,swe,yC,Gdt,qdt,Vdt,Wdt,Ydt,Kdt,owe,J7,awe,Z7,Bu,X7,$7,dO,cwe,lwe,zb,uwe,fwe,k7,ag,wo,iO,hwe,EC,R7,T7,eV,Xb,$b,eD,tD,zdt,rD,Jdt,Zdt,Xdt,Awe,dV,Yb,qwe,$dt,e0t,U$t,t0t,r0t,n0t,i0t,s0t,Kb,H$t,o0t,Vwe=tt(()=>{pwe=st(Ae("events"),1),lc=st(Ae("fs"),1),IO=Ae("node:events"),tV=st(Ae("node:stream"),1),dwe=Ae("node:string_decoder"),nV=st(Ae("node:path"),1),Wy=st(Ae("node:fs"),1),CO=Ae("path"),ywe=Ae("events"),gO=st(Ae("assert"),1),og=Ae("buffer"),jIe=st(Ae("zlib"),1), Line truncated
`,n=Buffer.byteLength(a),l=Math.floor(Math.log(n)/Math.log(10))+1;return n+l>=Math.pow(10,l)&&(l+=1),l+n+a}static parse(e,r,s=!1){return new bwe(ndt(idt(e),r),s)}},ndt=(t,e)=>e?Object.assign({},e,t):t,idt=t=>t.replace(/\n$/,"").split(`
`).reduce(sdt,Object.create(null)),sdt=(t,e)=>{let r=parseInt(e,10);if(r!==Buffer.byteLength(e)+1)return t;e=e.slice((r+" ").length);let s=e.split("="),a=s.shift();if(!a)return t;let n=a.replace(/^SCHILY\.(dev|ino|nlink)/,"$1"),l=s.join("=");return t[n]=/^([A-Z]+\.)?([mac]|birth|creation)time$/.test(n)?new Date(Number(l)*1e3):/^[0-9]+$/.test(l)?+l:l,t},odt=process.env.TESTING_TAR_FAKE_PLATFORM||process.platform,xn=odt!=="win32"?t=>t:t=>t&&t.replace(/\\/g,"/"),Dwe=class extends Zy{extended;globalExtended;header;startBlockSize;blockRemain;remain;type;meta=!1;ignore=!1;path;mode;uid;gid;uname;gname;size=0;mtime;atime;ctime;linkpath;dev;ino;nlink;invalid=!1;absolute;unsupported=!1;constructor(t,e,r){switch(super({}),this.pause(),this.extended=e,this.globalExtended=r,this.header=t,this.remain=t.size??0,this.startBlockSize=512*Math.ceil(this.remain/512),this.blockRemain=this.startBlockSize,this.type=t.type,this.type){case"File":case"OldFile":case"Link":case"SymbolicLink":case"CharacterDevice":case"BlockDevice":case"Directory":case"FIFO":case"ContiguousFile":case"GNUDumpDir":break;case"NextFileHasLongLinkpath":case"NextFileHasLongPath":case"OldGnuLongPath":case"GlobalExtendedHeader":case"ExtendedHeader":case"OldExtendedHeader":this.meta=!0;break;default:this.ignore=!0}if(!t.path)throw new Error("no path provided for tar.ReadEntry");this.path=xn(t.path),this.mode=t.mode,this.mode&&(this.mode=this.mode&4095),this.uid=t.uid,this.gid=t.gid,this.uname=t.uname,this.gname=t.gname,this.size=this.remain,this.mtime=t.mtime,this.atime=t.atime,this.ctime=t.ctime,this.linkpath=t.linkpath?xn(t.linkpath):void 0,this.uname=t.uname,this.gname=t.gname,e&&this.#e(e),r&&this.#e(r,!0)}write(t){let e=t.length;if(e>this.blockRemain)throw new Error("writing more to entry than is appropriate");let r=this.remain,s=this.blockRemain;return this.remain=Math.max(0,r-e),this.blockRemain=Math.max(0,s-e),this.ignore?!0:r>=e?super.write(t):super.write(t.subarray(0,r))}#e(t,e=!1){t.path&&(t.path=xn(t.path)),t.linkpath&&(t.linkpath=xn(t.linkpath)),Object.assign(this,Object.fromEntries(Object.entries(t).filter(([r,s])=>!(s==null||r==="path"&&e))))}},vO=(t,e,r,s={})=>{t.file&&(s.file=t.file),t.cwd&&(s.cwd=t.cwd),s.code=r instanceof Error&&r.code||e,s.tarCode=e,!t.strict&&s.recoverable!==!1?(r instanceof Error&&(s=Object.assign(r,s),r=r.message),t.emit("warn",e,r,s)):r instanceof Error?t.emit("error",Object.assign(r,s)):t.emit("error",Object.assign(new Error(`${e}: ${r}`),s))},adt=1024*1024,N7=Buffer.from([31,139]),O7=Buffer.from([40,181,47,253]),cdt=Math.max(N7.length,O7.length),Cu=Symbol("state"),Uy=Symbol("writeEntry"),Yp=Symbol("readEntry"),I7=Symbol("nextEntry"),qIe=Symbol("processEntry"),Xh=Symbol("extendedHeader"),jb=Symbol("globalExtendedHeader"),$0=Symbol("meta"),VIe=Symbol("emitMeta"),qi=Symbol("buffer"),Kp=Symbol("queue"),eg=Symbol("ended"),w7=Symbol("emittedEnd"),Hy=Symbol("emit"),Ms=Symbol("unzip"),XN=Symbol("consumeChunk"),$N=Symbol("consumeChunkSub"),C7=Symbol("consumeBody"),WIe=Symbol("consumeMeta"),YIe=Symbol("consumeHeader"),Gb=Symbol("consuming"),B7=Symbol("bufferConcat"),eO=Symbol("maybeEnd"),mC=Symbol("writing"),tg=Symbol("aborted"),tO=Symbol("onDone"),jy=Symbol("sawValidEntry"),rO=Symbol("sawNullBlock"),nO=Symbol("sawEOF"),KIe=Symbol("closeStream"),ldt=()=>!0,Jy=class extends ywe.EventEmitter{file;strict;maxMetaEntrySize;filter;brotli;zstd;writable=!0;readable=!1;[Kp]=[];[qi];[Yp];[Uy];[Cu]="begin";[$0]="";[Xh];[jb];[eg]=!1;[Ms];[tg]=!1;[jy];[rO]=!1;[nO]=!1;[mC]=!1;[Gb]=!1;[w7]=!1;constructor(t={}){super(),this.file=t.file||"",this.on(tO,()=>{(this[Cu]==="begin"||this[jy]===!1)&&this.warn("TAR_BAD_ARCHIVE","Unrecognized archive format")}),t.ondone?this.on(tO,t.ondone):this.on(tO,()=>{this.emit("prefinish"),this.emit("finish"),this.emit("end")}),this.strict=!!t.strict,this.maxMetaEntrySize=t.maxMetaEntrySize||adt,this.filter=typeof t.filter=="function"?t.filter:ldt;let e=t.file&&(t.file.endsWith(".tar.br")||t.file.endsWith(".tbr"));this.brotli=!(t.gzip||t.zstd)&&t.brotli!==void 0?t.brotli:e?void 0:!1;let r=t.file&&(t.file.endsWith(".tar.zst")||t.file.endsWith(".tzst"));this.zstd=!(t.gzip||t.brotli)&&t.zstd!==void 0?t.zstd:r?!0:void 0,this.on("end",()=>this[KIe]()),typeof t.onwarn=="function"&&this.on("warn",t.onwarn),typeof t.onReadEntry=="function"&&this.on("entry",t.onReadEntry)}warn(t,e,r={}){vO(this,t,e,r)}[YIe](t,e){this[jy]===void 0&&(this[jy]=!1);let r;try{r=new zy(t,e,this[Xh],this[jb])}catch(s){return this.warn("TAR_ENTRY_INVALID",s)}if(r.nullBlock)this[rO]?(this[nO]=!0,this[Cu]==="begin"&&(this[Cu]="header"),this[Hy]("eof")):(this[rO]=!0,this[Hy]("nullBlock"));else if(this[rO]=!1,!r.cksumValid)this.warn("TAR_ENTRY_INVALID","checksum failure",{header:r});else if(!r.path)this.warn("TAR_ENTRY_INVALID","path is required",{header:r});else{let s=r.type;if(/^(Symbolic)?Link$/.test(s)&&!r.linkpath)this.warn("TAR_ENTRY_INVALID","linkpath required",{header:r});else if(!/^(Symbolic)?Link$/.test(s)&&!/^(Global)?ExtendedHeader$/.test Line truncated
`}),f},s})});var bs={};lr(bs,{emitList:()=>A0t,emitTree:()=>oCe,treeNodeToJson:()=>sCe,treeNodeToTreeify:()=>iCe});function iCe(t,{configuration:e}){let r={},s=0,a=(n,l)=>{let f=Array.isArray(n)?n.entries():Object.entries(n);for(let[h,A]of f){if(!A)continue;let{label:m,value:w,children:v}=A,D=[];typeof m<"u"&&D.push(wy(e,m,2)),typeof w<"u"&&D.push(or(e,w[0],w[1])),D.length===0&&D.push(wy(e,`${h}`,2));let I=D.join(": ").trim(),R=`\0${s++}\0`,N=l[`${R}${I}`]={};typeof v<"u"&&a(v,N)}};if(typeof t.children>"u")throw new Error("The root node must only contain children");return a(t.children,r),r}function sCe(t){let e=r=>{if(typeof r.children>"u"){if(typeof r.value>"u")throw new Error("Assertion failed: Expected a value to be set if the children are missing");return Cy(r.value[0],r.value[1])}let s=Array.isArray(r.children)?r.children.entries():Object.entries(r.children??{}),a=Array.isArray(r.children)?[]:{};for(let[n,l]of s)l&&(a[p0t(n)]=e(l));return typeof r.value>"u"?a:{value:Cy(r.value[0],r.value[1]),children:a}};return e(t)}function A0t(t,{configuration:e,stdout:r,json:s}){let a=t.map(n=>({value:n}));oCe({children:a},{configuration:e,stdout:r,json:s})}function oCe(t,{configuration:e,stdout:r,json:s,separators:a=0}){if(s){let l=Array.isArray(t.children)?t.children.values():Object.values(t.children??{});for(let f of l)f&&r.write(`${JSON.stringify(sCe(f))}
`);return}let n=(0,nCe.asTree)(iCe(t,{configuration:e}),!1,!1);if(n=n.replace(/\0[0-9]+\0/g,""),a>=1&&(n=n.replace(/^([├└]─)/gm,`\u2502
$1`).replace(/^│\n/,"")),a>=2)for(let l=0;l<2;++l)n=n.replace(/^([│ ].{2}[├│ ].{2}[^\n]+\n)(([│ ]).{2}[├└].{2}[^\n]*\n[│ ].{2}[│ ].{2}[├└]─)/gm,`$1$3 \u2502
$2`).replace(/^│\n/,"");if(a>=3)throw new Error("Only the first two levels are accepted by treeUtils.emitTree");r.write(n)}function p0t(t){return typeof t=="string"?t.replace(/^\0[0-9]+\0/,""):t}var nCe,aCe=tt(()=>{nCe=st(rCe());pu()});var xO,cCe=tt(()=>{xO=class{constructor(e){this.releaseFunction=e;this.map=new Map}addOrCreate(e,r){let s=this.map.get(e);if(typeof s<"u"){if(s.refCount<=0)throw new Error(`Race condition in RefCountedMap. While adding a new key the refCount is: ${s.refCount} for ${JSON.stringify(e)}`);return s.refCount++,{value:s.value,release:()=>this.release(e)}}else{let a=r();return this.map.set(e,{refCount:1,value:a}),{value:a,release:()=>this.release(e)}}}release(e){let r=this.map.get(e);if(!r)throw new Error(`Unbalanced calls to release. No known instances of: ${JSON.stringify(e)}`);let s=r.refCount;if(s<=0)throw new Error(`Unbalanced calls to release. Too many release vs alloc refcount would become: ${s-1} of ${JSON.stringify(e)}`);s==1?(this.map.delete(e),this.releaseFunction(r.value)):r.refCount--}}});function lD(t){let e=t.match(d0t);if(!e?.groups)throw new Error("Assertion failed: Expected the checksum to match the requested pattern");let r=e.groups.cacheVersion?parseInt(e.groups.cacheVersion):null;return{cacheKey:e.groups.cacheKey??null,cacheVersion:r,cacheSpec:e.groups.cacheSpec??null,hash:e.groups.hash}}var lCe,BV,vV,kO,gn,d0t,SV=tt(()=>{We();Mt();Mt();Kh();lCe=Ae("crypto"),BV=st(Ae("fs"));cCe();mu();G0();Au();Ea();vV=Ow(process.env.YARN_CACHE_CHECKPOINT_OVERRIDE??process.env.YARN_CACHE_VERSION_OVERRIDE??9),kO=Ow(process.env.YARN_CACHE_VERSION_OVERRIDE??10),gn=class t{constructor(e,{configuration:r,immutable:s=r.get("enableImmutableCache"),check:a=!1}){this.markedFiles=new Set;this.mutexes=new Map;this.refCountedZipFsCache=new xO(e=>{e.discardAndClose()});this.cacheId=`-${(0,lCe.randomBytes)(8).toString("hex")}.tmp`;this.configuration=r,this.cwd=e,this.immutable=s,this.check=a;let{cacheSpec:n,cacheKey:l}=t.getCacheKey(r);this.cacheSpec=n,this.cacheKey=l}static async find(e,{immutable:r,check:s}={}){let a=new t(e.get("cacheFolder"),{configuration:e,immutable:r,check:s});return await a.setup(),a}static getCacheKey(e){let r=e.get("compressionLevel"),s=r!=="mixed"?`c${r}`:"";return{cacheKey:[kO,s].join(""),cacheSpec:s}}get mirrorCwd(){if(!this.configuration.get("enableMirror"))return null;let e=`${this.configuration.get("globalFolder")}/cache`;return e!==this.cwd?e:null}getVersionFilename(e){return`${Yw(e)}-${this.cacheKey}.zip`}getChecksumFilename(e,r){let a=lD(r).hash.slice(0,10);return`${Yw(e)}-${a}.zip`}isChecksumCompatible(e){if(e===null)return!1;let{cacheVersion:r,cacheSpec:s}=lD(e);if(r===null||r<vV)return!1;let a=this.configuration.get("cacheMigrationMode");return!(r<kO&&a==="always"||s!==this.cacheSpec&&a!=="required-only")}getLocatorPath(e,r){return this.mirrorCwd===null?Y.resolve(this.cwd,this.getVersionFilename(e)):r===null?Y.resolve(this.cwd,this.getVersionFilename(e)):Y.resolve(this.cwd,this.getChecksumFilename(e,r))}getLocatorMirrorPath(e){let r=this.mirrorCwd;return r!==null?Y.resolve(r,this.getVersionFilename(e)):null}async setup(){if(!this.configuration.get("enableGlobalCache"))if(this.immutable){if(!await fe.existsPromise(this.cwd))throw new Zt(56,"Cache path does not exist.")}else{await fe.mkdirPromise(this.cwd,{recursive:!0});let e=Y.resolve(this.cwd,".gitignore");await fe.changeFilePromise(e,`/.gitignore
*.flock
*.tmp
`)}(this.mirrorCwd||!this.immutable)&&await fe.mkdirPromise(this.mirrorCwd||this.cwd,{recursive:!0})}async fetchPackageFromCache(e,r,{onHit:s,onMiss:a,loader:n,...l}){let f=this.getLocatorMirrorPath(e),h=new pi,A=()=>{let de=new _s,xe=Y.join(Rt.root,L9(e));return de.mkdirSync(xe,{recursive:!0}),de.writeJsonSync(Y.join(xe,Or.manifest),{name:Qn(e),mocked:!0}),de},m=async(de,{isColdHit:xe,controlPath:we=null})=>{if(we===null&&l.unstablePackages?.has(e.locatorHash))return{isValid:!0,hash:null};let d=r&&!xe?lD(r).cacheKey:this.cacheKey,be=!l.skipIntegrityCheck||!r?`${d}/${await RF(de)}`:r;if(we!==null){let Ee=!l.skipIntegrityCheck||!r?`${this.cacheKey}/${await RF(we)}`:r;if(be!==Ee)throw new Zt(18,"The remote archive doesn't match the local checksum - has the local cache been corrupted?")}let Ce=null;switch(r!==null&&be!==r&&(this.check?Ce="throw":lD(r).cacheKey!==lD(be).cacheKey?Ce="update":Ce=this.configuration.get("checksumBehavior")),Ce){case null:case"update":return{isValid:!0,hash:be};case"ignore":return{isValid:!0,hash:r};case"reset":return{isValid:!1,hash:r};default:case"throw":throw new Zt(18,"The remote archive doesn't match the expected checksum")}},w=async de=>{if(!n)throw new Error(`Cache check required but no loader configured for ${hn(this.configuration,e)}`);let xe=await n(),we=xe.getRealPath();xe.saveAndClose(),await fe.chmodPromise(we,420);let d=await m(de,{controlPath:we,isColdHit:!1});if(!d.isValid)throw new Error("Assertion failed: Expected a valid checksum");return d.hash},v=async()=>{if(f===null||!await fe.existsPromise(f)){let de=await n(),xe=de.getRealPath();return de.saveAndClose(),{source:"loader",path:xe}}return{source:"mirror",path:f}},D=async()=>{if(!n)throw new Error(`Cache entry required but missing for ${hn(this.configuration,e)}`);if(this.immutable)throw new Zt(56,`Cache entry required but missing for ${hn(this.configuration,e)}`);let{path:de,source:xe}=await v(),{hash:we}=await m(de,{isColdHit:!0}),d=this.getLocatorPath(e,we),be=[];xe!=="mirror"&&f!==null&&be.push(async()=>{let Ee=`${f}${this.cacheId}`;await fe.copyFilePromise(de,Ee,BV.default.constants.COPYFILE_FICLONE),await fe.chmodPromise(Ee,420),await fe.renamePromise(Ee,f)}),(!l.mirrorWriteOnly||f===null)&&be.push(async()=>{let Ee=`${d}${this.cacheId}`;await fe.copyFilePromise(de,Ee,BV.default.constants.COPYFILE_FICLONE),await fe.chmodPromise(Ee,420),await fe.renamePromise(Ee,d)});let Ce=l.mirrorWriteOnly?f??d:d;return await Promise.all(be.map(Ee=>Ee())),[!1,Ce,we]},I=async()=>{let xe=(async()=>{let we=l.unstablePackages?.has(e.locatorHash),d=we||!r||this.isChecksumCompatible(r)?this.getLocatorPath(e,r):null,be=d!==null?this.markedFiles.has(d)||await h.existsPromise(d):!1,Ce=!!l.mockedPackages?.has(e.locatorHash)&&(!this.check||!be),Ee=Ce||be,he=Ee?s:a;if(he&&he(),Ee){let $=null,De=d;if(!Ce)if(this.check)$=await w(De);else{let Te=await m(De,{isColdHit:!1});if(Te.isValid)$=Te.hash;else return D()}return[Ce,De,$]}else{if(this.immutable&&we)throw new Zt(56,`Cache entry required but missing for ${hn(this.configuration,e)}; consider defining ${pe.pretty(this.configuration,"supportedArchitectures",pe.Type.CODE)} to cache packages for multiple systems`);return D()}})();this.mutexes.set(e.locatorHash,xe);try{return await xe}finally{this.mutexes.delete(e.locatorHash)}};for(let de;de=this.mutexes.get(e.locatorHash);)await de;let[R,N,U]=await I();R||this.markedFiles.add(N);let V=()=>this.refCountedZipFsCache.addOrCreate(N,()=>R?A():new _s(N,{baseFs:h,readOnly:!0})),ee,te=new ow(()=>Z5(()=>(ee=V(),ee.value),de=>`Failed to open the cache entry for ${hn(this.configuration,e)}: ${de}`),Y),ie=new Qh(N,{baseFs:te,pathUtils:Y}),ae=()=>{ee?.release()},ge=l.unstablePackages?.has(e.locatorHash)?null:U;return[ie,ae,ge]}},d0t=/^(?:(?<cacheKey>(?<cacheVersion>[0-9]+)(?<cacheSpec>.*))\/)?(?<hash>.*)$/});var RO,uCe=tt(()=>{RO=(r=>(r[r.SCRIPT=0]="SCRIPT",r[r.SHELLCODE=1]="SHELLCODE",r))(RO||{})});var g0t,DC,bV=tt(()=>{Mt();au();_p();Ea();g0t=[[/^(git(?:\+(?:https|ssh))?:\/\/.*(?:\.git)?)#(.*)$/,(t,e,r,s)=>`${r}#commit=${s}`],[/^https:\/\/((?:[^/]+?)@)?codeload\.github\.com\/([^/]+\/[^/]+)\/tar\.gz\/([0-9a-f]+)$/,(t,e,r="",s,a)=>`https://${r}github.com/${s}.git#commit=${a}`],[/^https:\/\/((?:[^/]+?)@)?github\.com\/([^/]+\/[^/]+?)(?:\.git)?#([0-9a-f]+)$/,(t,e,r="",s,a)=>`https://${r}github.com/${s}.git#commit=${a}`],[/^https?:\/\/[^/]+\/(?:[^/]+\/)*(?:@.+(?:\/|(?:%2f)))?([^/]+)\/(?:-|download)\/\1-[^/]+\.tgz(?:#|$)/,t=>`npm:${t}`],[/^https:\/\/npm\.pkg\.github\.com\/download\/(?:@[^/]+)\/(?:[^/]+)\/(?:[^/]+)\/(?:[0-9a-f]+)(?:#|$)/,t=>`npm:${t}`],[/^https:\/\/npm\.fontawesome\.com\/(?:@[^/]+)\/([^/]+)\/-\/([^/]+)\/\1-\2.tgz(?:#|$)/,t=>`npm:${t}`],[/^https?:\/\/[^/]+\/.*\/(@[^/]+)\/([^/]+)\/-\/\1\/\2-(?:[.\d\w-]+)\.tgz(?:#|$)/,(t,e)=>OF({protocol:"npm:",source:null,selector:t,params:{__archiveUrl:e}})],[/^[^/]+\.tgz#[0-9a-f]+$/,t=>`npm:${t}`]],DC=class{constructor(e){this.resolver=e;this.resolutions=null}async setup(e,{report:r}){let s=Y.join(e.cwd,Or Line truncated
`)}reportProgress(r){return{...Promise.resolve().then(async()=>{for await(let{}of r);}),stop:()=>{}}}reportJson(r){}reportFold(r,s){}async finalize(){this.errorCount>0&&(this.stdout.write(`
`),this.stdout.write(`${or(this.configuration,"\u27A4","redBright")} Errors happened when preparing the environment required to run this command.
`),this.suggestInstall&&this.stdout.write(`${or(this.configuration,"\u27A4","redBright")} This might be caused by packages being missing from the lockfile, in which case running "yarn install" might help.
`))}formatNameWithHyperlink(r){return e7(r,{configuration:this.configuration,json:!1})}}});var PC,DV=tt(()=>{Ea();PC=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return!!(r.project.storedResolutions.get(e.descriptorHash)||r.project.originalPackages.has(QF(e).locatorHash))}supportsLocator(e,r){return!!(r.project.originalPackages.has(e.locatorHash)&&!r.project.lockfileNeedsRefresh)}shouldPersistResolution(e,r){throw new Error("The shouldPersistResolution method shouldn't be called on the lockfile resolver, which would always answer yes")}bindDescriptor(e,r,s){return e}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,s){let a=s.project.storedResolutions.get(e.descriptorHash);if(a){let l=s.project.originalPackages.get(a);if(l)return[l]}let n=s.project.originalPackages.get(QF(e).locatorHash);if(n)return[n];throw new Error("Resolution expected from the lockfile data")}async getSatisfying(e,r,s,a){let[n]=await this.getCandidates(e,r,a);return{locators:s.filter(l=>l.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let s=r.project.originalPackages.get(e.locatorHash);if(!s)throw new Error("The lockfile resolver isn't meant to resolve packages - they should already have been stored into a cache");return s}}});function Zp(){}function m0t(t,e,r,s,a){for(var n=0,l=e.length,f=0,h=0;n<l;n++){var A=e[n];if(A.removed){if(A.value=t.join(s.slice(h,h+A.count)),h+=A.count,n&&e[n-1].added){var w=e[n-1];e[n-1]=e[n],e[n]=w}}else{if(!A.added&&a){var m=r.slice(f,f+A.count);m=m.map(function(D,I){var R=s[h+I];return R.length>D.length?R:D}),A.value=t.join(m)}else A.value=t.join(r.slice(f,f+A.count));f+=A.count,A.added||(h+=A.count)}}var v=e[l-1];return l>1&&typeof v.value=="string"&&(v.added||v.removed)&&t.equals("",v.value)&&(e[l-2].value+=v.value,e.pop()),e}function y0t(t){return{newPos:t.newPos,components:t.components.slice(0)}}function E0t(t,e){if(typeof t=="function")e.callback=t;else if(t)for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e}function pCe(t,e,r){return r=E0t(r,{ignoreWhitespace:!0}),TV.diff(t,e,r)}function I0t(t,e,r){return QV.diff(t,e,r)}function TO(t){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?TO=function(e){return typeof e}:TO=function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},TO(t)}function PV(t){return B0t(t)||v0t(t)||S0t(t)||b0t()}function B0t(t){if(Array.isArray(t))return xV(t)}function v0t(t){if(typeof Symbol<"u"&&Symbol.iterator in Object(t))return Array.from(t)}function S0t(t,e){if(t){if(typeof t=="string")return xV(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);if(r==="Object"&&t.constructor&&(r=t.constructor.name),r==="Map"||r==="Set")return Array.from(t);if(r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return xV(t,e)}}function xV(t,e){(e==null||e>t.length)&&(e=t.length);for(var r=0,s=new Array(e);r<e;r++)s[r]=t[r];return s}function b0t(){throw new TypeError(`Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function kV(t,e,r,s,a){e=e||[],r=r||[],s&&(t=s(a,t));var n;for(n=0;n<e.length;n+=1)if(e[n]===t)return r[n];var l;if(D0t.call(t)==="[object Array]"){for(e.push(t),l=new Array(t.length),r.push(l),n=0;n<t.length;n+=1)l[n]=kV(t[n],e,r,s,a);return e.pop(),r.pop(),l}if(t&&t.toJSON&&(t=t.toJSON()),TO(t)==="object"&&t!==null){e.push(t),l={},r.push(l);var f=[],h;for(h in t)t.hasOwnProperty(h)&&f.push(h);for(f.sort(),n=0;n<f.length;n+=1)h=f[n],l[h]=kV(t[h],e,r,s,h);e.pop(),r.pop()}else l=t;return l}function dCe(t,e,r,s,a,n,l){l||(l={}),typeof l.context>"u"&&(l.context=4);var f=I0t(r,s,l);if(!f)return;f.push({value:"",lines:[]});function h(U){return U.map(function(V){return" "+V})}for(var A=[],m=0,w=0,v=[],D=1,I=1,R=function(V){var ee=f[V],te=ee.lines||ee.value.replace(/\n$/,"").split(`
`);if(ee.lines=te,ee.added||ee.removed){var ie;if(!m){var ae=f[V-1];m=D,w=I,ae&&(v=l.context>0?h(ae.lines.slice(-l.context)):[],m-=v.length,w-=v.length)}(ie=v).push.apply(ie,PV(te.map(function(Ee){return(ee.added?"+":"-")+Ee}))),ee.added?I+=te.length:D+=te.length}else{if(m)if(te.length<=l.context*2&&V<f.length-2){var ge;(ge=v).push.apply(ge,PV(h(te)))}else{var de,xe=Math.min(te.length,l.context);(de=v).push.apply(de,PV(h(te.slice(0,xe))));var we={oldStart:m,oldLines:D-m+xe,newStart:w,newLines:I-w+xe,lines:v};if(V>=f.length-2&&te.length<=l.context){var d=/\n$/.test(r),be=/\n$/.test(s),Ce=te.length==0&&v.length>we.oldLines;!d&&Ce&&r.length>0&&v.splice(we.oldLines,0,"\\ No newline at end of file"),(!d&&!Ce||!be)&&v.push("\\ No newline at end of file")}A.push(we),m=0,w=0,v=[]}D+=te.length,I+=te.length}},N=0;N<f.length;N++)R(N);return{oldFileName:t,newFileName:e,oldHeader:a,newHeader:n,hunks:A}}var $er,hCe,ACe,TV,QV,w0t,C0t,D0t,uD,RV,FV=tt(()=>{Zp.prototype={diff:function(e,r){var s=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=s.callback;typeof s=="function"&&(a=s,s={}),this.options=s;var n=this;function l(R){return a?(setTimeout(function(){a(void 0,R)},0),!0):R}e=this.castInput(e),r=this.castInput(r),e=this.removeEmpty(this.tokenize(e)),r=this.removeEmpty(this.tokenize(r));var f=r.length,h=e.length,A=1,m=f+h;s.maxEditLength&&(m=Math.min(m,s.maxEditLength));var w=[{newPos:-1,components:[]}],v=this.extractCommon(w[0],r,e,0);if(w[0].newPos+1>=f&&v+1>=h)return l([{value:this.join(r),count:r.length}]);function D(){for(var R=-1*A;R<=A;R+=2){var N=void 0,U=w[R-1],V=w[R+1],ee=(V?V.newPos:0)-R;U&&(w[R-1]=void 0);var te=U&&U.newPos+1<f,ie=V&&0<=ee&&ee<h;if(!te&&!ie){w[R]=void 0;continue}if(!te||ie&&U.newPos<V.newPos?(N=y0t(V),n.pushComponent(N.components,void 0,!0)):(N=U,N.newPos++,n.pushComponent(N.components,!0,void 0)),ee=n.extractCommon(N,r,e,R),N.newPos+1>=f&&ee+1>=h)return l(m0t(n,N.components,r,e,n.useLongestToken));w[R]=N}A++}if(a)(function R(){setTimeout(function(){if(A>m)return a();D()||R()},0)})();else for(;A<=m;){var I=D();if(I)return I}},pushComponent:function(e,r,s){var a=e[e.length-1];a&&a.added===r&&a.removed===s?e[e.length-1]={count:a.count+1,added:r,removed:s}:e.push({count:1,added:r,removed:s})},extractCommon:function(e,r,s,a){for(var n=r.length,l=s.length,f=e.newPos,h=f-a,A=0;f+1<n&&h+1<l&&this.equals(r[f+1],s[h+1]);)f++,h++,A++;return A&&e.components.push({count:A}),e.newPos=f,h},equals:function(e,r){return this.options.comparator?this.options.comparator(e,r):e===r||this.options.ignoreCase&&e.toLowerCase()===r.toLowerCase()},removeEmpty:function(e){for(var r=[],s=0;s<e.length;s++)e[s]&&r.push(e[s]);return r},castInput:function(e){return e},tokenize:function(e){return e.split("")},join:function(e){return e.join("")}};$er=new Zp;hCe=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/,ACe=/\S/,TV=new Zp;TV.equals=function(t,e){return this.options.ignoreCase&&(t=t.toLowerCase(),e=e.toLowerCase()),t===e||this.options.ignoreWhitespace&&!ACe.test(t)&&!ACe.test(e)};TV.tokenize=function(t){for(var e=t.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/),r=0;r<e.length-1;r++)!e[r+1]&&e[r+2]&&hCe.test(e[r])&&hCe.test(e[r+2])&&(e[r]+=e[r+2],e.splice(r+1,2),r--);return e};QV=new Zp;QV.tokenize=function(t){var e=[],r=t.split(/(\n|\r\n)/);r[r.length-1]||r.pop();for(var s=0;s<r.length;s++){var a=r[s];s%2&&!this.options.newlineIsToken?e[e.length-1]+=a:(this.options.ignoreWhitespace&&(a=a.trim()),e.push(a))}return e};w0t=new Zp;w0t.tokenize=function(t){return t.split(/(\S.+?[.!?])(?=\s+|$)/)};C0t=new Zp;C0t.tokenize=function(t){return t.split(/([{}:;,]|\s+)/)};D0t=Object.prototype.toString,uD=new Zp;uD.useLongestToken=!0;uD.tokenize=QV.tokenize;uD.castInput=function(t){var e=this.options,r=e.undefinedReplacement,s=e.stringifyReplacer,a=s===void 0?function(n,l){return typeof l>"u"?r:l}:s;return typeof t=="string"?t:JSON.stringify(kV(t,null,null,a),a," ")};uD.equals=function(t,e){return Zp.prototype.equals.call(uD,t.replace(/,([\r\n])/g,"$1"),e.replace(/,([\r\n])/g,"$1"))};RV=new Zp;RV.tokenize=function(t){return t.slice()};RV.join=RV.removeEmpty=function(t){return t}});var QO,gCe=tt(()=>{mu();QO=class{constructor(e){this.resolver=e}supportsDescriptor(e,r){return this.resolver.supportsDescriptor(e,r)}supportsLocator(e,r){return this.resolver.supportsLocator(e,r)}shouldPersistResolution(e,r){return this.resolver.shouldPersistResolution(e,r)}bindDescriptor(e,r,s){return this.resolver.bindDescriptor(e,r,s)}getResolutionDependencies(e,r){return this.resolver.getResolutionDependencies(e,r)}async getCandidates(e,r,s){throw new Zt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}async getSatisfying(e,r,s,a){throw new Zt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfile`)}async resolve(e,r){throw new Zt(20,`This package doesn't seem to be present in your lockfile; run "yarn install" to update the lockfLine truncated
`;await fe.changeFilePromise(r,s,{automaticNewlines:!0}),this.manifest.raw=e}}});function Q0t({project:t,allDescriptors:e,allResolutions:r,allPackages:s,accessibleLocators:a=new Set,optionalBuilds:n=new Set,peerRequirements:l=new Map,peerWarnings:f=[],peerRequirementNodes:h=new Map,volatileDescriptors:A=new Set}){let m=new Map,w=[],v=new Map,D=new Map,I=new Map,R=new Map,N=new Map,U=new Map(t.workspaces.map(ae=>{let ge=ae.anchoredLocator.locatorHash,de=s.get(ge);if(typeof de>"u")throw new Error("Assertion failed: The workspace should have an associated package");return[ge,ZS(de)]})),V=()=>{let ae=fe.mktempSync(),ge=Y.join(ae,"stacktrace.log"),de=String(w.length+1).length,xe=w.map((we,d)=>`${`${d+1}.`.padStart(de," ")} ${qc(we)}
`).join("");throw fe.writeFileSync(ge,xe),fe.detachTemp(ae),new Zt(45,`Encountered a stack overflow when resolving peer dependencies; cf ${me.fromPortablePath(ge)}`)},ee=ae=>{let ge=r.get(ae.descriptorHash);if(typeof ge>"u")throw new Error("Assertion failed: The resolution should have been registered");let de=s.get(ge);if(!de)throw new Error("Assertion failed: The package could not be found");return de},te=(ae,ge,de,{top:xe,optional:we})=>{w.length>1e3&&V(),w.push(ge);let d=ie(ae,ge,de,{top:xe,optional:we});return w.pop(),d},ie=(ae,ge,de,{top:xe,optional:we})=>{if(we||n.delete(ge.locatorHash),a.has(ge.locatorHash))return;a.add(ge.locatorHash);let d=s.get(ge.locatorHash);if(!d)throw new Error(`Assertion failed: The package (${hn(t.configuration,ge)}) should have been registered`);let be=new Set,Ce=new Map,Ee=[],he=[],$=[],De=[];for(let Te of Array.from(d.dependencies.values())){if(d.peerDependencies.has(Te.identHash)&&d.locatorHash!==xe)continue;if(Np(Te))throw new Error("Assertion failed: Virtual packages shouldn't be encountered when virtualizing a branch");A.delete(Te.descriptorHash);let ot=we;if(!ot){let Qe=d.dependenciesMeta.get(Qn(Te));if(typeof Qe<"u"){let ft=Qe.get(null);typeof ft<"u"&&ft.optional&&(ot=!0)}}let j=r.get(Te.descriptorHash);if(!j)throw new Error(`Assertion failed: The resolution (${xi(t.configuration,Te)}) should have been registered`);let rt=U.get(j)||s.get(j);if(!rt)throw new Error(`Assertion failed: The package (${j}, resolved from ${xi(t.configuration,Te)}) should have been registered`);if(rt.peerDependencies.size===0){te(Te,rt,new Map,{top:xe,optional:ot});continue}let Ne,Fe,Pe=new Set,He=new Map;Ee.push(()=>{Ne=N9(Te,ge.locatorHash),Fe=O9(rt,ge.locatorHash),d.dependencies.set(Te.identHash,Ne),r.set(Ne.descriptorHash,Fe.locatorHash),e.set(Ne.descriptorHash,Ne),s.set(Fe.locatorHash,Fe),Tp(R,Fe.locatorHash).add(Ne.descriptorHash),be.add(Fe.locatorHash)}),he.push(()=>{N.set(Fe.locatorHash,He);for(let Qe of Fe.peerDependencies.values()){let Me=Rl(Ce,Qe.identHash,()=>{let x=de.get(Qe.identHash)??null,C=d.dependencies.get(Qe.identHash);return!C&&$S(ge,Qe)&&(ae.identHash===ge.identHash?C=ae:(C=oi(ge,ae.range),e.set(C.descriptorHash,C),r.set(C.descriptorHash,ge.locatorHash),A.delete(C.descriptorHash),x=null)),C||(C=oi(Qe,"missing:")),{subject:ge,ident:Qe,provided:C,root:!x,requests:new Map,hash:`p${Os(ge.locatorHash,Qe.identHash).slice(0,6)}`}}).provided;if(Me.range==="missing:"&&Fe.dependencies.has(Qe.identHash)){Fe.peerDependencies.delete(Qe.identHash);continue}if(He.set(Qe.identHash,{requester:Fe,descriptor:Qe,meta:Fe.peerDependenciesMeta.get(Qn(Qe)),children:new Map}),Fe.dependencies.set(Qe.identHash,Me),Np(Me)){let x=r.get(Me.descriptorHash);Tp(I,x).add(Fe.locatorHash)}v.set(Me.identHash,Me),Me.range==="missing:"&&Pe.add(Me.identHash)}Fe.dependencies=new Map(go(Fe.dependencies,([Qe,ft])=>Qn(ft)))}),$.push(()=>{if(!s.has(Fe.locatorHash))return;let Qe=m.get(rt.locatorHash);typeof Qe=="number"&&Qe>=2&&V();let ft=m.get(rt.locatorHash),Me=typeof ft<"u"?ft+1:1;m.set(rt.locatorHash,Me),te(Ne,Fe,He,{top:xe,optional:ot}),m.set(rt.locatorHash,Me-1)}),De.push(()=>{let Qe=r.get(Ne.descriptorHash);if(typeof Qe>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");let ft=N.get(Qe);if(typeof ft>"u")throw new Error("Assertion failed: Expected the peer requests to be registered");for(let Me of Ce.values()){let x=ft.get(Me.ident.identHash);x&&(Me.requests.set(Ne.descriptorHash,x),h.set(Me.hash,Me),Me.root||de.get(Me.ident.identHash)?.children.set(Ne.descriptorHash,x))}if(s.has(Fe.locatorHash))for(let Me of Pe)Fe.dependencies.delete(Me)})}for(let Te of[...Ee,...he])Te();for(let Te of be){be.delete(Te);let ot=s.get(Te),j=Os(Ww(ot).locatorHash,...Array.from(ot.dependencies.values(),Pe=>{let He=Pe.range!=="missing:"?r.get(Pe.descriptorHash):"missing:";if(typeof He>"u")throw new Error(`Assertion failed: Expected the resolution for ${xi(t.configuration,Pe)} to have been registered`);return He===xe?`${He} (top)`:He})),rt=D.get(j);if(typeof rt>"u"){D.set(j,ot);continue}let Ne=Tp(R,rt.locatorHash);for(let Pe of R.get(ot.locatorHash)??[])r.set(Pe,rt.locatorHash),Ne.add(Pe);s.delete(ot.locatorHash),a.delete(ot.locatorHash),be.delete(ot.locatorHash);let Fe=I.get(ot.locatorHash);if(Fe!==void 0){let Pe=Tp(I,rt.locatorHash);for(let He of Fe)Pe.add(He),be.add(He)}}for(let Te of[...$,...De])Te()};for(let ae of t.workspaces){let ge=ae.anchoredLocator;A.delete(ae.anchoredDescriptor.descriptorHash),te(ae.anchoredDescriptor,ge,new Map,{top:ge.locatorHash,optional:!1})}for(let ae of h.values()){if(!ae.root)continue;let ge=s.get(ae.subject.locatorHash);if(typeof ge>"u")continue;for(let xe of ae.requests.values()){let we=`p${Os(ae.subject.locatorHash,Qn(ae.ident),xe.requester.locatorHash).slice(0,6)}`;l.set(we,{subject:ae.subject.locatorHash,requested:ae.ident,rootRequester:xe.requester.locatorHash,allRequesters:Array.from(ib(xe),d=>d.requester.locatorHash)})}let de=[...ib(ae)];if(ae.provided.rang Line truncated
${[w,v,D].join(`
`)}`)}async setupResolutions(){this.storedResolutions=new Map,this.storedDescriptors=new Map,this.storedPackages=new Map,this.lockFileChecksum=null;let e=Y.join(this.cwd,Or.lockfile),r=this.configuration.get("defaultLanguageName");if(fe.existsSync(e)){let s=await fe.readFilePromise(e,"utf8");this.lockFileChecksum=ECe(s);let a=Fs(s);if(a.__metadata){let n=a.__metadata.version,l=a.__metadata.cacheKey;this.lockfileLastVersion=n,this.lockfileNeedsRefresh=n<OO;for(let f of Object.keys(a)){if(f==="__metadata")continue;let h=a[f];if(typeof h.resolution>"u")throw new Error(`Assertion failed: Expected the lockfile entry to have a resolution field (${f})`);let A=Op(h.resolution,!0),m=new nr;m.load(h,{yamlCompatibilityMode:!0});let w=m.version,v=m.languageName||r,D=h.linkType.toUpperCase(),I=h.conditions??null,R=m.dependencies,N=m.peerDependencies,U=m.dependenciesMeta,V=m.peerDependenciesMeta,ee=m.bin;if(h.checksum!=null){let ie=typeof l<"u"&&!h.checksum.includes("/")?`${l}/${h.checksum}`:h.checksum;this.storedChecksums.set(A.locatorHash,ie)}let te={...A,version:w,languageName:v,linkType:D,conditions:I,dependencies:R,peerDependencies:N,dependenciesMeta:U,peerDependenciesMeta:V,bin:ee};this.originalPackages.set(te.locatorHash,te);for(let ie of f.split(x0t)){let ae=q0(ie);n<=6&&(ae=this.configuration.normalizeDependency(ae),ae=oi(ae,ae.range.replace(/^patch:[^@]+@(?!npm(:|%3A))/,"$1npm%3A"))),this.storedDescriptors.set(ae.descriptorHash,ae),this.storedResolutions.set(ae.descriptorHash,A.locatorHash)}}}else s.includes("yarn lockfile v1")&&(this.lockfileLastVersion=-1)}}async setupWorkspaces(){this.workspaces=[],this.workspacesByCwd=new Map,this.workspacesByIdent=new Map;let e=new Set,r=(0,NO.default)(4),s=async(a,n)=>{if(e.has(n))return a;e.add(n);let l=new xC(n,{project:this});await r(()=>l.setup());let f=a.then(()=>{this.addWorkspace(l)});return Array.from(l.workspacesCwds).reduce(s,f)};await s(Promise.resolve(),this.cwd)}addWorkspace(e){let r=this.workspacesByIdent.get(e.anchoredLocator.identHash);if(typeof r<"u")throw new Error(`Duplicate workspace name ${vs(this.configuration,e.anchoredLocator)}: ${me.fromPortablePath(e.cwd)} conflicts with ${me.fromPortablePath(r.cwd)}`);this.workspaces.push(e),this.workspacesByCwd.set(e.cwd,e),this.workspacesByIdent.set(e.anchoredLocator.identHash,e)}get topLevelWorkspace(){return this.getWorkspaceByCwd(this.cwd)}tryWorkspaceByCwd(e){Y.isAbsolute(e)||(e=Y.resolve(this.cwd,e)),e=Y.normalize(e).replace(/\/+$/,"")||Rt.root;let r=this.workspacesByCwd.get(e);return r||null}getWorkspaceByCwd(e){let r=this.tryWorkspaceByCwd(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByFilePath(e){let r=null;for(let s of this.workspaces)Y.relative(s.cwd,e).startsWith("../")||r&&r.cwd.length>=s.cwd.length||(r=s);return r||null}getWorkspaceByFilePath(e){let r=this.tryWorkspaceByFilePath(e);if(!r)throw new Error(`Workspace not found (${e})`);return r}tryWorkspaceByIdent(e){let r=this.workspacesByIdent.get(e.identHash);return typeof r>"u"?null:r}getWorkspaceByIdent(e){let r=this.tryWorkspaceByIdent(e);if(!r)throw new Error(`Workspace not found (${vs(this.configuration,e)})`);return r}tryWorkspaceByDescriptor(e){if(e.range.startsWith(Gi.protocol)){let s=e.range.slice(Gi.protocol.length);if(s!=="^"&&s!=="~"&&s!=="*"&&!Vc(s))return this.tryWorkspaceByCwd(s)}let r=this.tryWorkspaceByIdent(e);return r===null||(Np(e)&&(e=XS(e)),!r.accepts(e.range))?null:r}getWorkspaceByDescriptor(e){let r=this.tryWorkspaceByDescriptor(e);if(r===null)throw new Error(`Workspace not found (${xi(this.configuration,e)})`);return r}tryWorkspaceByLocator(e){let r=this.tryWorkspaceByIdent(e);return r===null||(kf(e)&&(e=Ww(e)),r.anchoredLocator.locatorHash!==e.locatorHash)?null:r}getWorkspaceByLocator(e){let r=this.tryWorkspaceByLocator(e);if(!r)throw new Error(`Workspace not found (${hn(this.configuration,e)})`);return r}deleteDescriptor(e){this.storedResolutions.delete(e),this.storedDescriptors.delete(e)}deleteLocator(e){this.originalPackages.delete(e),this.storedPackages.delete(e),this.accessibleLocators.delete(e)}forgetResolution(e){if("descriptorHash"in e){let r=this.storedResolutions.get(e.descriptorHash);this.deleteDescriptor(e.descriptorHash);let s=new Set(this.storedResolutions.values());typeof r<"u"&&!s.has(r)&&this.deleteLocator(r)}if("locatorHash"in e){this.deleteLocator(e.locatorHash);for(let[r,s]of this.storedResolutions)s===e.locatorHash&&this.deleteDescriptor(r)}}forgetTransientResolutions(){let e=this.configuration.makeResolver(),r=new Map;for(let[s,a]of this.storedResolutions.entries()){let n=r.get(a);n||r.set(a,n=new Set),n.add(s)}for(let s of this.originalPackages.values()){let a;try{a=e.shouldPersistResolution(s,{project:this,resolver:e})}catch{a=!1}if(!a){this.deleteLocator(s.locatorHash);let n=r.get(s.locatorHash);if(n){r.delete(s.locatorHash);for(let l of n)this.deleteDescriptor(l)}}}}forgetVirtualResolutions(){for(let e of this.storedPackages.values())for(let[r,s]of e.dependencies)NLine truncated
`;switch(rt.type){case 0:Ne+=`# Script name: ${rt.script}
`;break;case 1:Ne+=`# Script code: ${rt.script}
`;break}let Fe=null;if(!await fe.mktempPromise(async He=>{let Qe=Y.join(He,"build.log"),{stdout:ft,stderr:Me}=this.configuration.getSubprocessStreams(Qe,{header:Ne,prefix:hn(this.configuration,$),report:r}),x;try{switch(rt.type){case 0:x=await GN($,rt.script,[],{cwd:j,project:this,stdin:Fe,stdout:ft,stderr:Me});break;case 1:x=await t7($,rt.script,[],{cwd:j,project:this,stdin:Fe,stdout:ft,stderr:Me});break}}catch(E){Me.write(E.stack),x=1}if(ft.end(),Me.end(),x===0)return!0;fe.detachTemp(He);let C=`${hn(this.configuration,$)} couldn't be built successfully (exit code ${or(this.configuration,x,Ct.NUMBER)}, logs can be found here: ${or(this.configuration,Qe,Ct.PATH)})`,P=this.optionalBuilds.has($.locatorHash);return P?r.reportInfo(9,C):r.reportError(9,C),PIe&&r.reportFold(me.fromPortablePath(Qe),fe.readFileSync(Qe,"utf8")),P}))return!1}return!0});Ee.push(...ot,Promise.allSettled(ot).then(j=>{te.delete(he),j.every(rt=>rt.status==="fulfilled"&&rt.value===!0)&&we.set($.locatorHash,Te)}))}if(await bf(Ee),Ce===te.size){let he=Array.from(te).map($=>{let De=this.storedPackages.get($);if(!De)throw new Error("Assertion failed: The package should have been registered");return hn(this.configuration,De)}).join(", ");r.reportError(3,`Some packages have circular dependencies that make their build order unsatisfiable - as a result they won't be built (affected packages are: ${he})`);break}}this.storedBuildState=we,this.skippedBuilds=N}async installWithNewReport(e,r){return(await Wt.start({configuration:this.configuration,json:e.json,stdout:e.stdout,forceSectionAlignment:!0,includeLogs:!e.json&&!e.quiet,includeVersion:!0},async a=>{await this.install({...r,report:a})})).exitCode()}async install(e){let r=this.configuration.get("nodeLinker");$e.telemetry?.reportInstall(r);let s=!1;if(await e.report.startTimerPromise("Project validation",{skipIfEmpty:!0},async()=>{this.configuration.get("enableOfflineMode")&&e.report.reportWarning(90,"Offline work is enabled; Yarn won't fetch packages from the remote registry if it can avoid it"),await this.configuration.triggerHook(m=>m.validateProject,this,{reportWarning:(m,w)=>{e.report.reportWarning(m,w)},reportError:(m,w)=>{e.report.reportError(m,w),s=!0}})}),s)return;let a=await this.configuration.getPackageExtensions();for(let m of a.values())for(let[,w]of m)for(let v of w)v.status="inactive";let n=Y.join(this.cwd,Or.lockfile),l=null;if(e.immutable)try{l=await fe.readFilePromise(n,"utf8")}catch(m){throw m.code==="ENOENT"?new Zt(28,"The lockfile would have been created by this install, which is explicitly forbidden."):m}await e.report.startTimerPromise("Resolution step",async()=>{await this.resolveEverything(e)}),await e.report.startTimerPromise("Post-resolution validation",{skipIfEmpty:!0},async()=>{N0t(this,e.report);for(let[,m]of a)for(let[,w]of m)for(let v of w)if(v.userProvided){let D=or(this.configuration,v,Ct.PACKAGE_EXTENSION);switch(v.status){case"inactive":e.report.reportWarning(68,`${D}: No matching package in the dependency tree; you may not need this rule anymore.`);break;case"redundant":e.report.reportWarning(69,`${D}: This rule seems redundant when applied on the original package; the extension may have been applied upstream.`);break}}if(l!==null){let m=ty(l,this.generateLockfile());if(m!==l){let w=dCe(n,n,l,m,void 0,void 0,{maxEditLength:100});if(w){e.report.reportSeparator();for(let v of w.hunks){e.report.reportInfo(null,`@@ -${v.oldStart},${v.oldLines} +${v.newStart},${v.newLines} @@`);for(let D of v.lines)D.startsWith("+")?e.report.reportError(28,or(this.configuration,D,Ct.ADDED)):D.startsWith("-")?e.report.reportError(28,or(this.configuration,D,Ct.REMOVED)):e.report.reportInfo(null,or(this.configuration,D,"grey"))}e.report.reportSeparator()}throw new Zt(28,"The lockfile would have been modified by this install, which is explicitly forbidden.")}}});for(let m of a.values())for(let[,w]of m)for(let v of w)v.userProvided&&v.status==="active"&&$e.telemetry?.reportPackageExtension(Cy(v,Ct.PACKAGE_EXTENSION));await e.report.startTimerPromise("Fetch step",async()=>{await this.fetchEverything(e)});let f=e.immutable?[...new Set(this.configuration.get("immutablePatterns"))].sort():[],h=await Promise.all(f.map(async m=>TF(m,{cwd:this.cwd})));(typeof e.persistProject>"u"||e.persistProject)&&await this.persist(),await e.report.startTimerPromise("Link step",async()=>{if(e.mode==="update-lockfile"){e.report.reportWarning(73,`Skipped due to ${or(this.configuration,"mode=update-lockfile",Ct.CODE)}`);return}await this.linkEverything(e);let m=await Promise.all(f.map(async w=>TF(w,{cwd:this.cwd})));for(let w=0;w<f.length;++w)h[w]!==m[w]&&e.report.reportError(64,`The checksum for ${f[w]} has been modified by this install, which is explicitly forbidden.`)}),await this.persistInstallStateFile();let A=!1;await e.report.startTimerPromise("Post-install validation",{skipIfEmpty:!0},async()=>{await this.configuration.triggerHook(m=>m.validateProjectAfterInstall,this,{reportWarning:(m,w)=>{e.report.r Line truncated
`,`# Manual changes might be lost - proceed with caution!
`].join("")}
`+Uc(r)}async persistLockfile(){let e=Y.join(this.cwd,Or.lockfile),r="";try{r=await fe.readFilePromise(e,"utf8")}catch{}let s=this.generateLockfile(),a=ty(r,s);a!==r&&(await fe.writeFilePromise(e,a),this.lockFileChecksum=ECe(a),this.lockfileNeedsRefresh=!1)}async persistInstallStateFile(){let e=[];for(let l of Object.values(LV))e.push(...l);let r=Iy(this,e),s=_V.default.serialize(r),a=Os(s);if(this.installStateChecksum===a)return;let n=this.configuration.get("installStatePath");await fe.mkdirPromise(Y.dirname(n),{recursive:!0}),await fe.writeFilePromise(n,await R0t(s)),this.installStateChecksum=a}async restoreInstallState({restoreLinkersCustomData:e=!0,restoreResolutions:r=!0,restoreBuildState:s=!0}={}){let a=this.configuration.get("installStatePath"),n;try{let l=await T0t(await fe.readFilePromise(a));n=_V.default.deserialize(l),this.installStateChecksum=Os(l)}catch{r&&await this.applyLightResolution();return}e&&typeof n.linkersCustomData<"u"&&(this.linkersCustomData=n.linkersCustomData),s&&Object.assign(this,Iy(n,LV.restoreBuildState)),r&&(n.lockFileChecksum===this.lockFileChecksum?Object.assign(this,Iy(n,LV.restoreResolutions)):await this.applyLightResolution())}async applyLightResolution(){await this.resolveEverything({lockfileOnly:!0,report:new rs}),await this.persistInstallStateFile()}async persist(){let e=(0,NO.default)(4);await Promise.all([this.persistLockfile(),...this.workspaces.map(r=>e(()=>r.persistManifest()))])}async cacheCleanup({cache:e,report:r}){if(this.configuration.get("enableGlobalCache"))return null;let s=new Set([".gitignore"]);if(!X9(e.cwd,this.cwd)||!await fe.existsPromise(e.cwd))return null;let a=[];for(let l of await fe.readdirPromise(e.cwd)){if(s.has(l))continue;let f=Y.resolve(e.cwd,l);e.markedFiles.has(f)||(e.immutable?r.reportError(56,`${or(this.configuration,Y.basename(f),"magenta")} appears to be unused and would be marked for deletion, but the cache is immutable`):a.push(fe.lstatPromise(f).then(async h=>(await fe.removePromise(f),h.size))))}if(a.length===0)return null;let n=await Promise.all(a);return{count:a.length,size:n.reduce((l,f)=>l+f,0)}}}});function O0t(t){let s=Math.floor(t.timeNow/864e5),a=t.updateInterval*864e5,n=t.state.lastUpdate??t.timeNow+a+Math.floor(a*t.randomInitialInterval),l=n+a,f=t.state.lastTips??s*864e5,h=f+864e5+8*36e5-t.timeZone,A=l<=t.timeNow,m=h<=t.timeNow,w=null;return(A||m||!t.state.lastUpdate||!t.state.lastTips)&&(w={},w.lastUpdate=A?t.timeNow:n,w.lastTips=f,w.blocks=A?{}:t.state.blocks,w.displayedTips=t.state.displayedTips),{nextState:w,triggerUpdate:A,triggerTips:m,nextTips:m?s*864e5:f}}var kC,CCe=tt(()=>{Mt();Qb();G0();EN();Au();_p();kC=class{constructor(e,r){this.values=new Map;this.hits=new Map;this.enumerators=new Map;this.nextTips=0;this.displayedTips=[];this.shouldCommitTips=!1;this.configuration=e;let s=this.getRegistryPath();this.isNew=!fe.existsSync(s),this.shouldShowTips=!1,this.sendReport(r),this.startBuffer()}commitTips(){this.shouldShowTips&&(this.shouldCommitTips=!0)}selectTip(e){let r=new Set(this.displayedTips),s=f=>f&&Fn?Wh(Fn,f):!1,a=e.map((f,h)=>h).filter(f=>e[f]&&s(e[f]?.selector));if(a.length===0)return null;let n=a.filter(f=>!r.has(f));if(n.length===0){let f=Math.floor(a.length*.2);this.displayedTips=f>0?this.displayedTips.slice(-f):[],n=a.filter(h=>!r.has(h))}let l=n[Math.floor(Math.random()*n.length)];return this.displayedTips.push(l),this.commitTips(),e[l]}reportVersion(e){this.reportValue("version",e.replace(/-git\..*/,"-git"))}reportCommandName(e){this.reportValue("commandName",e||"<none>")}reportPluginName(e){this.reportValue("pluginName",e)}reportProject(e){this.reportEnumerator("projectCount",e)}reportInstall(e){this.reportHit("installCount",e)}reportPackageExtension(e){this.reportValue("packageExtension",e)}reportWorkspaceCount(e){this.reportValue("workspaceCount",String(e))}reportDependencyCount(e){this.reportValue("dependencyCount",String(e))}reportValue(e,r){Tp(this.values,e).add(r)}reportEnumerator(e,r){Tp(this.enumerators,e).add(Os(r))}reportHit(e,r="*"){let s=J5(this.hits,e),a=Rl(s,r,()=>0);s.set(r,a+1)}getRegistryPath(){let e=this.configuration.get("globalFolder");return Y.join(e,"telemetry.json")}sendReport(e){let r=this.getRegistryPath(),s;try{s=fe.readJsonSync(r)}catch{s={}}let{nextState:a,triggerUpdate:n,triggerTips:l,nextTips:f}=O0t({state:s,timeNow:Date.now(),timeZone:new Date().getTimezoneOffset()*60*1e3,randomInitialInterval:Math.random(),updateInterval:this.configuration.get("telemetryInterval")});if(this.nextTips=f,this.displayedTips=s.displayedTips??[],a!==null)try{fe.mkdirSync(Y.dirname(r),{recursive:!0}),fe.writeJsonSync(r,a)}catch{return!1}if(l&&this.configuration.get("enableTips")&&(this.shouldShowTips=!0),n){let h=s.blocks??{};if(Object.keys(h).length===0){let A=`https://browser-http-intake.logs.datadoghq.eu/v1/input/${e}?ddsource=yarn`,m=w=>yq(A,w,{configuration:this.configuration}).catch(()=>{});for(let[w,v]of Object.entries(s.blocks??{})){if(Object.keys(v).length===0)continue;let D=v;D Line truncated
`),A=l.length;for(A>0&&l.includes("unstyle")&&(l=[...new Set(["unstyle",...l])].reverse());A-- >0;)f=r(t.styles[l[A]],f,h);return f},a=(n,l,f)=>{t.styles[n]=e({name:n,codes:l}),(t.keys[f]||(t.keys[f]=[])).push(n),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(A){t.alias(n,A)},get(){let A=m=>s(m,A.stack);return Reflect.setPrototypeOf(A,t),A.stack=this.stack?this.stack.concat(n):[n],A}})};return a("reset",[0,0],"modifier"),a("bold",[1,22],"modifier"),a("dim",[2,22],"modifier"),a("italic",[3,23],"modifier"),a("underline",[4,24],"modifier"),a("inverse",[7,27],"modifier"),a("hidden",[8,28],"modifier"),a("strikethrough",[9,29],"modifier"),a("black",[30,39],"color"),a("red",[31,39],"color"),a("green",[32,39],"color"),a("yellow",[33,39],"color"),a("blue",[34,39],"color"),a("magenta",[35,39],"color"),a("cyan",[36,39],"color"),a("white",[37,39],"color"),a("gray",[90,39],"color"),a("grey",[90,39],"color"),a("bgBlack",[40,49],"bg"),a("bgRed",[41,49],"bg"),a("bgGreen",[42,49],"bg"),a("bgYellow",[43,49],"bg"),a("bgBlue",[44,49],"bg"),a("bgMagenta",[45,49],"bg"),a("bgCyan",[46,49],"bg"),a("bgWhite",[47,49],"bg"),a("blackBright",[90,39],"bright"),a("redBright",[91,39],"bright"),a("greenBright",[92,39],"bright"),a("yellowBright",[93,39],"bright"),a("blueBright",[94,39],"bright"),a("magentaBright",[95,39],"bright"),a("cyanBright",[96,39],"bright"),a("whiteBright",[97,39],"bright"),a("bgBlackBright",[100,49],"bgBright"),a("bgRedBright",[101,49],"bgBright"),a("bgGreenBright",[102,49],"bgBright"),a("bgYellowBright",[103,49],"bgBright"),a("bgBlueBright",[104,49],"bgBright"),a("bgMagentaBright",[105,49],"bgBright"),a("bgCyanBright",[106,49],"bgBright"),a("bgWhiteBright",[107,49],"bgBright"),t.ansiRegex=H0t,t.hasColor=t.hasAnsi=n=>(t.ansiRegex.lastIndex=0,typeof n=="string"&&n!==""&&t.ansiRegex.test(n)),t.alias=(n,l)=>{let f=typeof l=="string"?t[l]:l;if(typeof f!="function")throw new TypeError("Expected alias to be the name of an existing color (string) or a function");f.stack||(Reflect.defineProperty(f,"name",{value:n}),t.styles[n]=f,f.stack=[n]),Reflect.defineProperty(t,n,{configurable:!0,enumerable:!0,set(h){t.alias(n,h)},get(){let h=A=>s(A,h.stack);return Reflect.setPrototypeOf(h,t),h.stack=this.stack?this.stack.concat(f.stack):f.stack,h}})},t.theme=n=>{if(!U0t(n))throw new TypeError("Expected theme to be an object");for(let l of Object.keys(n))t.alias(l,n[l]);return t},t.alias("unstyle",n=>typeof n=="string"&&n!==""?(t.ansiRegex.lastIndex=0,n.replace(t.ansiRegex,"")):""),t.alias("noop",n=>n),t.none=t.clear=t.noop,t.stripColor=t.unstyle,t.symbols=PCe(),t.define=a,t};jV.exports=xCe();jV.exports.create=xCe});var va=H(On=>{"use strict";var j0t=Object.prototype.toString,vu=Mf(),kCe=!1,GV=[],RCe={yellow:"blue",cyan:"red",green:"magenta",black:"white",blue:"yellow",red:"cyan",magenta:"green",white:"black"};On.longest=(t,e)=>t.reduce((r,s)=>Math.max(r,e?s[e].length:s.length),0);On.hasColor=t=>!!t&&vu.hasColor(t);var MO=On.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);On.nativeType=t=>j0t.call(t).slice(8,-1).toLowerCase().replace(/\s/g,"");On.isAsyncFn=t=>On.nativeType(t)==="asyncfunction";On.isPrimitive=t=>t!=null&&typeof t!="object"&&typeof t!="function";On.resolve=(t,e,...r)=>typeof e=="function"?e.call(t,...r):e;On.scrollDown=(t=[])=>[...t.slice(1),t[0]];On.scrollUp=(t=[])=>[t.pop(),...t];On.reorder=(t=[])=>{let e=t.slice();return e.sort((r,s)=>r.index>s.index?1:r.index<s.index?-1:0),e};On.swap=(t,e,r)=>{let s=t.length,a=r===s?0:r<0?s-1:r,n=t[e];t[e]=t[a],t[a]=n};On.width=(t,e=80)=>{let r=t&&t.columns?t.columns:e;return t&&typeof t.getWindowSize=="function"&&(r=t.getWindowSize()[0]),process.platform==="win32"?r-1:r};On.height=(t,e=20)=>{let r=t&&t.rows?t.rows:e;return t&&typeof t.getWindowSize=="function"&&(r=t.getWindowSize()[1]),r};On.wordWrap=(t,e={})=>{if(!t)return t;typeof e=="number"&&(e={width:e});let{indent:r="",newline:s=`
`+r,width:a=80}=e,n=(s+r).match(/[^\S\n]/g)||[];a-=n.length;let l=`.{1,${a}}([\\s\\u200B]+|$)|[^\\s\\u200B]+?([\\s\\u200B]+|$)`,f=t.trim(),h=new RegExp(l,"g"),A=f.match(h)||[];return A=A.map(m=>m.replace(/\n$/,"")),e.padEnd&&(A=A.map(m=>m.padEnd(a," "))),e.padStart&&(A=A.map(m=>m.padStart(a," "))),r+A.join(s)};On.unmute=t=>{let e=t.stack.find(s=>vu.keys.color.includes(s));return e?vu[e]:t.stack.find(s=>s.slice(2)==="bg")?vu[e.slice(2)]:s=>s};On.pascal=t=>t?t[0].toUpperCase()+t.slice(1):"";On.inverse=t=>{if(!t||!t.stack)return t;let e=t.stack.find(s=>vu.keys.color.includes(s));if(e){let s=vu["bg"+On.pascal(e)];return s?s.black:t}let r=t.stack.find(s=>s.slice(0,2)==="bg");return r?vu[r.slice(2).toLowerCase()]||t:vu.none};On.complement=t=>{if(!t||!t.stack)return t;let e=t.stack.find(s=>vu.keys.color.includes(s)),r=t.stack.find(s=>s.slice(0,2)==="bg");if(e&&!r)return vu[RCe[e]||e];if(r){let s=r.slice(2).toLowerCase(),a=RCe[s];return a&&vu["bg"+On.pascal(a)]||t}return vu.none};On.meridiem=t=>{let e=t.getHours(),r=t.getMinutes(),s=e>=12?"pm":"am";e=e%12;let a=e===0?12:e,n=r<10?"0"+r:r;return a+":"+n+" "+s};On.set=(t={},e="",r)=>e.split(".").reduce((s,a,n,l)=>{let f=l.length-1>n?s[a]||{}:r;return!On.isObject(f)&&n<l.length-1&&(f={}),s[a]=f},t);On.get=(t={},e="",r)=>{let s=t[e]==null?e.split(".").reduce((a,n)=>a&&a[n],t):t[e];return s??r};On.mixin=(t,e)=>{if(!MO(t))return e;if(!MO(e))return t;for(let r of Object.keys(e)){let s=Object.getOwnPropertyDescriptor(e,r);if(s.hasOwnProperty("value"))if(t.hasOwnProperty(r)&&MO(s.value)){let a=Object.getOwnPropertyDescriptor(t,r);MO(a.value)?t[r]=On.merge({},t[r],e[r]):Reflect.defineProperty(t,r,s)}else Reflect.defineProperty(t,r,s);else Reflect.defineProperty(t,r,s)}return t};On.merge=(...t)=>{let e={};for(let r of t)On.mixin(e,r);return e};On.mixinEmitter=(t,e)=>{let r=e.constructor.prototype;for(let s of Object.keys(r)){let a=r[s];typeof a=="function"?On.define(t,s,a.bind(e)):On.define(t,s,a)}};On.onExit=t=>{let e=(r,s)=>{kCe||(kCe=!0,GV.forEach(a=>a()),r===!0&&process.exit(128+s))};GV.length===0&&(process.once("SIGTERM",e.bind(null,!0,15)),process.once("SIGINT",e.bind(null,!0,2)),process.once("exit",e)),GV.push(t)};On.define=(t,e,r)=>{Reflect.defineProperty(t,e,{value:r})};On.defineExport=(t,e,r)=>{let s;Reflect.defineProperty(t,e,{enumerable:!0,configurable:!0,set(a){s=a},get(){return s?s():r()}})}});var TCe=H(FC=>{"use strict";FC.ctrl={a:"first",b:"backward",c:"cancel",d:"deleteForward",e:"last",f:"forward",g:"reset",i:"tab",k:"cutForward",l:"reset",n:"newItem",m:"cancel",j:"submit",p:"search",r:"remove",s:"save",u:"undo",w:"cutLeft",x:"toggleCursor",v:"paste"};FC.shift={up:"shiftUp",down:"shiftDown",left:"shiftLeft",right:"shiftRight",tab:"prev"};FC.fn={up:"pageUp",down:"pageDown",left:"pageLeft",right:"pageRight",delete:"deleteForward"};FC.option={b:"backward",f:"forward",d:"cutRight",left:"cutLeft",up:"altUp",down:"altDown"};FC.keys={pageup:"pageUp",pagedown:"pageDown",home:"home",end:"end",cancel:"cancel",delete:"deleteForward",backspace:"delete",down:"down",enter:"submit",escape:"cancel",left:"left",space:"space",number:"number",return:"submit",right:"right",tab:"next",up:"up"}});var NCe=H((krr,FCe)=>{"use strict";var QCe=Ae("readline"),G0t=TCe(),q0t=/^(?:\x1b)([a-zA-Z0-9])$/,V0t=/^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/,W0t={OP:"f1",OQ:"f2",OR:"f3",OS:"f4","[11~":"f1","[12~":"f2","[13~":"f3","[14~":"f4","[[A":"f1","[[B":"f2","[[C":"f3","[[D":"f4","[[E":"f5","[15~":"f5","[17~":"f6","[18~":"f7","[19~":"f8","[20~":"f9","[21~":"f10","[23~":"f11","[24~":"f12","[A":"up","[B":"down","[C":"right","[D":"left","[E":"clear","[F":"end","[H":"home",OA:"up",OB:"down",OC:"right",OD:"left",OE:"clear",OF:"end",OH:"home","[1~":"home","[2~":"insert","[3~":"delete","[4~":"end","[5~":"pageup","[6~":"pagedown","[[5~":"pageup","[[6~":"pagedown","[7~":"home","[8~":"end","[a":"up","[b":"down","[c":"right","[d":"left","[e":"clear","[2$":"insert","[3$":"delete","[5$":"pageup","[6$":"pagedown","[7$":"home","[8$":"end",Oa:"up",Ob:"down",Oc:"right",Od:"left",Oe:"clear","[2^":"insert","[3^":"delete","[5^":"pageup","[6^":"pagedown","[7^":"home","[8^":"end","[Z":"tab"};function Y0t(t){return["[a","[b","[c","[d","[e","[2$","[3$","[5$","[6$","[7$","[8$","[Z"].includes(t)}function K0t(t){return["Oa","Ob","Oc","Od","Oe","[2^","[3^","[5^","[6^","[7^","[8^"].includes(t)}var UO=(t="",e={})=>{let r,s={name:e.name,ctrl:!1,meta:!1,shift:!1,option:!1,sequence:t,raw:t,...e};if(Buffer.isBuffer(t)?t[0]>127&&t[1]===void 0?(t[0]-=128,t="\x1B"+String(t)):t=String(t):t!==void 0&&typeof t!="string"?t=String(t):t||(t=s.sequence||""),s.sequence=s.sequence||t||s.name,t==="\r")s.raw=void 0,s.name="return";else if(t===`
`)s.name="enter";else if(t===" ")s.name="tab";else if(t==="\b"||t==="\x7F"||t==="\x1B\x7F"||t==="\x1B\b")s.name="backspace",s.meta=t.charAt(0)==="\x1B";else if(t==="\x1B"||t==="\x1B\x1B")s.name="escape",s.meta=t.length===2;else if(t===" "||t==="\x1B ")s.name="space",s.meta=t.length===2;else if(t<="")s.name=String.fromCharCode(t.charCodeAt(0)+97-1),s.ctrl=!0;else if(t.length===1&&t>="0"&&t<="9")s.name="number";else if(t.length===1&&t>="a"&&t<="z")s.name=t;else if(t.length===1&&t>="A"&&t<="Z")s.name=t.toLowerCase(),s.shift=!0;else if(r=q0t.exec(t))s.meta=!0,s.shift=/^[A-Z]$/.test(r[1]);else if(r=V0t.exec(t)){let a=[...t];a[0]==="\x1B"&&a[1]==="\x1B"&&(s.option=!0);let n=[r[1],r[2],r[4],r[6]].filter(Boolean).join(""),l=(r[3]||r[5]||1)-1;s.ctrl=!!(l&4),s.meta=!!(l&10),s.shift=!!(l&1),s.code=n,s.name=W0t[n],s.shift=Y0t(n)||s.shift,s.ctrl=K0t(n)||s.ctrl}return s};UO.listen=(t={},e)=>{let{stdin:r}=t;if(!r||r!==process.stdin&&!r.isTTY)throw new Error("Invalid stream passed");let s=QCe.createInterface({terminal:!0,input:r});QCe.emitKeypressEvents(r,s);let a=(f,h)=>e(f,UO(f,h),s),n=r.isRaw;return r.isTTY&&r.setRawMode(!0),r.on("keypress",a),s.resume(),()=>{r.isTTY&&r.setRawMode(n),r.removeListener("keypress",a),s.pause(),s.close()}};UO.action=(t,e,r)=>{let s={...G0t,...r};return e.ctrl?(e.action=s.ctrl[e.name],e):e.option&&s.option?(e.action=s.option[e.name],e):e.shift?(e.action=s.shift[e.name],e):(e.action=s.keys[e.name],e)};FCe.exports=UO});var LCe=H((Rrr,OCe)=>{"use strict";OCe.exports=t=>{t.timers=t.timers||{};let e=t.options.timers;if(e)for(let r of Object.keys(e)){let s=e[r];typeof s=="number"&&(s={interval:s}),z0t(t,r,s)}};function z0t(t,e,r={}){let s=t.timers[e]={name:e,start:Date.now(),ms:0,tick:0},a=r.interval||120;s.frames=r.frames||[],s.loading=!0;let n=setInterval(()=>{s.ms=Date.now()-s.start,s.tick++,t.render()},a);return s.stop=()=>{s.loading=!1,clearInterval(n)},Reflect.defineProperty(s,"interval",{value:n}),t.once("close",()=>s.stop()),s.stop}});var MCe=H((Trr,_Ce)=>{"use strict";var{define:J0t,width:Z0t}=va(),qV=class{constructor(e){let r=e.options;J0t(this,"_prompt",e),this.type=e.type,this.name=e.name,this.message="",this.header="",this.footer="",this.error="",this.hint="",this.input="",this.cursor=0,this.index=0,this.lines=0,this.tick=0,this.prompt="",this.buffer="",this.width=Z0t(r.stdout||process.stdout),Object.assign(this,r),this.name=this.name||this.message,this.message=this.message||this.name,this.symbols=e.symbols,this.styles=e.styles,this.required=new Set,this.cancelled=!1,this.submitted=!1}clone(){let e={...this};return e.status=this.status,e.buffer=Buffer.from(e.buffer),delete e.clone,e}set color(e){this._color=e}get color(){let e=this.prompt.styles;if(this.cancelled)return e.cancelled;if(this.submitted)return e.submitted;let r=this._color||e[this.status];return typeof r=="function"?r:e.pending}set loading(e){this._loading=e}get loading(){return typeof this._loading=="boolean"?this._loading:this.loadingChoices?"choices":!1}get status(){return this.cancelled?"cancelled":this.submitted?"submitted":"pending"}};_Ce.exports=qV});var HCe=H((Qrr,UCe)=>{"use strict";var VV=va(),qo=Mf(),WV={default:qo.noop,noop:qo.noop,set inverse(t){this._inverse=t},get inverse(){return this._inverse||VV.inverse(this.primary)},set complement(t){this._complement=t},get complement(){return this._complement||VV.complement(this.primary)},primary:qo.cyan,success:qo.green,danger:qo.magenta,strong:qo.bold,warning:qo.yellow,muted:qo.dim,disabled:qo.gray,dark:qo.dim.gray,underline:qo.underline,set info(t){this._info=t},get info(){return this._info||this.primary},set em(t){this._em=t},get em(){return this._em||this.primary.underline},set heading(t){this._heading=t},get heading(){return this._heading||this.muted.underline},set pending(t){this._pending=t},get pending(){return this._pending||this.primary},set submitted(t){this._submitted=t},get submitted(){return this._submitted||this.success},set cancelled(t){this._cancelled=t},get cancelled(){return this._cancelled||this.danger},set typing(t){this._typing=t},get typing(){return this._typing||this.dim},set placeholder(t){this._placeholder=t},get placeholder(){return this._placeholder||this.primary.dim},set highlight(t){this._highlight=t},get highlight(){return this._highlight||this.inverse}};WV.merge=(t={})=>{t.styles&&typeof t.styles.enabled=="boolean"&&(qo.enabled=t.styles.enabled),t.styles&&typeof t.styles.visible=="boolean"&&(qo.visible=t.styles.visible);let e=VV.merge({},WV,t.styles);delete e.merge;for(let r of Object.keys(qo))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>qo[r]});for(let r of Object.keys(qo.styles))e.hasOwnProperty(r)||Reflect.defineProperty(e,r,{get:()=>qo[r]});return e};UCe.exports=WV});var GCe=H((Frr,jCe)=>{"use strict";var YV=process.platform==="win32",Xp=Mf(),X0t=va(),KV={...Xp.symbols,upDownDoubleArrow:"\u21D5",upDownDoubleArrow2:"\u2B0D",upDownArrow:"\u2195",asterisk:"*",asterism:"\u2042",bulletWhite:"\u25E6",electricArrow:"\u2301", Line truncated
`),A=h[0],m=h[h.length-1],v=(s+(r?" "+r:"")).length,D=v<A.length?A.slice(v+1):"";return{header:l,prompt:A,after:D,rest:h.slice(1),last:m}}async submit(){this.state.submitted=!0,this.state.validating=!0,this.options.onSubmit&&await this.options.onSubmit.call(this,this.name,this.value,this);let e=this.state.error||await this.validate(this.value,this.state);if(e!==!0){let r=`
`+this.symbols.pointer+" ";typeof e=="string"?r+=e.trim():r+="Invalid input",this.state.error=`
`+this.styles.danger(r),this.state.submitted=!1,await this.render(),await this.alert(),this.state.validating=!1,this.state.error=void 0;return}this.state.validating=!1,await this.render(),await this.close(),this.value=await this.result(this.value),this.emit("submit",this.value)}async cancel(e){this.state.cancelled=this.state.submitted=!0,await this.render(),await this.close(),typeof this.options.onCancel=="function"&&await this.options.onCancel.call(this,this.name,this.value,this),this.emit("cancel",await this.error(e))}async close(){this.state.closed=!0;try{let e=this.sections(),r=Math.ceil(e.prompt.length/this.width);e.rest&&this.write($y.cursor.down(e.rest.length)),this.write(`
`.repeat(r))}catch{}this.emit("close")}start(){!this.stop&&this.options.show!==!1&&(this.stop=XV.listen(this,this.keypress.bind(this)),this.once("close",this.stop))}async skip(){return this.skipped=this.options.skip===!0,typeof this.options.skip=="function"&&(this.skipped=await this.options.skip.call(this,this.name,this.value)),this.skipped}async initialize(){let{format:e,options:r,result:s}=this;if(this.format=()=>e.call(this,this.value),this.result=()=>s.call(this,this.value),typeof r.initial=="function"&&(this.initial=await r.initial.call(this,this)),typeof r.onRun=="function"&&await r.onRun.call(this,this),typeof r.onSubmit=="function"){let a=r.onSubmit.bind(this),n=this.submit.bind(this);delete this.options.onSubmit,this.submit=async()=>(await a(this.name,this.value,this),n())}await this.start(),await this.render()}render(){throw new Error("expected prompt to have a custom render method")}run(){return new Promise(async(e,r)=>{if(this.once("submit",e),this.once("cancel",r),await this.skip())return this.render=()=>{},this.submit();await this.initialize(),this.emit("run")})}async element(e,r,s){let{options:a,state:n,symbols:l,timers:f}=this,h=f&&f[e];n.timer=h;let A=a[e]||n[e]||l[e],m=r&&r[e]!=null?r[e]:await A;if(m==="")return m;let w=await this.resolve(m,n,r,s);return!w&&r&&r[e]?this.resolve(A,n,r,s):w}async prefix(){let e=await this.element("prefix")||this.symbols,r=this.timers&&this.timers.prefix,s=this.state;return s.timer=r,Kc.isObject(e)&&(e=e[s.status]||e.pending),Kc.hasColor(e)?e:(this.styles[s.status]||this.styles.pending)(e)}async message(){let e=await this.element("message");return Kc.hasColor(e)?e:this.styles.strong(e)}async separator(){let e=await this.element("separator")||this.symbols,r=this.timers&&this.timers.separator,s=this.state;s.timer=r;let a=e[s.status]||e.pending||s.separator,n=await this.resolve(a,s);return Kc.isObject(n)&&(n=n[s.status]||n.pending),Kc.hasColor(n)?n:this.styles.muted(n)}async pointer(e,r){let s=await this.element("pointer",e,r);if(typeof s=="string"&&Kc.hasColor(s))return s;if(s){let a=this.styles,n=this.index===r,l=n?a.primary:A=>A,f=await this.resolve(s[n?"on":"off"]||s,this.state),h=Kc.hasColor(f)?f:l(f);return n?h:" ".repeat(f.length)}}async indicator(e,r){let s=await this.element("indicator",e,r);if(typeof s=="string"&&Kc.hasColor(s))return s;if(s){let a=this.styles,n=e.enabled===!0,l=n?a.success:a.dark,f=s[n?"on":"off"]||s;return Kc.hasColor(f)?f:l(f)}return""}body(){return null}footer(){if(this.state.status==="pending")return this.element("footer")}header(){if(this.state.status==="pending")return this.element("header")}async hint(){if(this.state.status==="pending"&&!this.isValue(this.state.input)){let e=await this.element("hint");return Kc.hasColor(e)?e:this.styles.muted(e)}}error(e){return this.state.submitted?"":e||this.state.error}format(e){return e}result(e){return e}validate(e){return this.options.required===!0?this.isValue(e):!0}isValue(e){return e!=null&&e!==""}resolve(e,...r){return Kc.resolve(this,e,...r)}get base(){return t.prototype}get style(){return this.styles[this.state.status]}get height(){return this.options.rows||Kc.height(this.stdout,25)}get width(){return this.options.columns||Kc.width(this.stdout,80)}get size(){return{width:this.width,height:this.height}}set cursor(e){this.state.cursor=e}get cursor(){return this.state.cursor}set input(e){this.state.input=e}get input(){return this.state.input}set value(e){this.state.value=e}get value(){let{input:e,value:r}=this.state,s=[r,e].find(this.isValue.bind(this));return this.isValue(s)?s:this.initial}static get prompt(){return e=>new this(e).run()}};function agt(t){let e=a=>t[a]===void 0||typeof t[a]=="function",r=["actions","choices","initial","margin","roles","styles","symbols","theme","timers","value"],s=["body","footer","error","header","hint","indicator","message","prefix","separator","skip"];for(let a of Object.keys(t.options)){if(r.includes(a)||/^on[A-Z]/.test(a))continue;let n=t.options[a];typeof n=="function"&&e(a)?s.includes(a)||(t[a]=n.bind(t)):typeof t[a]!="function"&&(t[a]=n)}}function cgt(t){typeof t=="number"&&(t=[t,t,t,t]);let e=[].concat(t||[]),r=a=>a%2===0?`
`:" ",s=[];for(let a=0;a<4;a++){let n=r(a);e[a]?s.push(n.repeat(e[a])):s.push("")}return s}XCe.exports=$V});var t1e=H((Lrr,e1e)=>{"use strict";var lgt=va(),$Ce={default(t,e){return e},checkbox(t,e){throw new Error("checkbox role is not implemented yet")},editable(t,e){throw new Error("editable role is not implemented yet")},expandable(t,e){throw new Error("expandable role is not implemented yet")},heading(t,e){return e.disabled="",e.indicator=[e.indicator," "].find(r=>r!=null),e.message=e.message||"",e},input(t,e){throw new Error("input role is not implemented yet")},option(t,e){return $Ce.default(t,e)},radio(t,e){throw new Error("radio role is not implemented yet")},separator(t,e){return e.disabled="",e.indicator=[e.indicator," "].find(r=>r!=null),e.message=e.message||t.symbols.line.repeat(5),e},spacer(t,e){return e}};e1e.exports=(t,e={})=>{let r=lgt.merge({},$Ce,e.roles);return r[t]||r.default}});var pD=H((_rr,i1e)=>{"use strict";var ugt=Mf(),fgt=NC(),hgt=t1e(),HO=va(),{reorder:eW,scrollUp:Agt,scrollDown:pgt,isObject:r1e,swap:dgt}=HO,tW=class extends fgt{constructor(e){super(e),this.cursorHide(),this.maxSelected=e.maxSelected||1/0,this.multiple=e.multiple||!1,this.initial=e.initial||0,this.delay=e.delay||0,this.longest=0,this.num=""}async initialize(){typeof this.options.initial=="function"&&(this.initial=await this.options.initial.call(this)),await this.reset(!0),await super.initialize()}async reset(){let{choices:e,initial:r,autofocus:s,suggest:a}=this.options;if(this.state._choices=[],this.state.choices=[],this.choices=await Promise.all(await this.toChoices(e)),this.choices.forEach(n=>n.enabled=!1),typeof a!="function"&&this.selectable.length===0)throw new Error("At least one choice must be selectable");r1e(r)&&(r=Object.keys(r)),Array.isArray(r)?(s!=null&&(this.index=this.findIndex(s)),r.forEach(n=>this.enable(this.find(n))),await this.render()):(s!=null&&(r=s),typeof r=="string"&&(r=this.findIndex(r)),typeof r=="number"&&r>-1&&(this.index=Math.max(0,Math.min(r,this.choices.length)),this.enable(this.find(this.index)))),this.isDisabled(this.focused)&&await this.down()}async toChoices(e,r){this.state.loadingChoices=!0;let s=[],a=0,n=async(l,f)=>{typeof l=="function"&&(l=await l.call(this)),l instanceof Promise&&(l=await l);for(let h=0;h<l.length;h++){let A=l[h]=await this.toChoice(l[h],a++,f);s.push(A),A.choices&&await n(A.choices,A)}return s};return n(e,r).then(l=>(this.state.loadingChoices=!1,l))}async toChoice(e,r,s){if(typeof e=="function"&&(e=await e.call(this,this)),e instanceof Promise&&(e=await e),typeof e=="string"&&(e={name:e}),e.normalized)return e;e.normalized=!0;let a=e.value;if(e=hgt(e.role,this.options)(this,e),typeof e.disabled=="string"&&!e.hint&&(e.hint=e.disabled,e.disabled=!0),e.disabled===!0&&e.hint==null&&(e.hint="(disabled)"),e.index!=null)return e;e.name=e.name||e.key||e.title||e.value||e.message,e.message=e.message||e.name||"",e.value=[e.value,e.name].find(this.isValue.bind(this)),e.input="",e.index=r,e.cursor=0,HO.define(e,"parent",s),e.level=s?s.level+1:1,e.indent==null&&(e.indent=s?s.indent+" ":e.indent||""),e.path=s?s.path+"."+e.name:e.name,e.enabled=!!(this.multiple&&!this.isDisabled(e)&&(e.enabled||this.isSelected(e))),this.isDisabled(e)||(this.longest=Math.max(this.longest,ugt.unstyle(e.message).length));let l={...e};return e.reset=(f=l.input,h=l.value)=>{for(let A of Object.keys(l))e[A]=l[A];e.input=f,e.value=h},a==null&&typeof e.initial=="function"&&(e.input=await e.initial.call(this,this.state,e,r)),e}async onChoice(e,r){this.emit("choice",e,r,this),typeof e.onChoice=="function"&&await e.onChoice.call(this,this.state,e,r)}async addChoice(e,r,s){let a=await this.toChoice(e,r,s);return this.choices.push(a),this.index=this.choices.length-1,this.limit=this.choices.length,a}async newItem(e,r,s){let a={name:"New choice name?",editable:!0,newChoice:!0,...e},n=await this.addChoice(a,r,s);return n.updateChoice=()=>{delete n.newChoice,n.name=n.message=n.input,n.input="",n.cursor=0},this.render()}indent(e){return e.indent==null?e.level>1?" ".repeat(e.level-1):"":e.indent}dispatch(e,r){if(this.multiple&&this[r.name])return this[r.name]();this.alert()}focus(e,r){return typeof r!="boolean"&&(r=e.enabled),r&&!e.enabled&&this.selected.length>=this.maxSelected?this.alert():(this.index=e.index,e.enabled=r&&!this.isDisabled(e),e)}space(){return this.multiple?(this.toggle(this.focused),this.render()):this.alert()}a(){if(this.maxSelected<this.choices.length)return this.alert();let e=this.selectable.every(r=>r.enabled);return this.choices.forEach(r=>r.enabled=!e),this.render()}i(){return this.choices.length-this.selected.length>this.maxSelected?this.alert():(this.choices.forEach(e=>e.enabled=!e.enabled),this.render())}g(e=this.focused){return this.choices.some(r=>!!r.parent)?(this.toggle(e.parent&&!e.choices?e.parent:e),this.render()):this.a()}toggle(e,r){if(!e.enabled&&this.selected.length>=this.maxSelected)return this.alert();typeof r!="boolean"&&(r=!e.enabled),e.enabled=r,e.choices&&e. Line truncated
`),a;return this.options.choicesHeader&&(a=await this.resolve(this.options.choicesHeader,this.state)),[a,s].filter(Boolean).join(`
`)}format(){return!this.state.submitted||this.state.cancelled?"":Array.isArray(this.selected)?this.selected.map(e=>this.styles.primary(e.name)).join(", "):this.styles.primary(this.selected.name)}async render(){let{submitted:e,size:r}=this.state,s="",a=await this.header(),n=await this.prefix(),l=await this.separator(),f=await this.message();this.options.promptLine!==!1&&(s=[n,f,l,""].join(" "),this.state.prompt=s);let h=await this.format(),A=await this.error()||await this.hint(),m=await this.renderChoices(),w=await this.footer();h&&(s+=h),A&&!s.includes(A)&&(s+=" "+A),e&&!h&&!m.trim()&&this.multiple&&this.emptyError!=null&&(s+=this.styles.danger(this.emptyError)),this.clear(r),this.write([a,s,m,w].filter(Boolean).join(`
`)),this.write(this.margin[2]),this.restore()}};s1e.exports=nW});var a1e=H((Urr,o1e)=>{"use strict";var mgt=hg(),ygt=(t,e)=>{let r=t.toLowerCase();return s=>{let n=s.toLowerCase().indexOf(r),l=e(s.slice(n,n+r.length));return n>=0?s.slice(0,n)+l+s.slice(n+r.length):s}},iW=class extends mgt{constructor(e){super(e),this.cursorShow()}moveCursor(e){this.state.cursor+=e}dispatch(e){return this.append(e)}space(e){return this.options.multiple?super.space(e):this.append(e)}append(e){let{cursor:r,input:s}=this.state;return this.input=s.slice(0,r)+e+s.slice(r),this.moveCursor(1),this.complete()}delete(){let{cursor:e,input:r}=this.state;return r?(this.input=r.slice(0,e-1)+r.slice(e),this.moveCursor(-1),this.complete()):this.alert()}deleteForward(){let{cursor:e,input:r}=this.state;return r[e]===void 0?this.alert():(this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.complete())}number(e){return this.append(e)}async complete(){this.completing=!0,this.choices=await this.suggest(this.input,this.state._choices),this.state.limit=void 0,this.index=Math.min(Math.max(this.visible.length-1,0),this.index),await this.render(),this.completing=!1}suggest(e=this.input,r=this.state._choices){if(typeof this.options.suggest=="function")return this.options.suggest.call(this,e,r);let s=e.toLowerCase();return r.filter(a=>a.message.toLowerCase().includes(s))}pointer(){return""}format(){if(!this.focused)return this.input;if(this.options.multiple&&this.state.submitted)return this.selected.map(e=>this.styles.primary(e.message)).join(", ");if(this.state.submitted){let e=this.value=this.input=this.focused.value;return this.styles.primary(e)}return this.input}async render(){if(this.state.status!=="pending")return super.render();let e=this.options.highlight?this.options.highlight.bind(this):this.styles.placeholder,r=ygt(this.input,e),s=this.choices;this.choices=s.map(a=>({...a,message:r(a.message)})),await super.render(),this.choices=s}submit(){return this.options.multiple&&(this.value=this.selected.map(e=>e.name)),super.submit()}};o1e.exports=iW});var oW=H((Hrr,c1e)=>{"use strict";var sW=va();c1e.exports=(t,e={})=>{t.cursorHide();let{input:r="",initial:s="",pos:a,showCursor:n=!0,color:l}=e,f=l||t.styles.placeholder,h=sW.inverse(t.styles.primary),A=R=>h(t.styles.black(R)),m=r,w=" ",v=A(w);if(t.blink&&t.blink.off===!0&&(A=R=>R,v=""),n&&a===0&&s===""&&r==="")return A(w);if(n&&a===0&&(r===s||r===""))return A(s[0])+f(s.slice(1));s=sW.isPrimitive(s)?`${s}`:"",r=sW.isPrimitive(r)?`${r}`:"";let D=s&&s.startsWith(r)&&s!==r,I=D?A(s[r.length]):v;if(a!==r.length&&n===!0&&(m=r.slice(0,a)+A(r[a])+r.slice(a+1),I=""),n===!1&&(I=""),D){let R=t.styles.unstyle(m+I);return m+I+f(s.slice(R.length))}return m+I}});var jO=H((jrr,l1e)=>{"use strict";var Egt=Mf(),Igt=hg(),wgt=oW(),aW=class extends Igt{constructor(e){super({...e,multiple:!0}),this.type="form",this.initial=this.options.initial,this.align=[this.options.align,"right"].find(r=>r!=null),this.emptyError="",this.values={}}async reset(e){return await super.reset(),e===!0&&(this._index=this.index),this.index=this._index,this.values={},this.choices.forEach(r=>r.reset&&r.reset()),this.render()}dispatch(e){return!!e&&this.append(e)}append(e){let r=this.focused;if(!r)return this.alert();let{cursor:s,input:a}=r;return r.value=r.input=a.slice(0,s)+e+a.slice(s),r.cursor++,this.render()}delete(){let e=this.focused;if(!e||e.cursor<=0)return this.alert();let{cursor:r,input:s}=e;return e.value=e.input=s.slice(0,r-1)+s.slice(r),e.cursor--,this.render()}deleteForward(){let e=this.focused;if(!e)return this.alert();let{cursor:r,input:s}=e;if(s[r]===void 0)return this.alert();let a=`${s}`.slice(0,r)+`${s}`.slice(r+1);return e.value=e.input=a,this.render()}right(){let e=this.focused;return e?e.cursor>=e.input.length?this.alert():(e.cursor++,this.render()):this.alert()}left(){let e=this.focused;return e?e.cursor<=0?this.alert():(e.cursor--,this.render()):this.alert()}space(e,r){return this.dispatch(e,r)}number(e,r){return this.dispatch(e,r)}next(){let e=this.focused;if(!e)return this.alert();let{initial:r,input:s}=e;return r&&r.startsWith(s)&&s!==r?(e.value=e.input=r,e.cursor=e.value.length,this.render()):super.next()}prev(){let e=this.focused;return e?e.cursor===0?super.prev():(e.value=e.input="",e.cursor=0,this.render()):this.alert()}separator(){return""}format(e){return this.state.submitted?"":super.format(e)}pointer(){return""}indicator(e){return e.input?"\u29BF":"\u2299"}async choiceSeparator(e,r){let s=await this.resolve(e.separator,this.state,e,r)||":";return s?" "+this.styles.disabled(s):""}async renderChoice(e,r){await this.onChoice(e,r);let{state:s,styles:a}=this,{cursor:n,initial:l="",name:f,hint:h,input:A=""}=e,{muted:m,submitted:w,primary:v,danger:D}=a,I=h,R=this.index===r,N=e.validate||(()=>!0),U=await this.choiceSeparator(e,r),V=e.message;this.align==="right"&&(V=V.padStart(this.longest+1," ")),this.align==="left"&&(V=V.padEnd(this.longest+1," "));let ee=this.values[f]=A||l,te=A?"success":"dark";await N.call(e,ee,thi Line truncated
`)),this.restore()}set value(e){super.value=e}get value(){return this.cast(super.value)}};d1e.exports=lW});var m1e=H((Wrr,g1e)=>{"use strict";var xgt=GO(),uW=class extends xgt{constructor(e){super(e),this.default=this.options.default||(this.initial?"(Y/n)":"(y/N)")}};g1e.exports=uW});var E1e=H((Yrr,y1e)=>{"use strict";var kgt=hg(),Rgt=jO(),OC=Rgt.prototype,fW=class extends kgt{constructor(e){super({...e,multiple:!0}),this.align=[this.options.align,"left"].find(r=>r!=null),this.emptyError="",this.values={}}dispatch(e,r){let s=this.focused,a=s.parent||{};return!s.editable&&!a.editable&&(e==="a"||e==="i")?super[e]():OC.dispatch.call(this,e,r)}append(e,r){return OC.append.call(this,e,r)}delete(e,r){return OC.delete.call(this,e,r)}space(e){return this.focused.editable?this.append(e):super.space()}number(e){return this.focused.editable?this.append(e):super.number(e)}next(){return this.focused.editable?OC.next.call(this):super.next()}prev(){return this.focused.editable?OC.prev.call(this):super.prev()}async indicator(e,r){let s=e.indicator||"",a=e.editable?s:super.indicator(e,r);return await this.resolve(a,this.state,e,r)||""}indent(e){return e.role==="heading"?"":e.editable?" ":" "}async renderChoice(e,r){return e.indent="",e.editable?OC.renderChoice.call(this,e,r):super.renderChoice(e,r)}error(){return""}footer(){return this.state.error}async validate(){let e=!0;for(let r of this.choices){if(typeof r.validate!="function"||r.role==="heading")continue;let s=r.parent?this.value[r.parent.name]:this.value;if(r.editable?s=r.value===r.name?r.initial||"":r.value:this.isDisabled(r)||(s=r.enabled===!0),e=await r.validate(s,this.state),e!==!0)break}return e!==!0&&(this.state.error=typeof e=="string"?e:"Invalid Input"),e}submit(){if(this.focused.newChoice===!0)return super.submit();if(this.choices.some(e=>e.newChoice))return this.alert();this.value={};for(let e of this.choices){let r=e.parent?this.value[e.parent.name]:this.value;if(e.role==="heading"){this.value[e.name]={};continue}e.editable?r[e.name]=e.value===e.name?e.initial||"":e.value:this.isDisabled(e)||(r[e.name]=e.enabled===!0)}return this.base.submit.call(this)}};y1e.exports=fW});var eE=H((Krr,I1e)=>{"use strict";var Tgt=NC(),Qgt=oW(),{isPrimitive:Fgt}=va(),hW=class extends Tgt{constructor(e){super(e),this.initial=Fgt(this.initial)?String(this.initial):"",this.initial&&this.cursorHide(),this.state.prevCursor=0,this.state.clipboard=[]}async keypress(e,r={}){let s=this.state.prevKeypress;return this.state.prevKeypress=r,this.options.multiline===!0&&r.name==="return"&&(!s||s.name!=="return")?this.append(`
`,r):super.keypress(e,r)}moveCursor(e){this.cursor+=e}reset(){return this.input=this.value="",this.cursor=0,this.render()}dispatch(e,r){if(!e||r.ctrl||r.code)return this.alert();this.append(e)}append(e){let{cursor:r,input:s}=this.state;this.input=`${s}`.slice(0,r)+e+`${s}`.slice(r),this.moveCursor(String(e).length),this.render()}insert(e){this.append(e)}delete(){let{cursor:e,input:r}=this.state;if(e<=0)return this.alert();this.input=`${r}`.slice(0,e-1)+`${r}`.slice(e),this.moveCursor(-1),this.render()}deleteForward(){let{cursor:e,input:r}=this.state;if(r[e]===void 0)return this.alert();this.input=`${r}`.slice(0,e)+`${r}`.slice(e+1),this.render()}cutForward(){let e=this.cursor;if(this.input.length<=e)return this.alert();this.state.clipboard.push(this.input.slice(e)),this.input=this.input.slice(0,e),this.render()}cutLeft(){let e=this.cursor;if(e===0)return this.alert();let r=this.input.slice(0,e),s=this.input.slice(e),a=r.split(" ");this.state.clipboard.push(a.pop()),this.input=a.join(" "),this.cursor=this.input.length,this.input+=s,this.render()}paste(){if(!this.state.clipboard.length)return this.alert();this.insert(this.state.clipboard.pop()),this.render()}toggleCursor(){this.state.prevCursor?(this.cursor=this.state.prevCursor,this.state.prevCursor=0):(this.state.prevCursor=this.cursor,this.cursor=0),this.render()}first(){this.cursor=0,this.render()}last(){this.cursor=this.input.length-1,this.render()}next(){let e=this.initial!=null?String(this.initial):"";if(!e||!e.startsWith(this.input))return this.alert();this.input=this.initial,this.cursor=this.initial.length,this.render()}prev(){if(!this.input)return this.alert();this.reset()}backward(){return this.left()}forward(){return this.right()}right(){return this.cursor>=this.input.length?this.alert():(this.moveCursor(1),this.render())}left(){return this.cursor<=0?this.alert():(this.moveCursor(-1),this.render())}isValue(e){return!!e}async format(e=this.value){let r=await this.resolve(this.initial,this.state);return this.state.submitted?this.styles.submitted(e||r):Qgt(this,{input:e,initial:r,pos:this.cursor})}async render(){let e=this.state.size,r=await this.prefix(),s=await this.separator(),a=await this.message(),n=[r,a,s].filter(Boolean).join(" ");this.state.prompt=n;let l=await this.header(),f=await this.format(),h=await this.error()||await this.hint(),A=await this.footer();h&&!f.includes(h)&&(f+=" "+h),n+=" "+f,this.clear(e),this.write([l,n,A].filter(Boolean).join(`
`)),this.restore()}};I1e.exports=hW});var C1e=H((zrr,w1e)=>{"use strict";var Ngt=t=>t.filter((e,r)=>t.lastIndexOf(e)===r),qO=t=>Ngt(t).filter(Boolean);w1e.exports=(t,e={},r="")=>{let{past:s=[],present:a=""}=e,n,l;switch(t){case"prev":case"undo":return n=s.slice(0,s.length-1),l=s[s.length-1]||"",{past:qO([r,...n]),present:l};case"next":case"redo":return n=s.slice(1),l=s[0]||"",{past:qO([...n,r]),present:l};case"save":return{past:qO([...s,r]),present:""};case"remove":return l=qO(s.filter(f=>f!==r)),a="",l.length&&(a=l.pop()),{past:l,present:a};default:throw new Error(`Invalid action: "${t}"`)}}});var pW=H((Jrr,v1e)=>{"use strict";var Ogt=eE(),B1e=C1e(),AW=class extends Ogt{constructor(e){super(e);let r=this.options.history;if(r&&r.store){let s=r.values||this.initial;this.autosave=!!r.autosave,this.store=r.store,this.data=this.store.get("values")||{past:[],present:s},this.initial=this.data.present||this.data.past[this.data.past.length-1]}}completion(e){return this.store?(this.data=B1e(e,this.data,this.input),this.data.present?(this.input=this.data.present,this.cursor=this.input.length,this.render()):this.alert()):this.alert()}altUp(){return this.completion("prev")}altDown(){return this.completion("next")}prev(){return this.save(),super.prev()}save(){this.store&&(this.data=B1e("save",this.data,this.input),this.store.set("values",this.data))}submit(){return this.store&&this.autosave===!0&&this.save(),super.submit()}};v1e.exports=AW});var b1e=H((Zrr,S1e)=>{"use strict";var Lgt=eE(),dW=class extends Lgt{format(){return""}};S1e.exports=dW});var P1e=H((Xrr,D1e)=>{"use strict";var _gt=eE(),gW=class extends _gt{constructor(e={}){super(e),this.sep=this.options.separator||/, */,this.initial=e.initial||""}split(e=this.value){return e?String(e).split(this.sep):[]}format(){let e=this.state.submitted?this.styles.primary:r=>r;return this.list.map(e).join(", ")}async submit(e){let r=this.state.error||await this.validate(this.list,this.state);return r!==!0?(this.state.error=r,super.submit()):(this.value=this.list,super.submit())}get list(){return this.split()}};D1e.exports=gW});var k1e=H(($rr,x1e)=>{"use strict";var Mgt=hg(),mW=class extends Mgt{constructor(e){super({...e,multiple:!0})}};x1e.exports=mW});var EW=H((enr,R1e)=>{"use strict";var Ugt=eE(),yW=class extends Ugt{constructor(e={}){super({style:"number",...e}),this.min=this.isValue(e.min)?this.toNumber(e.min):-1/0,this.max=this.isValue(e.max)?this.toNumber(e.max):1/0,this.delay=e.delay!=null?e.delay:1e3,this.float=e.float!==!1,this.round=e.round===!0||e.float===!1,this.major=e.major||10,this.minor=e.minor||1,this.initial=e.initial!=null?e.initial:"",this.input=String(this.initial),this.cursor=this.input.length,this.cursorShow()}append(e){return!/[-+.]/.test(e)||e==="."&&this.input.includes(".")?this.alert("invalid number"):super.append(e)}number(e){return super.append(e)}next(){return this.input&&this.input!==this.initial?this.alert():this.isValue(this.initial)?(this.input=this.initial,this.cursor=String(this.initial).length,this.render()):this.alert()}up(e){let r=e||this.minor,s=this.toNumber(this.input);return s>this.max+r?this.alert():(this.input=`${s+r}`,this.render())}down(e){let r=e||this.minor,s=this.toNumber(this.input);return s<this.min-r?this.alert():(this.input=`${s-r}`,this.render())}shiftDown(){return this.down(this.major)}shiftUp(){return this.up(this.major)}format(e=this.input){return typeof this.options.format=="function"?this.options.format.call(this,e):this.styles.info(e)}toNumber(e=""){return this.float?+e:Math.round(+e)}isValue(e){return/^[-+]?[0-9]+((\.)|(\.[0-9]+))?$/.test(e)}submit(){let e=[this.input,this.initial].find(r=>this.isValue(r));return this.value=this.toNumber(e||0),super.submit()}};R1e.exports=yW});var Q1e=H((tnr,T1e)=>{T1e.exports=EW()});var N1e=H((rnr,F1e)=>{"use strict";var Hgt=eE(),IW=class extends Hgt{constructor(e){super(e),this.cursorShow()}format(e=this.input){return this.keypressed?(this.state.submitted?this.styles.primary:this.styles.muted)(this.symbols.asterisk.repeat(e.length)):""}};F1e.exports=IW});var _1e=H((nnr,L1e)=>{"use strict";var jgt=Mf(),Ggt=pD(),O1e=va(),wW=class extends Ggt{constructor(e={}){super(e),this.widths=[].concat(e.messageWidth||50),this.align=[].concat(e.align||"left"),this.linebreak=e.linebreak||!1,this.edgeLength=e.edgeLength||3,this.newline=e.newline||`
`;let r=e.startNumber||1;typeof this.scale=="number"&&(this.scaleKey=!1,this.scale=Array(this.scale).fill(0).map((s,a)=>({name:a+r})))}async reset(){return this.tableized=!1,await super.reset(),this.render()}tableize(){if(this.tableized===!0)return;this.tableized=!0;let e=0;for(let r of this.choices){e=Math.max(e,r.message.length),r.scaleIndex=r.initial||2,r.scale=[];for(let s=0;s<this.scale.length;s++)r.scale.push({index:s})}this.widths[0]=Math.min(this.widths[0],e+3)}async dispatch(e,r){if(this.multiple)return this[r.name]?await this[r.name](e,r):await super.dispatch(e,r);this.alert()}heading(e,r,s){return this.styles.strong(e)}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;return e.scaleIndex>=this.scale.length-1?this.alert():(e.scaleIndex++,this.render())}left(){let e=this.focused;return e.scaleIndex<=0?this.alert():(e.scaleIndex--,this.render())}indent(){return""}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.index)).join(", "):""}pointer(){return""}renderScaleKey(){return this.scaleKey===!1||this.state.submitted?"":["",...this.scale.map(s=>` ${s.name} - ${s.message}`)].map(s=>this.styles.muted(s)).join(`
`)}renderScaleHeading(e){let r=this.scale.map(h=>h.name);typeof this.options.renderScaleHeading=="function"&&(r=this.options.renderScaleHeading.call(this,e));let s=this.scaleLength-r.join("").length,a=Math.round(s/(r.length-1)),l=r.map(h=>this.styles.strong(h)).join(" ".repeat(a)),f=" ".repeat(this.widths[0]);return this.margin[3]+f+this.margin[1]+l}scaleIndicator(e,r,s){if(typeof this.options.scaleIndicator=="function")return this.options.scaleIndicator.call(this,e,r,s);let a=e.scaleIndex===r.index;return r.disabled?this.styles.hint(this.symbols.radio.disabled):a?this.styles.success(this.symbols.radio.on):this.symbols.radio.off}renderScale(e,r){let s=e.scale.map(n=>this.scaleIndicator(e,n,r)),a=this.term==="Hyper"?"":" ";return s.join(a+this.symbols.line.repeat(this.edgeLength))}async renderChoice(e,r){await this.onChoice(e,r);let s=this.index===r,a=await this.pointer(e,r),n=await e.hint;n&&!O1e.hasColor(n)&&(n=this.styles.muted(n));let l=I=>this.margin[3]+I.replace(/\s+$/,"").padEnd(this.widths[0]," "),f=this.newline,h=this.indent(e),A=await this.resolve(e.message,this.state,e,r),m=await this.renderScale(e,r),w=this.margin[1]+this.margin[3];this.scaleLength=jgt.unstyle(m).length,this.widths[0]=Math.min(this.widths[0],this.width-this.scaleLength-w.length);let D=O1e.wordWrap(A,{width:this.widths[0],newline:f}).split(`
`).map(I=>l(I)+this.margin[1]);return s&&(m=this.styles.info(m),D=D.map(I=>this.styles.info(I))),D[0]+=m,this.linebreak&&D.push(""),[h+a,D.join(`
`)].filter(Boolean)}async renderChoices(){if(this.state.submitted)return"";this.tableize();let e=this.visible.map(async(a,n)=>await this.renderChoice(a,n)),r=await Promise.all(e),s=await this.renderScaleHeading();return this.margin[0]+[s,...r.map(a=>a.join(" "))].join(`
`)}async render(){let{submitted:e,size:r}=this.state,s=await this.prefix(),a=await this.separator(),n=await this.message(),l="";this.options.promptLine!==!1&&(l=[s,n,a,""].join(" "),this.state.prompt=l);let f=await this.header(),h=await this.format(),A=await this.renderScaleKey(),m=await this.error()||await this.hint(),w=await this.renderChoices(),v=await this.footer(),D=this.emptyError;h&&(l+=h),m&&!l.includes(m)&&(l+=" "+m),e&&!h&&!w.trim()&&this.multiple&&D!=null&&(l+=this.styles.danger(D)),this.clear(r),this.write([f,l,A,w,v].filter(Boolean).join(`
`)),this.state.submitted||this.write(this.margin[2]),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIndex;return this.base.submit.call(this)}};L1e.exports=wW});var H1e=H((inr,U1e)=>{"use strict";var M1e=Mf(),qgt=(t="")=>typeof t=="string"?t.replace(/^['"]|['"]$/g,""):"",BW=class{constructor(e){this.name=e.key,this.field=e.field||{},this.value=qgt(e.initial||this.field.initial||""),this.message=e.message||this.name,this.cursor=0,this.input="",this.lines=[]}},Vgt=async(t={},e={},r=s=>s)=>{let s=new Set,a=t.fields||[],n=t.template,l=[],f=[],h=[],A=1;typeof n=="function"&&(n=await n());let m=-1,w=()=>n[++m],v=()=>n[m+1],D=I=>{I.line=A,l.push(I)};for(D({type:"bos",value:""});m<n.length-1;){let I=w();if(/^[^\S\n ]$/.test(I)){D({type:"text",value:I});continue}if(I===`
`){D({type:"newline",value:I}),A++;continue}if(I==="\\"){I+=w(),D({type:"text",value:I});continue}if((I==="$"||I==="#"||I==="{")&&v()==="{"){let N=w();I+=N;let U={type:"template",open:I,inner:"",close:"",value:I},V;for(;V=w();){if(V==="}"){v()==="}"&&(V+=w()),U.value+=V,U.close=V;break}V===":"?(U.initial="",U.key=U.inner):U.initial!==void 0&&(U.initial+=V),U.value+=V,U.inner+=V}U.template=U.open+(U.initial||U.inner)+U.close,U.key=U.key||U.inner,e.hasOwnProperty(U.key)&&(U.initial=e[U.key]),U=r(U),D(U),h.push(U.key),s.add(U.key);let ee=f.find(te=>te.name===U.key);U.field=a.find(te=>te.name===U.key),ee||(ee=new BW(U),f.push(ee)),ee.lines.push(U.line-1);continue}let R=l[l.length-1];R.type==="text"&&R.line===A?R.value+=I:D({type:"text",value:I})}return D({type:"eos",value:""}),{input:n,tabstops:l,unique:s,keys:h,items:f}};U1e.exports=async t=>{let e=t.options,r=new Set(e.required===!0?[]:e.required||[]),s={...e.values,...e.initial},{tabstops:a,items:n,keys:l}=await Vgt(e,s),f=CW("result",t,e),h=CW("format",t,e),A=CW("validate",t,e,!0),m=t.isValue.bind(t);return async(w={},v=!1)=>{let D=0;w.required=r,w.items=n,w.keys=l,w.output="";let I=async(V,ee,te,ie)=>{let ae=await A(V,ee,te,ie);return ae===!1?"Invalid field "+te.name:ae};for(let V of a){let ee=V.value,te=V.key;if(V.type!=="template"){ee&&(w.output+=ee);continue}if(V.type==="template"){let ie=n.find(we=>we.name===te);e.required===!0&&w.required.add(ie.name);let ae=[ie.input,w.values[ie.value],ie.value,ee].find(m),de=(ie.field||{}).message||V.inner;if(v){let we=await I(w.values[te],w,ie,D);if(we&&typeof we=="string"||we===!1){w.invalid.set(te,we);continue}w.invalid.delete(te);let d=await f(w.values[te],w,ie,D);w.output+=M1e.unstyle(d);continue}ie.placeholder=!1;let xe=ee;ee=await h(ee,w,ie,D),ae!==ee?(w.values[te]=ae,ee=t.styles.typing(ae),w.missing.delete(de)):(w.values[te]=void 0,ae=`<${de}>`,ee=t.styles.primary(ae),ie.placeholder=!0,w.required.has(te)&&w.missing.add(de)),w.missing.has(de)&&w.validating&&(ee=t.styles.warning(ae)),w.invalid.has(te)&&w.validating&&(ee=t.styles.danger(ae)),D===w.index&&(xe!==ee?ee=t.styles.underline(ee):ee=t.styles.heading(M1e.unstyle(ee))),D++}ee&&(w.output+=ee)}let R=w.output.split(`
`).map(V=>" "+V),N=n.length,U=0;for(let V of n)w.invalid.has(V.name)&&V.lines.forEach(ee=>{R[ee][0]===" "&&(R[ee]=w.styles.danger(w.symbols.bullet)+R[ee].slice(1))}),t.isValue(w.values[V.name])&&U++;return w.completed=(U/N*100).toFixed(0),w.output=R.join(`
`),w.output}};function CW(t,e,r,s){return(a,n,l,f)=>typeof l.field[t]=="function"?l.field[t].call(e,a,n,l,f):[s,a].find(h=>e.isValue(h))}});var G1e=H((snr,j1e)=>{"use strict";var Wgt=Mf(),Ygt=H1e(),Kgt=NC(),vW=class extends Kgt{constructor(e){super(e),this.cursorHide(),this.reset(!0)}async initialize(){this.interpolate=await Ygt(this),await super.initialize()}async reset(e){this.state.keys=[],this.state.invalid=new Map,this.state.missing=new Set,this.state.completed=0,this.state.values={},e!==!0&&(await this.initialize(),await this.render())}moveCursor(e){let r=this.getItem();this.cursor+=e,r.cursor+=e}dispatch(e,r){if(!r.code&&!r.ctrl&&e!=null&&this.getItem()){this.append(e,r);return}this.alert()}append(e,r){let s=this.getItem(),a=s.input.slice(0,this.cursor),n=s.input.slice(this.cursor);this.input=s.input=`${a}${e}${n}`,this.moveCursor(1),this.render()}delete(){let e=this.getItem();if(this.cursor<=0||!e.input)return this.alert();let r=e.input.slice(this.cursor),s=e.input.slice(0,this.cursor-1);this.input=e.input=`${s}${r}`,this.moveCursor(-1),this.render()}increment(e){return e>=this.state.keys.length-1?0:e+1}decrement(e){return e<=0?this.state.keys.length-1:e-1}first(){this.state.index=0,this.render()}last(){this.state.index=this.state.keys.length-1,this.render()}right(){if(this.cursor>=this.input.length)return this.alert();this.moveCursor(1),this.render()}left(){if(this.cursor<=0)return this.alert();this.moveCursor(-1),this.render()}prev(){this.state.index=this.decrement(this.state.index),this.getItem(),this.render()}next(){this.state.index=this.increment(this.state.index),this.getItem(),this.render()}up(){this.prev()}down(){this.next()}format(e){let r=this.state.completed<100?this.styles.warning:this.styles.success;return this.state.submitted===!0&&this.state.completed!==100&&(r=this.styles.danger),r(`${this.state.completed}% completed`)}async render(){let{index:e,keys:r=[],submitted:s,size:a}=this.state,n=[this.options.newline,`
`].find(V=>V!=null),l=await this.prefix(),f=await this.separator(),h=await this.message(),A=[l,h,f].filter(Boolean).join(" ");this.state.prompt=A;let m=await this.header(),w=await this.error()||"",v=await this.hint()||"",D=s?"":await this.interpolate(this.state),I=this.state.key=r[e]||"",R=await this.format(I),N=await this.footer();R&&(A+=" "+R),v&&!R&&this.state.completed===0&&(A+=" "+v),this.clear(a);let U=[m,A,D,N,w.trim()];this.write(U.filter(Boolean).join(n)),this.restore()}getItem(e){let{items:r,keys:s,index:a}=this.state,n=r.find(l=>l.name===s[a]);return n&&n.input!=null&&(this.input=n.input,this.cursor=n.cursor),n}async submit(){typeof this.interpolate!="function"&&await this.initialize(),await this.interpolate(this.state,!0);let{invalid:e,missing:r,output:s,values:a}=this.state;if(e.size){let f="";for(let[h,A]of e)f+=`Invalid ${h}: ${A}
`;return this.state.error=f,super.submit()}if(r.size)return this.state.error="Required: "+[...r.keys()].join(", "),super.submit();let l=Wgt.unstyle(s).split(`
`).map(f=>f.slice(1)).join(`
`);return this.value={values:a,result:l},super.submit()}};j1e.exports=vW});var V1e=H((onr,q1e)=>{"use strict";var zgt="(Use <shift>+<up/down> to sort)",Jgt=hg(),SW=class extends Jgt{constructor(e){super({...e,reorder:!1,sort:!0,multiple:!0}),this.state.hint=[this.options.hint,zgt].find(this.isValue.bind(this))}indicator(){return""}async renderChoice(e,r){let s=await super.renderChoice(e,r),a=this.symbols.identicalTo+" ",n=this.index===r&&this.sorting?this.styles.muted(a):" ";return this.options.drag===!1&&(n=""),this.options.numbered===!0?n+`${r+1} - `+s:n+s}get selected(){return this.choices}submit(){return this.value=this.choices.map(e=>e.value),super.submit()}};q1e.exports=SW});var Y1e=H((anr,W1e)=>{"use strict";var Zgt=pD(),bW=class extends Zgt{constructor(e={}){if(super(e),this.emptyError=e.emptyError||"No items were selected",this.term=process.env.TERM_PROGRAM,!this.options.header){let r=["","4 - Strongly Agree","3 - Agree","2 - Neutral","1 - Disagree","0 - Strongly Disagree",""];r=r.map(s=>this.styles.muted(s)),this.state.header=r.join(`
`)}}async toChoices(...e){if(this.createdScales)return!1;this.createdScales=!0;let r=await super.toChoices(...e);for(let s of r)s.scale=Xgt(5,this.options),s.scaleIdx=2;return r}dispatch(){this.alert()}space(){let e=this.focused,r=e.scale[e.scaleIdx],s=r.selected;return e.scale.forEach(a=>a.selected=!1),r.selected=!s,this.render()}indicator(){return""}pointer(){return""}separator(){return this.styles.muted(this.symbols.ellipsis)}right(){let e=this.focused;return e.scaleIdx>=e.scale.length-1?this.alert():(e.scaleIdx++,this.render())}left(){let e=this.focused;return e.scaleIdx<=0?this.alert():(e.scaleIdx--,this.render())}indent(){return" "}async renderChoice(e,r){await this.onChoice(e,r);let s=this.index===r,a=this.term==="Hyper",n=a?9:8,l=a?"":" ",f=this.symbols.line.repeat(n),h=" ".repeat(n+(a?0:1)),A=ee=>(ee?this.styles.success("\u25C9"):"\u25EF")+l,m=r+1+".",w=s?this.styles.heading:this.styles.noop,v=await this.resolve(e.message,this.state,e,r),D=this.indent(e),I=D+e.scale.map((ee,te)=>A(te===e.scaleIdx)).join(f),R=ee=>ee===e.scaleIdx?w(ee):ee,N=D+e.scale.map((ee,te)=>R(te)).join(h),U=()=>[m,v].filter(Boolean).join(" "),V=()=>[U(),I,N," "].filter(Boolean).join(`
`);return s&&(I=this.styles.cyan(I),N=this.styles.cyan(N)),V()}async renderChoices(){if(this.state.submitted)return"";let e=this.visible.map(async(s,a)=>await this.renderChoice(s,a)),r=await Promise.all(e);return r.length||r.push(this.styles.danger("No matching choices")),r.join(`
`)}format(){return this.state.submitted?this.choices.map(r=>this.styles.info(r.scaleIdx)).join(", "):""}async render(){let{submitted:e,size:r}=this.state,s=await this.prefix(),a=await this.separator(),n=await this.message(),l=[s,n,a].filter(Boolean).join(" ");this.state.prompt=l;let f=await this.header(),h=await this.format(),A=await this.error()||await this.hint(),m=await this.renderChoices(),w=await this.footer();(h||!A)&&(l+=" "+h),A&&!l.includes(A)&&(l+=" "+A),e&&!h&&!m&&this.multiple&&this.type!=="form"&&(l+=this.styles.danger(this.emptyError)),this.clear(r),this.write([l,f,m,w].filter(Boolean).join(`
`)),this.restore()}submit(){this.value={};for(let e of this.choices)this.value[e.name]=e.scaleIdx;return this.base.submit.call(this)}};function Xgt(t,e={}){if(Array.isArray(e.scale))return e.scale.map(s=>({...s}));let r=[];for(let s=1;s<t+1;s++)r.push({i:s,selected:!1});return r}W1e.exports=bW});var z1e=H((cnr,K1e)=>{K1e.exports=pW()});var Z1e=H((lnr,J1e)=>{"use strict";var $gt=GO(),DW=class extends $gt{async initialize(){await super.initialize(),this.value=this.initial=!!this.options.initial,this.disabled=this.options.disabled||"no",this.enabled=this.options.enabled||"yes",await this.render()}reset(){this.value=this.initial,this.render()}delete(){this.alert()}toggle(){this.value=!this.value,this.render()}enable(){if(this.value===!0)return this.alert();this.value=!0,this.render()}disable(){if(this.value===!1)return this.alert();this.value=!1,this.render()}up(){this.toggle()}down(){this.toggle()}right(){this.toggle()}left(){this.toggle()}next(){this.toggle()}prev(){this.toggle()}dispatch(e="",r){switch(e.toLowerCase()){case" ":return this.toggle();case"1":case"y":case"t":return this.enable();case"0":case"n":case"f":return this.disable();default:return this.alert()}}format(){let e=s=>this.styles.primary.underline(s);return[this.value?this.disabled:e(this.disabled),this.value?e(this.enabled):this.enabled].join(this.styles.muted(" / "))}async render(){let{size:e}=this.state,r=await this.header(),s=await this.prefix(),a=await this.separator(),n=await this.message(),l=await this.format(),f=await this.error()||await this.hint(),h=await this.footer(),A=[s,n,a,l].join(" ");this.state.prompt=A,f&&!A.includes(f)&&(A+=" "+f),this.clear(e),this.write([r,A,h].filter(Boolean).join(`
`)),this.write(this.margin[2]),this.restore()}};J1e.exports=DW});var $1e=H((unr,X1e)=>{"use strict";var emt=hg(),PW=class extends emt{constructor(e){if(super(e),typeof this.options.correctChoice!="number"||this.options.correctChoice<0)throw new Error("Please specify the index of the correct answer from the list of choices")}async toChoices(e,r){let s=await super.toChoices(e,r);if(s.length<2)throw new Error("Please give at least two choices to the user");if(this.options.correctChoice>s.length)throw new Error("Please specify the index of the correct answer from the list of choices");return s}check(e){return e.index===this.options.correctChoice}async result(e){return{selectedAnswer:e,correctAnswer:this.options.choices[this.options.correctChoice].value,correct:await this.check(this.state)}}};X1e.exports=PW});var t2e=H(xW=>{"use strict";var e2e=va(),ro=(t,e)=>{e2e.defineExport(xW,t,e),e2e.defineExport(xW,t.toLowerCase(),e)};ro("AutoComplete",()=>a1e());ro("BasicAuth",()=>p1e());ro("Confirm",()=>m1e());ro("Editable",()=>E1e());ro("Form",()=>jO());ro("Input",()=>pW());ro("Invisible",()=>b1e());ro("List",()=>P1e());ro("MultiSelect",()=>k1e());ro("Numeral",()=>Q1e());ro("Password",()=>N1e());ro("Scale",()=>_1e());ro("Select",()=>hg());ro("Snippet",()=>G1e());ro("Sort",()=>V1e());ro("Survey",()=>Y1e());ro("Text",()=>z1e());ro("Toggle",()=>Z1e());ro("Quiz",()=>$1e())});var n2e=H((hnr,r2e)=>{r2e.exports={ArrayPrompt:pD(),AuthPrompt:cW(),BooleanPrompt:GO(),NumberPrompt:EW(),StringPrompt:eE()}});var gD=H((Anr,s2e)=>{"use strict";var i2e=Ae("assert"),RW=Ae("events"),Ag=va(),Hf=class extends RW{constructor(e,r){super(),this.options=Ag.merge({},e),this.answers={...r}}register(e,r){if(Ag.isObject(e)){for(let a of Object.keys(e))this.register(a,e[a]);return this}i2e.equal(typeof r,"function","expected a function");let s=e.toLowerCase();return r.prototype instanceof this.Prompt?this.prompts[s]=r:this.prompts[s]=r(this.Prompt,this),this}async prompt(e=[]){for(let r of[].concat(e))try{typeof r=="function"&&(r=await r.call(this)),await this.ask(Ag.merge({},this.options,r))}catch(s){return Promise.reject(s)}return this.answers}async ask(e){typeof e=="function"&&(e=await e.call(this));let r=Ag.merge({},this.options,e),{type:s,name:a}=e,{set:n,get:l}=Ag;if(typeof s=="function"&&(s=await s.call(this,e,this.answers)),!s)return this.answers[a];i2e(this.prompts[s],`Prompt "${s}" is not registered`);let f=new this.prompts[s](r),h=l(this.answers,a);f.state.answers=this.answers,f.enquirer=this,a&&f.on("submit",m=>{this.emit("answer",a,m,f),n(this.answers,a,m)});let A=f.emit.bind(f);return f.emit=(...m)=>(this.emit.call(this,...m),A(...m)),this.emit("prompt",f,this),r.autofill&&h!=null?(f.value=f.input=h,r.autofill==="show"&&await f.submit()):h=f.value=await f.run(),h}use(e){return e.call(this,this),this}set Prompt(e){this._Prompt=e}get Prompt(){return this._Prompt||this.constructor.Prompt}get prompts(){return this.constructor.prompts}static set Prompt(e){this._Prompt=e}static get Prompt(){return this._Prompt||NC()}static get prompts(){return t2e()}static get types(){return n2e()}static get prompt(){let e=(r,...s)=>{let a=new this(...s),n=a.emit.bind(a);return a.emit=(...l)=>(e.emit(...l),n(...l)),a.prompt(r)};return Ag.mixinEmitter(e,new RW),e}};Ag.mixinEmitter(Hf,new RW);var kW=Hf.prompts;for(let t of Object.keys(kW)){let e=t.toLowerCase(),r=s=>new kW[t](s).run();Hf.prompt[e]=r,Hf[e]=r,Hf[t]||Reflect.defineProperty(Hf,t,{get:()=>kW[t]})}var dD=t=>{Ag.defineExport(Hf,t,()=>Hf.types[t])};dD("ArrayPrompt");dD("AuthPrompt");dD("BooleanPrompt");dD("NumberPrompt");dD("StringPrompt");s2e.exports=Hf});var A2e=H((Oir,lmt)=>{lmt.exports={name:"@yarnpkg/cli",version:"4.18.0",license:"BSD-2-Clause",main:"./sources/index.ts",exports:{".":"./sources/index.ts","./polyfills":"./sources/polyfills.ts","./package.json":"./package.json"},dependencies:{"@yarnpkg/core":"workspace:^","@yarnpkg/fslib":"workspace:^","@yarnpkg/libzip":"workspace:^","@yarnpkg/parsers":"workspace:^","@yarnpkg/plugin-catalog":"workspace:^","@yarnpkg/plugin-compat":"workspace:^","@yarnpkg/plugin-constraints":"workspace:^","@yarnpkg/plugin-dlx":"workspace:^","@yarnpkg/plugin-essentials":"workspace:^","@yarnpkg/plugin-exec":"workspace:^","@yarnpkg/plugin-file":"workspace:^","@yarnpkg/plugin-git":"workspace:^","@yarnpkg/plugin-github":"workspace:^","@yarnpkg/plugin-http":"workspace:^","@yarnpkg/plugin-init":"workspace:^","@yarnpkg/plugin-interactive-tools":"workspace:^","@yarnpkg/plugin-jsr":"workspace:^","@yarnpkg/plugin-link":"workspace:^","@yarnpkg/plugin-nm":"workspace:^","@yarnpkg/plugin-npm":"workspace:^","@yarnpkg/plugin-npm-cli":"workspace:^","@yarnpkg/plugin-pack":"workspace:^","@yarnpkg/plugin-patch":"workspace:^","@yarnpkg/plugin-pnp":"workspace:^","@yarnpkg/plugin-pnpm":"workspace:^","@yarnpkg/plugin-stage":"workspace:^","@yarnpkg/plugin-typescript":"workspace:^","@yarnpkg/plugin-version":"workspace:^","@yarnpkg/plugin-workspace-tools":"workspace:^","@yarnpkg/shell":"workspa Line truncated
${V} at ${ee}`:`
${V}`}).join("");A.push({text:`Conflict detected in constraint targeting ${pe.pretty(t.configuration,D,pe.Type.CODE)}; conflicting values are:${R}`,fixable:!1})}else{let[[R]]=I,N=rc(v,D);if(JSON.stringify(N)===JSON.stringify(R))continue;if(!s){let U=typeof N>"u"?`Missing field ${pe.pretty(t.configuration,D,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,R,pe.Type.INSPECT)}`:typeof R>"u"?`Extraneous field ${pe.pretty(t.configuration,D,pe.Type.CODE)} currently set to ${pe.pretty(t.configuration,N,pe.Type.INSPECT)}`:`Invalid field ${pe.pretty(t.configuration,D,pe.Type.CODE)}; expected ${pe.pretty(t.configuration,R,pe.Type.INSPECT)}, found ${pe.pretty(t.configuration,N,pe.Type.INSPECT)}`;A.push({text:U,fixable:!0});continue}typeof R>"u"?N0(v,D):Ey(v,D,R),m=!0}m&&a.set(w,v)}A.length>0&&n.set(w,A)}return{changedWorkspaces:a,remainingErrors:n}}function $2e(t,{configuration:e}){let r={children:[]};for(let[s,a]of t){let n=[];for(let f of a){let h=f.text.split(/\n/);f.fixable&&(h[0]=`${pe.pretty(e,"\u2699","gray")} ${h[0]}`),n.push({value:pe.tuple(pe.Type.NO_HINT,h[0]),children:h.slice(1).map(A=>({value:pe.tuple(pe.Type.NO_HINT,A)}))})}let l={value:pe.tuple(pe.Type.LOCATOR,s.anchoredLocator),children:Ye.sortMap(n,f=>f.value[1])};r.children.push(l)}return r.children=Ye.sortMap(r.children,s=>s.value[1]),r}var v1,iyt,syt,oyt,DD=tt(()=>{We();xl();v1=class{constructor(e){this.indexedFields=e;this.items=[];this.indexes={};this.clear()}clear(){this.items=[];for(let e of this.indexedFields)this.indexes[e]=new Map}insert(e){this.items.push(e);for(let r of this.indexedFields){let s=Object.hasOwn(e,r)?e[r]:void 0;if(typeof s>"u")continue;Ye.getArrayWithDefault(this.indexes[r],s).push(e)}return e}find(e){if(typeof e>"u")return this.items;let r=Object.entries(e);if(r.length===0)return this.items;let s=[],a;for(let[l,f]of r){let h=l,A=Object.hasOwn(this.indexes,h)?this.indexes[h]:void 0;if(typeof A>"u"){s.push([h,f]);continue}let m=new Set(A.get(f)??[]);if(m.size===0)return[];if(typeof a>"u")a=m;else for(let w of a)m.has(w)||a.delete(w);if(a.size===0)break}let n=[...a??[]];return s.length>0&&(n=n.filter(l=>{for(let[f,h]of s)if(!(typeof h<"u"?Object.hasOwn(l,f)&&l[f]===h:Object.hasOwn(l,f)===!1))return!1;return!0})),n}},iyt=/^[0-9]+$/,syt=/^[a-zA-Z0-9_]+$/,oyt=new Set(["scripts",...nr.allDependencies])});var eBe=H((wur,AY)=>{var lyt;(function(t){var e=function(){return{"append/2":[new t.type.Rule(new t.type.Term("append",[new t.type.Var("X"),new t.type.Var("L")]),new t.type.Term("foldl",[new t.type.Term("append",[]),new t.type.Var("X"),new t.type.Term("[]",[]),new t.type.Var("L")]))],"append/3":[new t.type.Rule(new t.type.Term("append",[new t.type.Term("[]",[]),new t.type.Var("X"),new t.type.Var("X")]),null),new t.type.Rule(new t.type.Term("append",[new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("S")])]),new t.type.Term("append",[new t.type.Var("T"),new t.type.Var("X"),new t.type.Var("S")]))],"member/2":[new t.type.Rule(new t.type.Term("member",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("_")])]),null),new t.type.Rule(new t.type.Term("member",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("_"),new t.type.Var("Xs")])]),new t.type.Term("member",[new t.type.Var("X"),new t.type.Var("Xs")]))],"permutation/2":[new t.type.Rule(new t.type.Term("permutation",[new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("permutation",[new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("T")]),new t.type.Var("S")]),new t.type.Term(",",[new t.type.Term("permutation",[new t.type.Var("T"),new t.type.Var("P")]),new t.type.Term(",",[new t.type.Term("append",[new t.type.Var("X"),new t.type.Var("Y"),new t.type.Var("P")]),new t.type.Term("append",[new t.type.Var("X"),new t.type.Term(".",[new t.type.Var("H"),new t.type.Var("Y")]),new t.type.Var("S")])])]))],"maplist/2":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("X"),new t.type.Var("Xs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("X")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("Xs")])]))],"maplist/3":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Term("[]",[])]),null),new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Term(".",[new t.type.Var("A"),new t.type.Var("As")]),new t.type.Term(".",[new t.type.Var("B"),new t.type.Var("Bs")])]),new t.type.Term(",",[new t.type.Term("call",[new t.type.Var("P"),new t.type.Var("A"),new t.type.Var("B")]),new t.type.Term("maplist",[new t.type.Var("P"),new t.type.Var("As"),new t.type.Var("Bs")])]))],"maplist/4":[new t.type.Rule(new t.type.Term("maplist",[new t.type.Var("_"),new t.type.Term("[]",[]),new t.type.Ter Line truncated
`+h:"")),l.error.method="_execFileSync",l.error.program=a,l.error.args=n,l.error.extMessage=h,l.error.exitCode=+f),ki.unlinkSync(A),ki.unlinkSync(m),ki.unlinkSync(w),ki.unlinkSync(v),l}function Ayt(t){var e,r={},s,a={env:process.env,encoding:t.encoding};if(pg||(nE?process.env.PSModulePath?(pg="powershell.exe",ZO=["-ExecutionPolicy","Bypass","-File",__dirname+"\\read.ps1"]):(pg="cscript.exe",ZO=["//nologo",__dirname+"\\read.cs.js"]):(pg="/bin/sh",ZO=[__dirname+"/read.sh"])),nE&&!process.env.PSModulePath&&(a.stdio=[process.stdin]),gY.execFileSync){e=sBe(t),PD&&PD("execFileSync",e);try{r.input=gY.execFileSync(pg,e,a)}catch(n){s=n.stderr?(n.stderr+"").trim():"",r.error=new Error(nBe+(s?`
`+s:"")),r.error.method="execFileSync",r.error.program=pg,r.error.args=e,r.error.extMessage=s,r.error.exitCode=n.status,r.error.code=n.code,r.error.signal=n.signal}}else r=hyt(t,a);return r.error||(r.input=r.input.replace(/^\s*'|'\s*$/g,""),t.display=""),r}function EY(t){var e="",r=t.display,s=!t.display&&t.keyIn&&t.hideEchoBack&&!t.mask;function a(){var n=Ayt(t);if(n.error)throw n.error;return n.input}return yY&&yY(t),function(){var n,l,f;function h(){return n||(n=process.binding("fs"),l=process.binding("constants")),n}if(typeof ed=="string")if(ed=null,nE){if(f=function(A){var m=A.replace(/^\D+/,"").split("."),w=0;return(m[0]=+m[0])&&(w+=m[0]*1e4),(m[1]=+m[1])&&(w+=m[1]*100),(m[2]=+m[2])&&(w+=m[2]),w}(process.version),!(f>=20302&&f<40204||f>=5e4&&f<50100||f>=50600&&f<60200)&&process.stdin.isTTY)process.stdin.pause(),ed=process.stdin.fd,b1=process.stdin._handle;else try{ed=h().open("CONIN$",l.O_RDWR,parseInt("0666",8)),b1=new tBe(ed,!0)}catch{}if(process.stdout.isTTY)Gf=process.stdout.fd;else{try{Gf=ki.openSync("\\\\.\\CON","w")}catch{}if(typeof Gf!="number")try{Gf=h().open("CONOUT$",l.O_RDWR,parseInt("0666",8))}catch{}}}else{if(process.stdin.isTTY){process.stdin.pause();try{ed=ki.openSync("/dev/tty","r"),b1=process.stdin._handle}catch{}}else try{ed=ki.openSync("/dev/tty","r"),b1=new tBe(ed,!1)}catch{}if(process.stdout.isTTY)Gf=process.stdout.fd;else try{Gf=ki.openSync("/dev/tty","w")}catch{}}}(),function(){var n,l,f=!t.hideEchoBack&&!t.keyIn,h,A,m,w,v;XO="";function D(I){return I===rBe?!0:b1.setRawMode(I)!==0?!1:(rBe=I,!0)}if(iBe||!b1||typeof Gf!="number"&&(t.display||!f)){e=a();return}if(t.display&&(ki.writeSync(Gf,t.display),t.display=""),!t.displayOnly){if(!D(!f)){e=a();return}for(A=t.keyIn?1:t.bufferSize,h=Buffer.allocUnsafe&&Buffer.alloc?Buffer.alloc(A):new Buffer(A),t.keyIn&&t.limit&&(l=new RegExp("[^"+t.limit+"]","g"+(t.caseSensitive?"":"i")));;){m=0;try{m=ki.readSync(ed,h,0,A)}catch(I){if(I.code!=="EOF"){D(!1),e+=a();return}}if(m>0?(w=h.toString(t.encoding,0,m),XO+=w):(w=`
`,XO+="\0"),w&&typeof(v=(w.match(/^(.*?)[\r\n]/)||[])[1])=="string"&&(w=v,n=!0),w&&(w=w.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"")),w&&l&&(w=w.replace(l,"")),w&&(f||(t.hideEchoBack?t.mask&&ki.writeSync(Gf,new Array(w.length+1).join(t.mask)):ki.writeSync(Gf,w)),e+=w),!t.keyIn&&n||t.keyIn&&e.length>=A)break}!f&&!s&&ki.writeSync(Gf,`
`),D(!1)}}(),t.print&&!s&&t.print(r+(t.displayOnly?"":(t.hideEchoBack?new Array(e.length+1).join(t.mask):e)+`
`),t.encoding),t.displayOnly?"":CY=t.keepWhitespace||t.keyIn?e:e.trim()}function pyt(t,e){var r=[];function s(a){a!=null&&(Array.isArray(a)?a.forEach(s):(!e||e(a))&&r.push(a))}return s(t),r}function BY(t){return t.replace(/[\x00-\x7f]/g,function(e){return"\\x"+("00"+e.charCodeAt().toString(16)).substr(-2)})}function Co(){var t=Array.prototype.slice.call(arguments),e,r;return t.length&&typeof t[0]=="boolean"&&(r=t.shift(),r&&(e=Object.keys(mY),t.unshift(mY))),t.reduce(function(s,a){return a==null||(a.hasOwnProperty("noEchoBack")&&!a.hasOwnProperty("hideEchoBack")&&(a.hideEchoBack=a.noEchoBack,delete a.noEchoBack),a.hasOwnProperty("noTrim")&&!a.hasOwnProperty("keepWhitespace")&&(a.keepWhitespace=a.noTrim,delete a.noTrim),r||(e=Object.keys(a)),e.forEach(function(n){var l;if(a.hasOwnProperty(n))switch(l=a[n],n){case"mask":case"limitMessage":case"defaultInput":case"encoding":l=l!=null?l+"":"",l&&n!=="limitMessage"&&(l=l.replace(/[\r\n]/g,"")),s[n]=l;break;case"bufferSize":!isNaN(l=parseInt(l,10))&&typeof l=="number"&&(s[n]=l);break;case"displayOnly":case"keyIn":case"hideEchoBack":case"caseSensitive":case"keepWhitespace":case"history":case"cd":s[n]=!!l;break;case"limit":case"trueValue":case"falseValue":s[n]=pyt(l,function(f){var h=typeof f;return h==="string"||h==="number"||h==="function"||f instanceof RegExp}).map(function(f){return typeof f=="string"?f.replace(/[\r\n]/g,""):f});break;case"print":case"phContent":case"preCheck":s[n]=typeof l=="function"?l:void 0;break;case"prompt":case"display":s[n]=l??"";break}})),s},{})}function IY(t,e,r){return e.some(function(s){var a=typeof s;return a==="string"?r?t===s:t.toLowerCase()===s.toLowerCase():a==="number"?parseFloat(t)===s:a==="function"?s(t):s instanceof RegExp?s.test(t):!1})}function vY(t,e){var r=dg.normalize(nE?(process.env.HOMEDRIVE||"")+(process.env.HOMEPATH||""):process.env.HOME||"").replace(/[\/\\]+$/,"");return t=dg.normalize(t),e?t.replace(/^~(?=\/|\\|$)/,r):t.replace(new RegExp("^"+BY(r)+"(?=\\/|\\\\|$)",nE?"i":""),"~")}function D1(t,e){var r="(?:\\(([\\s\\S]*?)\\))?(\\w+|.-.)(?:\\(([\\s\\S]*?)\\))?",s=new RegExp("(\\$)?(\\$<"+r+">)","g"),a=new RegExp("(\\$)?(\\$\\{"+r+"\\})","g");function n(l,f,h,A,m,w){var v;return f||typeof(v=e(m))!="string"?h:v?(A||"")+v+(w||""):""}return t.replace(s,n).replace(a,n)}function oBe(t,e,r){var s,a=[],n=-1,l=0,f="",h;function A(m,w){return w.length>3?(m.push(w[0]+"..."+w[w.length-1]),h=!0):w.length&&(m=m.concat(w)),m}return s=t.reduce(function(m,w){return m.concat((w+"").split(""))},[]).reduce(function(m,w){var v,D;return e||(w=w.toLowerCase()),v=/^\d$/.test(w)?1:/^[A-Z]$/.test(w)?2:/^[a-z]$/.test(w)?3:0,r&&v===0?f+=w:(D=w.charCodeAt(0),v&&v===n&&D===l+1?a.push(w):(m=A(m,a),a=[w],n=v),l=D),m},[]),s=A(s,a),f&&(s.push(f),h=!0),{values:s,suppressed:h}}function aBe(t,e){return t.join(t.length>2?", ":e?" / ":"/")}function cBe(t,e){var r,s,a={},n;if(e.phContent&&(r=e.phContent(t,e)),typeof r!="string")switch(t){case"hideEchoBack":case"mask":case"defaultInput":case"caseSensitive":case"keepWhitespace":case"encoding":case"bufferSize":case"history":case"cd":r=e.hasOwnProperty(t)?typeof e[t]=="boolean"?e[t]?"on":"off":e[t]+"":"";break;case"limit":case"trueValue":case"falseValue":s=e[e.hasOwnProperty(t+"Src")?t+"Src":t],e.keyIn?(a=oBe(s,e.caseSensitive),s=a.values):s=s.filter(function(l){var f=typeof l;return f==="string"||f==="number"}),r=aBe(s,a.suppressed);break;case"limitCount":case"limitCountNotZero":r=e[e.hasOwnProperty("limitSrc")?"limitSrc":"limit"].length,r=r||t!=="limitCountNotZero"?r+"":"";break;case"lastInput":r=CY;break;case"cwd":case"CWD":case"cwdHome":r=process.cwd(),t==="CWD"?r=dg.basename(r):t==="cwdHome"&&(r=vY(r));break;case"date":case"time":case"localeDate":case"localeTime":r=new Date()["to"+t.replace(/^./,function(l){return l.toUpperCase()})+"String"]();break;default:typeof(n=(t.match(/^history_m(\d+)$/)||[])[1])=="string"&&(r=rE[rE.length-n]||"")}return r}function lBe(t){var e=/^(.)-(.)$/.exec(t),r="",s,a,n,l;if(!e)return null;for(s=e[1].charCodeAt(0),a=e[2].charCodeAt(0),l=s<a?1:-1,n=s;n!==a+l;n+=l)r+=String.fromCharCode(n);return r}function wY(t){var e=new RegExp(/(\s*)(?:("|')(.*?)(?:\2|$)|(\S+))/g),r,s="",a=[],n;for(t=t.trim();r=e.exec(t);)n=r[3]||r[4]||"",r[1]&&(a.push(s),s=""),s+=n;return s&&a.push(s),a}function uBe(t,e){return e.trueValue.length&&IY(t,e.trueValue,e.caseSensitive)?!0:e.falseValue.length&&IY(t,e.falseValue,e.caseSensitive)?!1:t}function fBe(t){var e,r,s,a,n,l,f;function h(m){return cBe(m,t)}function A(m){t.display+=(/[^\r\n]$/.test(t.display)?`
`:"")+m}for(t.limitSrc=t.limit,t.displaySrc=t.display,t.limit="",t.display=D1(t.display+"",h);;){if(e=EY(t),r=!1,s="",t.defaultInput&&!e&&(e=t.defaultInput),t.history&&((a=/^\s*\!(?:\!|-1)(:p)?\s*$/.exec(e))?(n=rE[0]||"",a[1]?r=!0:e=n,A(n+`
`),r||(t.displayOnly=!0,EY(t),t.displayOnly=!1)):e&&e!==rE[rE.length-1]&&(rE=[e])),!r&&t.cd&&e)switch(l=wY(e),l[0].toLowerCase()){case"cd":if(l[1])try{process.chdir(vY(l[1],!0))}catch(m){A(m+"")}r=!0;break;case"pwd":A(process.cwd()),r=!0;break}if(!r&&t.preCheck&&(f=t.preCheck(e,t),e=f.res,f.forceNext&&(r=!0)),!r){if(!t.limitSrc.length||IY(e,t.limitSrc,t.caseSensitive))break;t.limitMessage&&(s=D1(t.limitMessage,h))}A((s?s+`
`:"")+D1(t.displaySrc+"",h))}return uBe(e,t)}wn._DBG_set_useExt=function(t){iBe=t};wn._DBG_set_checkOptions=function(t){yY=t};wn._DBG_set_checkMethod=function(t){PD=t};wn._DBG_clearHistory=function(){CY="",rE=[]};wn.setDefaultOptions=function(t){return mY=Co(!0,t),Co(!0)};wn.question=function(t,e){return fBe(Co(Co(!0,e),{display:t}))};wn.prompt=function(t){var e=Co(!0,t);return e.display=e.prompt,fBe(e)};wn.keyIn=function(t,e){var r=Co(Co(!0,e),{display:t,keyIn:!0,keepWhitespace:!0});return r.limitSrc=r.limit.filter(function(s){var a=typeof s;return a==="string"||a==="number"}).map(function(s){return D1(s+"",lBe)}),r.limit=BY(r.limitSrc.join("")),["trueValue","falseValue"].forEach(function(s){r[s]=r[s].reduce(function(a,n){var l=typeof n;return l==="string"||l==="number"?a=a.concat((n+"").split("")):a.push(n),a},[])}),r.display=D1(r.display+"",function(s){return cBe(s,r)}),uBe(EY(r),r)};wn.questionEMail=function(t,e){return t==null&&(t="Input e-mail address: "),wn.question(t,Co({hideEchoBack:!1,limit:/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,limitMessage:"Input valid e-mail address, please.",trueValue:null,falseValue:null},e,{keepWhitespace:!1,cd:!1}))};wn.questionNewPassword=function(t,e){var r,s,a,n=Co({hideEchoBack:!0,mask:"*",limitMessage:`It can include: $<charlist>
And the length must be: $<length>`,trueValue:null,falseValue:null,caseSensitive:!0},e,{history:!1,cd:!1,phContent:function(D){return D==="charlist"?r.text:D==="length"?s+"..."+a:null}}),l,f,h,A,m,w,v;for(e=e||{},l=D1(e.charlist?e.charlist+"":"$<!-~>",lBe),(isNaN(s=parseInt(e.min,10))||typeof s!="number")&&(s=12),(isNaN(a=parseInt(e.max,10))||typeof a!="number")&&(a=24),A=new RegExp("^["+BY(l)+"]{"+s+","+a+"}$"),r=oBe([l],n.caseSensitive,!0),r.text=aBe(r.values,r.suppressed),f=e.confirmMessage!=null?e.confirmMessage:"Reinput a same one to confirm it: ",h=e.unmatchMessage!=null?e.unmatchMessage:"It differs from first one. Hit only the Enter key if you want to retry from first one.",t==null&&(t="Input new password: "),m=n.limitMessage;!v;)n.limit=A,n.limitMessage=m,w=wn.question(t,n),n.limit=[w,""],n.limitMessage=h,v=wn.question(f,n);return w};function hBe(t,e,r){var s;function a(n){return s=r(n),!isNaN(s)&&typeof s=="number"}return wn.question(t,Co({limitMessage:"Input valid number, please."},e,{limit:a,cd:!1})),s}wn.questionInt=function(t,e){return hBe(t,e,function(r){return parseInt(r,10)})};wn.questionFloat=function(t,e){return hBe(t,e,parseFloat)};wn.questionPath=function(t,e){var r,s="",a=Co({hideEchoBack:!1,limitMessage:`$<error(
)>Input valid path, please.$<( Min:)min>$<( Max:)max>`,history:!0,cd:!0},e,{keepWhitespace:!1,limit:function(n){var l,f,h;n=vY(n,!0),s="";function A(m){m.split(/\/|\\/).reduce(function(w,v){var D=dg.resolve(w+=v+dg.sep);if(!ki.existsSync(D))ki.mkdirSync(D);else if(!ki.statSync(D).isDirectory())throw new Error("Non directory already exists: "+D);return w},"")}try{if(l=ki.existsSync(n),r=l?ki.realpathSync(n):dg.resolve(n),!e.hasOwnProperty("exists")&&!l||typeof e.exists=="boolean"&&e.exists!==l)return s=(l?"Already exists":"No such file or directory")+": "+r,!1;if(!l&&e.create&&(e.isDirectory?A(r):(A(dg.dirname(r)),ki.closeSync(ki.openSync(r,"w"))),r=ki.realpathSync(r)),l&&(e.min||e.max||e.isFile||e.isDirectory)){if(f=ki.statSync(r),e.isFile&&!f.isFile())return s="Not file: "+r,!1;if(e.isDirectory&&!f.isDirectory())return s="Not directory: "+r,!1;if(e.min&&f.size<+e.min||e.max&&f.size>+e.max)return s="Size "+f.size+" is out of range: "+r,!1}if(typeof e.validate=="function"&&(h=e.validate(r))!==!0)return typeof h=="string"&&(s=h),!1}catch(m){return s=m+"",!1}return!0},phContent:function(n){return n==="error"?s:n!=="min"&&n!=="max"?null:e.hasOwnProperty(n)?e[n]+"":""}});return e=e||{},t==null&&(t='Input path (you can "cd" and "pwd"): '),wn.question(t,a),r};function ABe(t,e){var r={},s={};return typeof t=="object"?(Object.keys(t).forEach(function(a){typeof t[a]=="function"&&(s[e.caseSensitive?a:a.toLowerCase()]=t[a])}),r.preCheck=function(a){var n;return r.args=wY(a),n=r.args[0]||"",e.caseSensitive||(n=n.toLowerCase()),r.hRes=n!=="_"&&s.hasOwnProperty(n)?s[n].apply(a,r.args.slice(1)):s.hasOwnProperty("_")?s._.apply(a,r.args):null,{res:a,forceNext:!1}},s.hasOwnProperty("_")||(r.limit=function(){var a=r.args[0]||"";return e.caseSensitive||(a=a.toLowerCase()),s.hasOwnProperty(a)})):r.preCheck=function(a){return r.args=wY(a),r.hRes=typeof t=="function"?t.apply(a,r.args):!0,{res:a,forceNext:!1}},r}wn.promptCL=function(t,e){var r=Co({hideEchoBack:!1,limitMessage:"Requested command is not available.",caseSensitive:!1,history:!0},e),s=ABe(t,r);return r.limit=s.limit,r.preCheck=s.preCheck,wn.prompt(r),s.args};wn.promptLoop=function(t,e){for(var r=Co({hideEchoBack:!1,trueValue:null,falseValue:null,caseSensitive:!1,history:!0},e);!t(wn.prompt(r)););};wn.promptCLLoop=function(t,e){var r=Co({hideEchoBack:!1,limitMessage:"Requested command is not available.",caseSensitive:!1,history:!0},e),s=ABe(t,r);for(r.limit=s.limit,r.preCheck=s.preCheck;wn.prompt(r),!s.hRes;);};wn.promptSimShell=function(t){return wn.prompt(Co({hideEchoBack:!1,history:!0},t,{prompt:function(){return nE?"$<cwd>>":(process.env.USER||"")+(process.env.HOSTNAME?"@"+process.env.HOSTNAME.replace(/\..*$/,""):"")+":$<cwdHome>$ "}()}))};function pBe(t,e,r){var s;return t==null&&(t="Are you sure? "),(!e||e.guide!==!1)&&(t+="")&&(t=t.replace(/\s*:?\s*$/,"")+" [y/n]: "),s=wn.keyIn(t,Co(e,{hideEchoBack:!1,limit:r,trueValue:"y",falseValue:"n",caseSensitive:!1})),typeof s=="boolean"?s:""}wn.keyInYN=function(t,e){return pBe(t,e)};wn.keyInYNStrict=function(t,e){return pBe(t,e,"yn")};wn.keyInPause=function(t,e){t==null&&(t="Continue..."),(!e||e.guide!==!1)&&(t+="")&&(t=t.replace(/\s+$/,"")+" (Hit any key)"),wn.keyIn(t,Co({limit:null},e,{hideEchoBack:!0,mask:""}))};wn.keyInSelect=function(t,e,r){var s=Co({hideEchoBack:!1},r,{trueValue:null,falseValue:null,caseSensitive:!1,phContent:function(h){return h==="itemsCount"?t.length+"":h==="firstItem"?(t[0]+"").trim():h==="lastItem"?(t[t.length-1]+"").trim():null}}),a="",n={},l=49,f=`
`;if(!Array.isArray(t)||!t.length||t.length>35)throw"`items` must be Array (max length: 35).";return t.forEach(function(h,A){var m=String.fromCharCode(l);a+=m,n[m]=A,f+="["+m+"] "+(h+"").trim()+`
`,l=l===57?97:l+1}),(!r||r.cancel!==!1)&&(a+="0",n[0]=-1,f+="[0] "+(r&&r.cancel!=null&&typeof r.cancel!="boolean"?(r.cancel+"").trim():"CANCEL")+`
`),s.limit=a,f+=`
`,e==null&&(e="Choose one from list: "),(e+="")&&((!r||r.guide!==!1)&&(e=e.replace(/\s*:?\s*$/,"")+" [$<limit>]: "),f+=e),n[wn.keyIn(f,s).toLowerCase()]};wn.getRawInput=function(){return XO};function xD(t,e){var r;return e.length&&(r={},r[t]=e[0]),wn.setDefaultOptions(r)[t]}wn.setPrint=function(){return xD("print",arguments)};wn.setPrompt=function(){return xD("prompt",arguments)};wn.setEncoding=function(){return xD("encoding",arguments)};wn.setMask=function(){return xD("mask",arguments)};wn.setBufferSize=function(){return xD("bufferSize",arguments)}});var SY=H((Bur,Nl)=>{(function(){var t={major:0,minor:2,patch:66,status:"beta"};tau_file_system={files:{},open:function(C,P,E){var F=tau_file_system.files[C];if(!F){if(E==="read")return null;F={path:C,text:"",type:P,get:function(Z,X){return X===this.text.length||X>this.text.length?"end_of_file":this.text.substring(X,X+Z)},put:function(Z,X){return X==="end_of_file"?(this.text+=Z,!0):X==="past_end_of_file"?null:(this.text=this.text.substring(0,X)+Z+this.text.substring(X+Z.length),!0)},get_byte:function(Z){if(Z==="end_of_stream")return-1;var X=Math.floor(Z/2);if(this.text.length<=X)return-1;var re=n(this.text[Math.floor(Z/2)],0);return Z%2===0?re&255:re/256>>>0},put_byte:function(Z,X){var re=X==="end_of_stream"?this.text.length:Math.floor(X/2);if(this.text.length<re)return null;var ce=this.text.length===re?-1:n(this.text[Math.floor(X/2)],0);return X%2===0?(ce=ce/256>>>0,ce=(ce&255)<<8|Z&255):(ce=ce&255,ce=(Z&255)<<8|ce&255),this.text.length===re?this.text+=l(ce):this.text=this.text.substring(0,re)+l(ce)+this.text.substring(re+1),!0},flush:function(){return!0},close:function(){var Z=tau_file_system.files[this.path];return Z?!0:null}},tau_file_system.files[C]=F}return E==="write"&&(F.text=""),F}},tau_user_input={buffer:"",get:function(C,P){for(var E;tau_user_input.buffer.length<C;)E=window.prompt(),E&&(tau_user_input.buffer+=E);return E=tau_user_input.buffer.substr(0,C),tau_user_input.buffer=tau_user_input.buffer.substr(C),E}},tau_user_output={put:function(C,P){return console.log(C),!0},flush:function(){return!0}},nodejs_file_system={open:function(C,P,E){var F=Ae("fs"),Z=F.openSync(C,E[0]);return E==="read"&&!F.existsSync(C)?null:{get:function(X,re){var ce=new Buffer(X);return F.readSync(Z,ce,0,X,re),ce.toString()},put:function(X,re){var ce=Buffer.from(X);if(re==="end_of_file")F.writeSync(Z,ce);else{if(re==="past_end_of_file")return null;F.writeSync(Z,ce,0,ce.length,re)}return!0},get_byte:function(X){return null},put_byte:function(X,re){return null},flush:function(){return!0},close:function(){return F.closeSync(Z),!0}}}},nodejs_user_input={buffer:"",get:function(C,P){for(var E,F=dBe();nodejs_user_input.buffer.length<C;)nodejs_user_input.buffer+=F.question();return E=nodejs_user_input.buffer.substr(0,C),nodejs_user_input.buffer=nodejs_user_input.buffer.substr(C),E}},nodejs_user_output={put:function(C,P){return process.stdout.write(C),!0},flush:function(){return!0}};var e;Array.prototype.indexOf?e=function(C,P){return C.indexOf(P)}:e=function(C,P){for(var E=C.length,F=0;F<E;F++)if(P===C[F])return F;return-1};var r=function(C,P){if(C.length!==0){for(var E=C[0],F=C.length,Z=1;Z<F;Z++)E=P(E,C[Z]);return E}},s;Array.prototype.map?s=function(C,P){return C.map(P)}:s=function(C,P){for(var E=[],F=C.length,Z=0;Z<F;Z++)E.push(P(C[Z]));return E};var a;Array.prototype.filter?a=function(C,P){return C.filter(P)}:a=function(C,P){for(var E=[],F=C.length,Z=0;Z<F;Z++)P(C[Z])&&E.push(C[Z]);return E};var n;String.prototype.codePointAt?n=function(C,P){return C.codePointAt(P)}:n=function(C,P){return C.charCodeAt(P)};var l;String.fromCodePoint?l=function(){return String.fromCodePoint.apply(null,arguments)}:l=function(){return String.fromCharCode.apply(null,arguments)};var f=0,h=1,A=/(\\a)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\v)|\\x([0-9a-fA-F]+)\\|\\([0-7]+)\\|(\\\\)|(\\')|('')|(\\")|(\\`)|(\\.)|(.)/g,m={"\\a":7,"\\b":8,"\\f":12,"\\n":10,"\\r":13,"\\t":9,"\\v":11};function w(C){var P=[],E=!1;return C.replace(A,function(F,Z,X,re,ce,ke,Le,pt,St,er,ur,Ht,Cn,Ur,kr,_,Ue){switch(!0){case St!==void 0:return P.push(parseInt(St,16)),"";case er!==void 0:return P.push(parseInt(er,8)),"";case ur!==void 0:case Ht!==void 0:case Cn!==void 0:case Ur!==void 0:case kr!==void 0:return P.push(n(F.substr(1),0)),"";case Ue!==void 0:return P.push(n(Ue,0)),"";case _!==void 0:E=!0;default:return P.push(m[F]),""}}),E?null:P}function v(C,P){var E="";if(C.length<2)return C;try{C=C.replace(/\\([0-7]+)\\/g,function(re,ce){return l(parseInt(ce,8))}),C=C.replace(/\\x([0-9a-fA-F]+)\\/g,function(re,ce){return l(parseInt(ce,16))})}catch{return null}for(var F=0;F<C.length;F++){var Z=C.charAt(F),X=C.charAt(F+1);if(Z===P&&X===P)F++,E+=P;else if(Z==="\\")if(["a","b","f","n","r","t","v","'",'"',"\\","a","\b","\f",`
`,"\r"," ","\v"].indexOf(X)!==-1)switch(F+=1,X){case"a":E+="a";break;case"b":E+="\b";break;case"f":E+="\f";break;case"n":E+=`
`;break;case"r":E+="\r";break;case"t":E+=" ";break;case"v":E+="\v";break;case"'":E+="'";break;case'"':E+='"';break;case"\\":E+="\\";break}else return null;else E+=Z}return E}function D(C){for(var P="",E=0;E<C.length;E++)switch(C.charAt(E)){case"'":P+="\\'";break;case"\\":P+="\\\\";break;case"\b":P+="\\b";break;case"\f":P+="\\f";break;case`
`:P+="\\n";break;case"\r":P+="\\r";break;case" ":P+="\\t";break;case"\v":P+="\\v";break;default:P+=C.charAt(E);break}return P}function I(C){var P=C.substr(2);switch(C.substr(0,2).toLowerCase()){case"0x":return parseInt(P,16);case"0b":return parseInt(P,2);case"0o":return parseInt(P,8);case"0'":return w(P)[0];default:return parseFloat(C)}}var R={whitespace:/^\s*(?:(?:%.*)|(?:\/\*(?:\n|\r|.)*?\*\/)|(?:\s+))\s*/,variable:/^(?:[A-Z_][a-zA-Z0-9_]*)/,atom:/^(\!|,|;|[a-z][0-9a-zA-Z_]*|[#\$\&\*\+\-\.\/\:\<\=\>\?\@\^\~\\]+|'(?:[^']*?(?:\\(?:x?\d+)?\\)*(?:'')*(?:\\')*)*')/,number:/^(?:0o[0-7]+|0x[0-9a-fA-F]+|0b[01]+|0'(?:''|\\[abfnrtv\\'"`]|\\x?\d+\\|[^\\])|\d+(?:\.\d+(?:[eE][+-]?\d+)?)?)/,string:/^(?:"([^"]|""|\\")*"|`([^`]|``|\\`)*`)/,l_brace:/^(?:\[)/,r_brace:/^(?:\])/,l_bracket:/^(?:\{)/,r_bracket:/^(?:\})/,bar:/^(?:\|)/,l_paren:/^(?:\()/,r_paren:/^(?:\))/};function N(C,P){return C.get_flag("char_conversion").id==="on"?P.replace(/./g,function(E){return C.get_char_conversion(E)}):P}function U(C){this.thread=C,this.text="",this.tokens=[]}U.prototype.set_last_tokens=function(C){return this.tokens=C},U.prototype.new_text=function(C){this.text=C,this.tokens=[]},U.prototype.get_tokens=function(C){var P,E=0,F=0,Z=0,X=[],re=!1;if(C){var ce=this.tokens[C-1];E=ce.len,P=N(this.thread,this.text.substr(ce.len)),F=ce.line,Z=ce.start}else P=this.text;if(/^\s*$/.test(P))return null;for(;P!=="";){var ke=[],Le=!1;if(/^\n/.exec(P)!==null){F++,Z=0,E++,P=P.replace(/\n/,""),re=!0;continue}for(var pt in R)if(R.hasOwnProperty(pt)){var St=R[pt].exec(P);St&&ke.push({value:St[0],name:pt,matches:St})}if(!ke.length)return this.set_last_tokens([{value:P,matches:[],name:"lexical",line:F,start:Z}]);var ce=r(ke,function(Ur,kr){return Ur.value.length>=kr.value.length?Ur:kr});switch(ce.start=Z,ce.line=F,P=P.replace(ce.value,""),Z+=ce.value.length,E+=ce.value.length,ce.name){case"atom":ce.raw=ce.value,ce.value.charAt(0)==="'"&&(ce.value=v(ce.value.substr(1,ce.value.length-2),"'"),ce.value===null&&(ce.name="lexical",ce.value="unknown escape sequence"));break;case"number":ce.float=ce.value.substring(0,2)!=="0x"&&ce.value.match(/[.eE]/)!==null&&ce.value!=="0'.",ce.value=I(ce.value),ce.blank=Le;break;case"string":var er=ce.value.charAt(0);ce.value=v(ce.value.substr(1,ce.value.length-2),er),ce.value===null&&(ce.name="lexical",ce.value="unknown escape sequence");break;case"whitespace":var ur=X[X.length-1];ur&&(ur.space=!0),Le=!0;continue;case"r_bracket":X.length>0&&X[X.length-1].name==="l_bracket"&&(ce=X.pop(),ce.name="atom",ce.value="{}",ce.raw="{}",ce.space=!1);break;case"r_brace":X.length>0&&X[X.length-1].name==="l_brace"&&(ce=X.pop(),ce.name="atom",ce.value="[]",ce.raw="[]",ce.space=!1);break}ce.len=E,X.push(ce),Le=!1}var Ht=this.set_last_tokens(X);return Ht.length===0?null:Ht};function V(C,P,E,F,Z){if(!P[E])return{type:f,value:x.error.syntax(P[E-1],"expression expected",!0)};var X;if(F==="0"){var re=P[E];switch(re.name){case"number":return{type:h,len:E+1,value:new x.type.Num(re.value,re.float)};case"variable":return{type:h,len:E+1,value:new x.type.Var(re.value)};case"string":var ce;switch(C.get_flag("double_quotes").id){case"atom":ce=new j(re.value,[]);break;case"codes":ce=new j("[]",[]);for(var ke=re.value.length-1;ke>=0;ke--)ce=new j(".",[new x.type.Num(n(re.value,ke),!1),ce]);break;case"chars":ce=new j("[]",[]);for(var ke=re.value.length-1;ke>=0;ke--)ce=new j(".",[new x.type.Term(re.value.charAt(ke),[]),ce]);break}return{type:h,len:E+1,value:ce};case"l_paren":var Ht=V(C,P,E+1,C.__get_max_priority(),!0);return Ht.type!==h?Ht:P[Ht.len]&&P[Ht.len].name==="r_paren"?(Ht.len++,Ht):{type:f,derived:!0,value:x.error.syntax(P[Ht.len]?P[Ht.len]:P[Ht.len-1],") or operator expected",!P[Ht.len])};case"l_bracket":var Ht=V(C,P,E+1,C.__get_max_priority(),!0);return Ht.type!==h?Ht:P[Ht.len]&&P[Ht.len].name==="r_bracket"?(Ht.len++,Ht.value=new j("{}",[Ht.value]),Ht):{type:f,derived:!0,value:x.error.syntax(P[Ht.len]?P[Ht.len]:P[Ht.len-1],"} or operator expected",!P[Ht.len])}}var Le=ee(C,P,E,Z);return Le.type===h||Le.derived||(Le=te(C,P,E),Le.type===h||Le.derived)?Le:{type:f,derived:!1,value:x.error.syntax(P[E],"unexpected token")}}var pt=C.__get_max_priority(),St=C.__get_next_priority(F),er=E;if(P[E].name==="atom"&&P[E+1]&&(P[E].space||P[E+1].name!=="l_paren")){var re=P[E++],ur=C.__lookup_operator_classes(F,re.value);if(ur&&ur.indexOf("fy")>-1){var Ht=V(C,P,E,F,Z);if(Ht.type!==f)return re.value==="-"&&!re.space&&x.type.is_number(Ht.value)?{value:new x.type.Num(-Ht.value.value,Ht.value.is_float),len:Ht.len,type:h}:{value:new x.type.Term(re.value,[Ht.value]),len:Ht.len,type:h};X=Ht}else if(ur&&ur.indexOf("fx")>-1){var Ht=V(C,P,E,St,Z);if(Ht.type!==f)return{value:new x.type.Term(re.value,[Ht.value]),len:Ht.len,type:h};X=Ht}}E=er;var Ht=V(C,P,E,St,Z);if(Ht.type===h){E=Ht.len;var re=P[E];if(P[E]&&(P[E].name==="atom"&&C.__lookup_operator_classes(F,re.value)||P[E].name==="bar"&&C.__lookup_operator_classes(F,"|"))){var Cn=St,Ur=F,ur=C.__lookup_operator_classes(F,re.value);iLine truncated
`;P+=`
`;for(key in this.rules)for(E=0;E<this.rules[key].length;E++)P+=this.rules[key][E].toString(C),P+=`
`;return P},De.prototype.clone=function(){return new De(this.id)},Te.prototype.clone=function(){return new Te(this.value,this.is_float)},j.prototype.clone=function(){return new j(this.id,s(this.args,function(C){return C.clone()}))},Ne.prototype.clone=function(){return new Stram(this.stream,this.mode,this.alias,this.type,this.reposition,this.eof_action)},Fe.prototype.clone=function(){var C={};for(var P in this.links)this.links.hasOwnProperty(P)&&(C[P]=this.links[P].clone());return new Fe(C)},Pe.prototype.clone=function(){return new Pe(this.goal.clone(),this.substitution.clone(),this.parent)},He.prototype.clone=function(){return new He(this.head.clone(),this.body!==null?this.body.clone():null)},De.prototype.equals=function(C){return x.type.is_variable(C)&&this.id===C.id},Te.prototype.equals=function(C){return x.type.is_number(C)&&this.value===C.value&&this.is_float===C.is_float},j.prototype.equals=function(C){if(!x.type.is_term(C)||this.indicator!==C.indicator)return!1;for(var P=0;P<this.args.length;P++)if(!this.args[P].equals(C.args[P]))return!1;return!0},Ne.prototype.equals=function(C){return x.type.is_stream(C)&&this.id===C.id},Fe.prototype.equals=function(C){var P;if(!x.type.is_substitution(C))return!1;for(P in this.links)if(this.links.hasOwnProperty(P)&&(!C.links[P]||!this.links[P].equals(C.links[P])))return!1;for(P in C.links)if(C.links.hasOwnProperty(P)&&!this.links[P])return!1;return!0},Pe.prototype.equals=function(C){return x.type.is_state(C)&&this.goal.equals(C.goal)&&this.substitution.equals(C.substitution)&&this.parent===C.parent},He.prototype.equals=function(C){return x.type.is_rule(C)&&this.head.equals(C.head)&&(this.body===null&&C.body===null||this.body!==null&&this.body.equals(C.body))},De.prototype.rename=function(C){return C.get_free_variable(this)},Te.prototype.rename=function(C){return this},j.prototype.rename=function(C){return new j(this.id,s(this.args,function(P){return P.rename(C)}))},Ne.prototype.rename=function(C){return this},He.prototype.rename=function(C){return new He(this.head.rename(C),this.body!==null?this.body.rename(C):null)},De.prototype.variables=function(){return[this.id]},Te.prototype.variables=function(){return[]},j.prototype.variables=function(){return[].concat.apply([],s(this.args,function(C){return C.variables()}))},Ne.prototype.variables=function(){return[]},He.prototype.variables=function(){return this.body===null?this.head.variables():this.head.variables().concat(this.body.variables())},De.prototype.apply=function(C){return C.lookup(this.id)?C.lookup(this.id):this},Te.prototype.apply=function(C){return this},j.prototype.apply=function(C){if(this.indicator==="./2"){for(var P=[],E=this;E.indicator==="./2";)P.push(E.args[0].apply(C)),E=E.args[1];for(var F=E.apply(C),Z=P.length-1;Z>=0;Z--)F=new j(".",[P[Z],F]);return F}return new j(this.id,s(this.args,function(X){return X.apply(C)}),this.ref)},Ne.prototype.apply=function(C){return this},He.prototype.apply=function(C){return new He(this.head.apply(C),this.body!==null?this.body.apply(C):null)},Fe.prototype.apply=function(C){var P,E={};for(P in this.links)this.links.hasOwnProperty(P)&&(E[P]=this.links[P].apply(C));return new Fe(E)},j.prototype.select=function(){for(var C=this;C.indicator===",/2";)C=C.args[0];return C},j.prototype.replace=function(C){return this.indicator===",/2"?this.args[0].indicator===",/2"?new j(",",[this.args[0].replace(C),this.args[1]]):C===null?this.args[1]:new j(",",[C,this.args[1]]):C},j.prototype.search=function(C){if(x.type.is_term(C)&&C.ref!==void 0&&this.ref===C.ref)return!0;for(var P=0;P<this.args.length;P++)if(x.type.is_term(this.args[P])&&this.args[P].search(C))return!0;return!1},Qe.prototype.get_current_input=function(){return this.current_input},ft.prototype.get_current_input=function(){return this.session.get_current_input()},Qe.prototype.get_current_output=function(){return this.current_output},ft.prototype.get_current_output=function(){return this.session.get_current_output()},Qe.prototype.set_current_input=function(C){this.current_input=C},ft.prototype.set_current_input=function(C){return this.session.set_current_input(C)},Qe.prototype.set_current_output=function(C){this.current_input=C},ft.prototype.set_current_output=function(C){return this.session.set_current_output(C)},Qe.prototype.get_stream_by_alias=function(C){return this.streams[C]},ft.prototype.get_stream_by_alias=function(C){return this.session.get_stream_by_alias(C)},Qe.prototype.file_system_open=function(C,P,E){return this.file_system.open(C,P,E)},ft.prototype.file_system_open=function(C,P,E){return this.session.file_system_open(C,P,E)},Qe.prototype.get_char_conversion=function(C){return this.__char_conversion[C]||C},ft.prototype.get_char_conversion=function(C){return this.session.get_char_conversion(C)},Qe.prototype.parse=function(C){return this.thread.parse(C)},ft.prototype.parse=function(C){var P=new U(this);P.new_text(C);var E=P.get_tokens();if(E===null)return!1;var F=V(this,E,0,this.__get_max_priority(),!1);return F Line truncated
`,[])])])),P.substitution,P)])},"nl/1":function(C,P,E){var F=E.args[0];C.prepend([new Pe(P.goal.replace(new j("put_char",[F,new j(`
`,[])])),P.substitution,P)])},"get_byte/1":function(C,P,E){var F=E.args[0];C.prepend([new Pe(P.goal.replace(new j(",",[new j("current_input",[new De("S")]),new j("get_byte",[new De("S"),F])])),P.substitution,P)])},"get_byte/2":function(C,P,E){var F=E.args[0],Z=E.args[1],X=x.type.is_stream(F)?F:C.get_stream_by_alias(F.id);if(x.type.is_variable(F))C.throw_error(x.error.instantiation(E.indicator));else if(!x.type.is_variable(Z)&&!x.type.is_byte(Z))C.throw_error(x.error.type("in_byte",char,E.indicator));else if(!x.type.is_stream(F)&&!x.type.is_atom(F))C.throw_error(x.error.domain("stream_or_alias",F,E.indicator));else if(!x.type.is_stream(X)||X.stream===null)C.throw_error(x.error.existence("stream",F,E.indicator));else if(X.output)C.throw_error(x.error.permission("input","stream",F,E.indicator));else if(X.type==="text")C.throw_error(x.error.permission("input","text_stream",F,E.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")C.throw_error(x.error.permission("input","past_end_of_stream",F,E.indicator));else{var re;if(X.position==="end_of_stream")re="end_of_file",X.position="past_end_of_stream";else{if(re=X.stream.get_byte(X.position),re===null){C.throw_error(x.error.representation("byte",E.indicator));return}X.position++}C.prepend([new Pe(P.goal.replace(new j("=",[new Te(re,!1),Z])),P.substitution,P)])}},"peek_byte/1":function(C,P,E){var F=E.args[0];C.prepend([new Pe(P.goal.replace(new j(",",[new j("current_input",[new De("S")]),new j("peek_byte",[new De("S"),F])])),P.substitution,P)])},"peek_byte/2":function(C,P,E){var F=E.args[0],Z=E.args[1],X=x.type.is_stream(F)?F:C.get_stream_by_alias(F.id);if(x.type.is_variable(F))C.throw_error(x.error.instantiation(E.indicator));else if(!x.type.is_variable(Z)&&!x.type.is_byte(Z))C.throw_error(x.error.type("in_byte",char,E.indicator));else if(!x.type.is_stream(F)&&!x.type.is_atom(F))C.throw_error(x.error.domain("stream_or_alias",F,E.indicator));else if(!x.type.is_stream(X)||X.stream===null)C.throw_error(x.error.existence("stream",F,E.indicator));else if(X.output)C.throw_error(x.error.permission("input","stream",F,E.indicator));else if(X.type==="text")C.throw_error(x.error.permission("input","text_stream",F,E.indicator));else if(X.position==="past_end_of_stream"&&X.eof_action==="error")C.throw_error(x.error.permission("input","past_end_of_stream",F,E.indicator));else{var re;if(X.position==="end_of_stream")re="end_of_file",X.position="past_end_of_stream";else if(re=X.stream.get_byte(X.position),re===null){C.throw_error(x.error.representation("byte",E.indicator));return}C.prepend([new Pe(P.goal.replace(new j("=",[new Te(re,!1),Z])),P.substitution,P)])}},"put_byte/1":function(C,P,E){var F=E.args[0];C.prepend([new Pe(P.goal.replace(new j(",",[new j("current_output",[new De("S")]),new j("put_byte",[new De("S"),F])])),P.substitution,P)])},"put_byte/2":function(C,P,E){var F=E.args[0],Z=E.args[1],X=x.type.is_stream(F)?F:C.get_stream_by_alias(F.id);x.type.is_variable(F)||x.type.is_variable(Z)?C.throw_error(x.error.instantiation(E.indicator)):x.type.is_byte(Z)?!x.type.is_variable(F)&&!x.type.is_stream(F)&&!x.type.is_atom(F)?C.throw_error(x.error.domain("stream_or_alias",F,E.indicator)):!x.type.is_stream(X)||X.stream===null?C.throw_error(x.error.existence("stream",F,E.indicator)):X.input?C.throw_error(x.error.permission("output","stream",F,E.indicator)):X.type==="text"?C.throw_error(x.error.permission("output","text_stream",F,E.indicator)):X.stream.put_byte(Z.value,X.position)&&(typeof X.position=="number"&&X.position++,C.success(P)):C.throw_error(x.error.type("byte",Z,E.indicator))},"read/1":function(C,P,E){var F=E.args[0];C.prepend([new Pe(P.goal.replace(new j(",",[new j("current_input",[new De("S")]),new j("read_term",[new De("S"),F,new j("[]",[])])])),P.substitution,P)])},"read/2":function(C,P,E){var F=E.args[0],Z=E.args[1];C.prepend([new Pe(P.goal.replace(new j("read_term",[F,Z,new j("[]",[])])),P.substitution,P)])},"read_term/2":function(C,P,E){var F=E.args[0],Z=E.args[1];C.prepend([new Pe(P.goal.replace(new j(",",[new j("current_input",[new De("S")]),new j("read_term",[new De("S"),F,Z])])),P.substitution,P)])},"read_term/3":function(C,P,E){var F=E.args[0],Z=E.args[1],X=E.args[2],re=x.type.is_stream(F)?F:C.get_stream_by_alias(F.id);if(x.type.is_variable(F)||x.type.is_variable(X))C.throw_error(x.error.instantiation(E.indicator));else if(!x.type.is_list(X))C.throw_error(x.error.type("list",X,E.indicator));else if(!x.type.is_stream(F)&&!x.type.is_atom(F))C.throw_error(x.error.domain("stream_or_alias",F,E.indicator));else if(!x.type.is_stream(re)||re.stream===null)C.throw_error(x.error.existence("stream",F,E.indicator));else if(re.output)C.throw_error(x.error.permission("input","stream",F,E.indicator));else if(re.type==="binary")C.throw_error(x.error.permission("input","binary_stream",F,E.indicator));else if(re.position==="past_end_of_stream"&&re.eof_action==="error")C.throw_error(x.error.permission("input","past_end_of_stream",F,E.indicator));else{for(v Line truncated
`;for(let r of this.project.workspacesByCwd.values()){let s=r.relativeCwd;e+=`workspace(${mg(s)}).
`,e+=`workspace_ident(${mg(s)}, ${mg(G.stringifyIdent(r.anchoredLocator))}).
`,e+=`workspace_version(${mg(s)}, ${mg(r.manifest.version)}).
`;for(let a of wBe)for(let n of r.manifest[a].values())e+=`workspace_has_dependency(${mg(s)}, ${mg(G.stringifyIdent(n))}, ${mg(n.range)}, ${a}).
`}return e+=`workspace(_) :- false.
`,e+=`workspace_ident(_, _) :- false.
`,e+=`workspace_version(_, _) :- false.
`,e+=`workspace_has_dependency(_, _, _, _) :- false.
`,e}getDeclarations(){let e="";return e+=`gen_enforced_dependency(_, _, _, _) :- false.
`,e+=`gen_enforced_field(_, _, _) :- false.
`,e}get fullSource(){return`${this.getProjectDatabase()}
${this.source}
${this.getDeclarations()}`}createSession(){return new DY(this.project,this.fullSource)}async processClassic(){let e=this.createSession();return{enforcedDependencies:await this.genEnforcedDependencies(e),enforcedFields:await this.genEnforcedFields(e)}}async process(){let{enforcedDependencies:e,enforcedFields:r}=await this.processClassic(),s=new Map;for(let{workspace:a,dependencyIdent:n,dependencyRange:l,dependencyType:f}of e){let h=bD([f,G.stringifyIdent(n)]),A=Ye.getMapWithDefault(s,a.cwd);Ye.getMapWithDefault(A,h).set(l??void 0,new Set)}for(let{workspace:a,fieldPath:n,fieldValue:l}of r){let f=bD(n),h=Ye.getMapWithDefault(s,a.cwd);Ye.getMapWithDefault(h,f).set(JSON.parse(l)??void 0,new Set)}return{manifestUpdates:s,reportedErrors:new Map}}async genEnforcedDependencies(e){let r=[];for await(let s of e.makeQuery("workspace(WorkspaceCwd), dependency_type(DependencyType), gen_enforced_dependency(WorkspaceCwd, DependencyIdent, DependencyRange, DependencyType).")){let a=Y.resolve(this.project.cwd,iE(s.links.WorkspaceCwd)),n=iE(s.links.DependencyIdent),l=iE(s.links.DependencyRange),f=iE(s.links.DependencyType);if(a===null||n===null)throw new Error("Invalid rule");let h=this.project.getWorkspaceByCwd(a),A=G.parseIdent(n);r.push({workspace:h,dependencyIdent:A,dependencyRange:l,dependencyType:f})}return Ye.sortMap(r,[({dependencyRange:s})=>s!==null?"0":"1",({workspace:s})=>G.stringifyIdent(s.anchoredLocator),({dependencyIdent:s})=>G.stringifyIdent(s)])}async genEnforcedFields(e){let r=[];for await(let s of e.makeQuery("workspace(WorkspaceCwd), gen_enforced_field(WorkspaceCwd, FieldPath, FieldValue).")){let a=Y.resolve(this.project.cwd,iE(s.links.WorkspaceCwd)),n=iE(s.links.FieldPath),l=yyt(s.links.FieldValue);if(a===null||n===null)throw new Error("Invalid rule");let f=this.project.getWorkspaceByCwd(a);r.push({workspace:f,fieldPath:n,fieldValue:l})}return Ye.sortMap(r,[({workspace:s})=>G.stringifyIdent(s.anchoredLocator),({fieldPath:s})=>s])}async*query(e){let r=this.createSession();for await(let s of r.makeQuery(e)){let a={};for(let[n,l]of Object.entries(s.links))n!=="_"&&(a[n]=iE(l));yield a}}}});var QBe=H(rL=>{"use strict";Object.defineProperty(rL,"__esModule",{value:!0});function WD(t){let e=[...t.caches],r=e.shift();return r===void 0?TBe():{get(s,a,n={miss:()=>Promise.resolve()}){return r.get(s,a,n).catch(()=>WD({caches:e}).get(s,a,n))},set(s,a){return r.set(s,a).catch(()=>WD({caches:e}).set(s,a))},delete(s){return r.delete(s).catch(()=>WD({caches:e}).delete(s))},clear(){return r.clear().catch(()=>WD({caches:e}).clear())}}}function TBe(){return{get(t,e,r={miss:()=>Promise.resolve()}){return e().then(a=>Promise.all([a,r.miss(a)])).then(([a])=>a)},set(t,e){return Promise.resolve(e)},delete(t){return Promise.resolve()},clear(){return Promise.resolve()}}}rL.createFallbackableCache=WD;rL.createNullCache=TBe});var NBe=H((oAr,FBe)=>{FBe.exports=QBe()});var OBe=H(jY=>{"use strict";Object.defineProperty(jY,"__esModule",{value:!0});function Lyt(t={serializable:!0}){let e={};return{get(r,s,a={miss:()=>Promise.resolve()}){let n=JSON.stringify(r);if(n in e)return Promise.resolve(t.serializable?JSON.parse(e[n]):e[n]);let l=s(),f=a&&a.miss||(()=>Promise.resolve());return l.then(h=>f(h)).then(()=>l)},set(r,s){return e[JSON.stringify(r)]=t.serializable?JSON.stringify(s):s,Promise.resolve(s)},delete(r){return delete e[JSON.stringify(r)],Promise.resolve()},clear(){return e={},Promise.resolve()}}}jY.createInMemoryCache=Lyt});var _Be=H((cAr,LBe)=>{LBe.exports=OBe()});var UBe=H(qf=>{"use strict";Object.defineProperty(qf,"__esModule",{value:!0});function _yt(t,e,r){let s={"x-algolia-api-key":r,"x-algolia-application-id":e};return{headers(){return t===GY.WithinHeaders?s:{}},queryParameters(){return t===GY.WithinQueryParameters?s:{}}}}function Myt(t){let e=0,r=()=>(e++,new Promise(s=>{setTimeout(()=>{s(t(r))},Math.min(100*e,1e3))}));return t(r)}function MBe(t,e=(r,s)=>Promise.resolve()){return Object.assign(t,{wait(r){return MBe(t.then(s=>Promise.all([e(s,r),s])).then(s=>s[1]))}})}function Uyt(t){let e=t.length-1;for(e;e>0;e--){let r=Math.floor(Math.random()*(e+1)),s=t[e];t[e]=t[r],t[r]=s}return t}function Hyt(t,e){return e&&Object.keys(e).forEach(r=>{t[r]=e[r](t)}),t}function jyt(t,...e){let r=0;return t.replace(/%s/g,()=>encodeURIComponent(e[r++]))}var Gyt="4.22.1",qyt=t=>()=>t.transporter.requester.destroy(),GY={WithinQueryParameters:0,WithinHeaders:1};qf.AuthMode=GY;qf.addMethods=Hyt;qf.createAuth=_yt;qf.createRetryablePromise=Myt;qf.createWaitablePromise=MBe;qf.destroy=qyt;qf.encode=jyt;qf.shuffle=Uyt;qf.version=Gyt});var YD=H((uAr,HBe)=>{HBe.exports=UBe()});var jBe=H(qY=>{"use strict";Object.defineProperty(qY,"__esModule",{value:!0});var Vyt={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};qY.MethodEnum=Vyt});var KD=H((hAr,GBe)=>{GBe.exports=jBe()});var ive=H(ds=>{"use strict";Object.defineProperty(ds,"__esModule",{value:!0});var VBe=KD();function VY(t,e){let r=t||{},s=r.data||{};return Object.keys(r).forEach(a=>{["timeout","head Line truncated
`;f!==s&&(s=f,t.write(tbe.default.eraseLines(r)+f),r=f.split(`
`).length)};return n.clear=()=>{t.write(tbe.default.eraseLines(r)),s="",r=0},n.done=()=>{s="",r=0,e||(rbe.default.show(),a=!1)},n};sP.default={create:Mwt}});var sbe=H((epr,Uwt)=>{Uwt.exports=[{name:"AppVeyor",constant:"APPVEYOR",env:"APPVEYOR",pr:"APPVEYOR_PULL_REQUEST_NUMBER"},{name:"Azure Pipelines",constant:"AZURE_PIPELINES",env:"SYSTEM_TEAMFOUNDATIONCOLLECTIONURI",pr:"SYSTEM_PULLREQUEST_PULLREQUESTID"},{name:"Bamboo",constant:"BAMBOO",env:"bamboo_planKey"},{name:"Bitbucket Pipelines",constant:"BITBUCKET",env:"BITBUCKET_COMMIT",pr:"BITBUCKET_PR_ID"},{name:"Bitrise",constant:"BITRISE",env:"BITRISE_IO",pr:"BITRISE_PULL_REQUEST"},{name:"Buddy",constant:"BUDDY",env:"BUDDY_WORKSPACE_ID",pr:"BUDDY_EXECUTION_PULL_REQUEST_ID"},{name:"Buildkite",constant:"BUILDKITE",env:"BUILDKITE",pr:{env:"BUILDKITE_PULL_REQUEST",ne:"false"}},{name:"CircleCI",constant:"CIRCLE",env:"CIRCLECI",pr:"CIRCLE_PULL_REQUEST"},{name:"Cirrus CI",constant:"CIRRUS",env:"CIRRUS_CI",pr:"CIRRUS_PR"},{name:"AWS CodeBuild",constant:"CODEBUILD",env:"CODEBUILD_BUILD_ARN"},{name:"Codeship",constant:"CODESHIP",env:{CI_NAME:"codeship"}},{name:"Drone",constant:"DRONE",env:"DRONE",pr:{DRONE_BUILD_EVENT:"pull_request"}},{name:"dsari",constant:"DSARI",env:"DSARI"},{name:"GitLab CI",constant:"GITLAB",env:"GITLAB_CI"},{name:"GoCD",constant:"GOCD",env:"GO_PIPELINE_LABEL"},{name:"Hudson",constant:"HUDSON",env:"HUDSON_URL"},{name:"Jenkins",constant:"JENKINS",env:["JENKINS_URL","BUILD_ID"],pr:{any:["ghprbPullId","CHANGE_ID"]}},{name:"Magnum CI",constant:"MAGNUM",env:"MAGNUM"},{name:"Netlify CI",constant:"NETLIFY",env:"NETLIFY_BUILD_BASE",pr:{env:"PULL_REQUEST",ne:"false"}},{name:"Sail CI",constant:"SAIL",env:"SAILCI",pr:"SAIL_PULL_REQUEST_NUMBER"},{name:"Semaphore",constant:"SEMAPHORE",env:"SEMAPHORE",pr:"PULL_REQUEST_NUMBER"},{name:"Shippable",constant:"SHIPPABLE",env:"SHIPPABLE",pr:{IS_PULL_REQUEST:"true"}},{name:"Solano CI",constant:"SOLANO",env:"TDDIUM",pr:"TDDIUM_PR_ID"},{name:"Strider CD",constant:"STRIDER",env:"STRIDER"},{name:"TaskCluster",constant:"TASKCLUSTER",env:["TASK_ID","RUN_ID"]},{name:"TeamCity",constant:"TEAMCITY",env:"TEAMCITY_VERSION"},{name:"Travis CI",constant:"TRAVIS",env:"TRAVIS",pr:{env:"TRAVIS_PULL_REQUEST",ne:"false"}}]});var cbe=H(Ol=>{"use strict";var abe=sbe(),nA=process.env;Object.defineProperty(Ol,"_vendors",{value:abe.map(function(t){return t.constant})});Ol.name=null;Ol.isPR=null;abe.forEach(function(t){var e=Array.isArray(t.env)?t.env:[t.env],r=e.every(function(s){return obe(s)});if(Ol[t.constant]=r,r)switch(Ol.name=t.name,typeof t.pr){case"string":Ol.isPR=!!nA[t.pr];break;case"object":"env"in t.pr?Ol.isPR=t.pr.env in nA&&nA[t.pr.env]!==t.pr.ne:"any"in t.pr?Ol.isPR=t.pr.any.some(function(s){return!!nA[s]}):Ol.isPR=obe(t.pr);break;default:Ol.isPR=null}});Ol.isCI=!!(nA.CI||nA.CONTINUOUS_INTEGRATION||nA.BUILD_NUMBER||nA.RUN_ID||Ol.name);function obe(t){return typeof t=="string"?!!nA[t]:Object.keys(t).every(function(e){return nA[e]===t[e]})}});var ube=H((rpr,lbe)=>{"use strict";lbe.exports=cbe().isCI});var hbe=H((npr,fbe)=>{"use strict";var Hwt=t=>{let e=new Set;do for(let r of Reflect.ownKeys(t))e.add([t,r]);while((t=Reflect.getPrototypeOf(t))&&t!==Object.prototype);return e};fbe.exports=(t,{include:e,exclude:r}={})=>{let s=a=>{let n=l=>typeof l=="string"?a===l:l.test(a);return e?e.some(n):r?!r.some(n):!0};for(let[a,n]of Hwt(t.constructor.prototype)){if(n==="constructor"||!s(n))continue;let l=Reflect.getOwnPropertyDescriptor(a,n);l&&typeof l.value=="function"&&(t[n]=t[n].bind(t))}return t}});var ybe=H(gi=>{"use strict";var J1,cP,CL,kK;typeof performance=="object"&&typeof performance.now=="function"?(Abe=performance,gi.unstable_now=function(){return Abe.now()}):(vK=Date,pbe=vK.now(),gi.unstable_now=function(){return vK.now()-pbe});var Abe,vK,pbe;typeof window>"u"||typeof MessageChannel!="function"?(z1=null,SK=null,bK=function(){if(z1!==null)try{var t=gi.unstable_now();z1(!0,t),z1=null}catch(e){throw setTimeout(bK,0),e}},J1=function(t){z1!==null?setTimeout(J1,0,t):(z1=t,setTimeout(bK,0))},cP=function(t,e){SK=setTimeout(t,e)},CL=function(){clearTimeout(SK)},gi.unstable_shouldYield=function(){return!1},kK=gi.unstable_forceFrameRate=function(){}):(dbe=window.setTimeout,gbe=window.clearTimeout,typeof console<"u"&&(mbe=window.cancelAnimationFrame,typeof window.requestAnimationFrame!="function"&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills"),typeof mbe!="function"&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills")),oP=!1,aP=null,EL=-1,DK=5,PK=0,gi.unstable_shouldYield=function(){return gi.unstable_now()>=PK},kK=function(){},gi.unstable_forceFrameRate=function(t){0>t||125<t?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):DK=0<t?Math Line truncated
`+Xu+S}var ve=!1;function Jt(S,b){if(!S||ve)return"";ve=!0;var T=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(b)if(b=function(){throw Error()},Object.defineProperty(b.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(b,[])}catch(wt){var q=wt}Reflect.construct(S,[],b)}else{try{b.call()}catch(wt){q=wt}S.call(b.prototype)}else{try{throw Error()}catch(wt){q=wt}S()}}catch(wt){if(wt&&q&&typeof wt.stack=="string"){for(var z=wt.stack.split(`
`),oe=q.stack.split(`
`),Se=z.length-1,qe=oe.length-1;1<=Se&&0<=qe&&z[Se]!==oe[qe];)qe--;for(;1<=Se&&0<=qe;Se--,qe--)if(z[Se]!==oe[qe]){if(Se!==1||qe!==1)do if(Se--,qe--,0>qe||z[Se]!==oe[qe])return`
`+z[Se].replace(" at new "," at ");while(1<=Se&&0<=qe);break}}}finally{ve=!1,Error.prepareStackTrace=T}return(S=S?S.displayName||S.name:"")?Vl(S):""}var Wl=[],as=-1;function To(S){return{current:S}}function Vt(S){0>as||(S.current=Wl[as],Wl[as]=null,as--)}function ei(S,b){as++,Wl[as]=S.current,S.current=b}var Ha={},As=To(Ha),cs=To(!1),Ic=Ha;function Un(S,b){var T=S.type.contextTypes;if(!T)return Ha;var q=S.stateNode;if(q&&q.__reactInternalMemoizedUnmaskedChildContext===b)return q.__reactInternalMemoizedMaskedChildContext;var z={},oe;for(oe in T)z[oe]=b[oe];return q&&(S=S.stateNode,S.__reactInternalMemoizedUnmaskedChildContext=b,S.__reactInternalMemoizedMaskedChildContext=z),z}function Ei(S){return S=S.childContextTypes,S!=null}function $u(){Vt(cs),Vt(As)}function Ud(S,b,T){if(As.current!==Ha)throw Error(l(168));ei(As,b),ei(cs,T)}function wc(S,b,T){var q=S.stateNode;if(S=b.childContextTypes,typeof q.getChildContext!="function")return T;q=q.getChildContext();for(var z in q)if(!(z in S))throw Error(l(108,d(b)||"Unknown",z));return s({},T,q)}function Cc(S){return S=(S=S.stateNode)&&S.__reactInternalMemoizedMergedChildContext||Ha,Ic=As.current,ei(As,S),ei(cs,cs.current),!0}function Bc(S,b,T){var q=S.stateNode;if(!q)throw Error(l(169));T?(S=wc(S,b,Ic),q.__reactInternalMemoizedMergedChildContext=S,Vt(cs),Vt(As),ei(As,S)):Vt(cs),ei(cs,T)}var it=null,vc=null,ah=n.unstable_now;ah();var Yl=0,Yn=8;function ja(S){if(1&S)return Yn=15,1;if(2&S)return Yn=14,2;if(4&S)return Yn=13,4;var b=24&S;return b!==0?(Yn=12,b):S&32?(Yn=11,32):(b=192&S,b!==0?(Yn=10,b):S&256?(Yn=9,256):(b=3584&S,b!==0?(Yn=8,b):S&4096?(Yn=7,4096):(b=4186112&S,b!==0?(Yn=6,b):(b=62914560&S,b!==0?(Yn=5,b):S&67108864?(Yn=4,67108864):S&134217728?(Yn=3,134217728):(b=805306368&S,b!==0?(Yn=2,b):1073741824&S?(Yn=1,1073741824):(Yn=8,S))))))}function VA(S){switch(S){case 99:return 15;case 98:return 10;case 97:case 96:return 8;case 95:return 2;default:return 0}}function WA(S){switch(S){case 15:case 14:return 99;case 13:case 12:case 11:case 10:return 98;case 9:case 8:case 7:case 6:case 4:case 5:return 97;case 3:case 2:case 1:return 95;case 0:return 90;default:throw Error(l(358,S))}}function Ga(S,b){var T=S.pendingLanes;if(T===0)return Yn=0;var q=0,z=0,oe=S.expiredLanes,Se=S.suspendedLanes,qe=S.pingedLanes;if(oe!==0)q=oe,z=Yn=15;else if(oe=T&134217727,oe!==0){var wt=oe&~Se;wt!==0?(q=ja(wt),z=Yn):(qe&=oe,qe!==0&&(q=ja(qe),z=Yn))}else oe=T&~Se,oe!==0?(q=ja(oe),z=Yn):qe!==0&&(q=ja(qe),z=Yn);if(q===0)return 0;if(q=31-ks(q),q=T&((0>q?0:1<<q)<<1)-1,b!==0&&b!==q&&!(b&Se)){if(ja(b),z<=Yn)return b;Yn=z}if(b=S.entangledLanes,b!==0)for(S=S.entanglements,b&=q;0<b;)T=31-ks(b),z=1<<T,q|=S[T],b&=~z;return q}function ll(S){return S=S.pendingLanes&-1073741825,S!==0?S:S&1073741824?1073741824:0}function rr(S,b){switch(S){case 15:return 1;case 14:return 2;case 12:return S=ti(24&~b),S===0?rr(10,b):S;case 10:return S=ti(192&~b),S===0?rr(8,b):S;case 8:return S=ti(3584&~b),S===0&&(S=ti(4186112&~b),S===0&&(S=512)),S;case 2:return b=ti(805306368&~b),b===0&&(b=268435456),b}throw Error(l(358,S))}function ti(S){return S&-S}function qa(S){for(var b=[],T=0;31>T;T++)b.push(S);return b}function Sc(S,b,T){S.pendingLanes|=b;var q=b-1;S.suspendedLanes&=q,S.pingedLanes&=q,S=S.eventTimes,b=31-ks(b),S[b]=T}var ks=Math.clz32?Math.clz32:zl,Kl=Math.log,ef=Math.LN2;function zl(S){return S===0?32:31-(Kl(S)/ef|0)|0}var bc=n.unstable_runWithPriority,ls=n.unstable_scheduleCallback,Ys=n.unstable_cancelCallback,ul=n.unstable_shouldYield,ch=n.unstable_requestPaint,Jl=n.unstable_now,zi=n.unstable_getCurrentPriorityLevel,ri=n.unstable_ImmediatePriority,Zl=n.unstable_UserBlockingPriority,et=n.unstable_NormalPriority,dt=n.unstable_LowPriority,_t=n.unstable_IdlePriority,Sr={},ne=ch!==void 0?ch:function(){},Be=null,_e=null,bt=!1,xt=Jl(),jt=1e4>xt?Jl:function(){return Jl()-xt};function Ir(){switch(zi()){case ri:return 99;case Zl:return 98;case et:return 97;case dt:return 96;case _t:return 95;default:throw Error(l(332))}}function Nn(S){switch(S){case 99:return ri;case 98:return Zl;case 97:return et;case 96:return dt;case 95:return _t;default:throw Error(l(332))}}function Qi(S,b){return S=Nn(S),bc(S,b)}function ps(S,b,T){return S=Nn(S),ls(S,b,T)}function ni(){if(_e!==null){var S=_e;_e=null,Ys(S)}Dc()}function Dc(){if(!bt&&Be!==null){bt=!0;var S=0;try{var b=Be;Qi(99,function(){for(;S<b.length;S++){var T=b[S];do T=T(!0);while(T!==null)}}),Be=null}catch(T){throw Be!==null&&(Be=Be.slice(S+1)),ls(ri,ni),T}finally{bt=!1}}}var mI=f.ReactCurrentBatchConfig;function Iv(S,b){return S===b&&(S!==0||1/S===1/b)||S!==S&&b!==b}var Xo=typeof Object.is=="function"?Object.is:Iv,yI=Object.prototype.hasOwnProperty;function Hd(S,b){if(Xo(S,b))return!0;if(typeof S!="object"||S===null||typeof b!="object"||b===null)return!1;var T=Object.keys(S),q=Object.keys(b);if(T.length!==q.length)return!1;for(q=0;q<T.length;q++)if(!yI.call(b,T[q])||!Xo(S[T[q]],b[T[q]]))return!1;return!0}function wv(S){switch(S.tag){case 5:return Vl(S.type);case 16:return Vl("Lazy" Line truncated
Error generating stack: `+oe.message+`
`+oe.stack}return{value:S,source:b,stack:z}}function xm(S,b){try{console.error(b.value)}catch(T){setTimeout(function(){throw T})}}var H8=typeof WeakMap=="function"?WeakMap:Map;function bv(S,b,T){T=hl(-1,T),T.tag=3,T.payload={element:null};var q=b.value;return T.callback=function(){UI||(UI=!0,Uv=q),xm(S,b)},T}function km(S,b,T){T=hl(-1,T),T.tag=3;var q=S.type.getDerivedStateFromError;if(typeof q=="function"){var z=b.value;T.payload=function(){return xm(S,b),q(z)}}var oe=S.stateNode;return oe!==null&&typeof oe.componentDidCatch=="function"&&(T.callback=function(){typeof q!="function"&&($l===null?$l=new Set([this]):$l.add(this),xm(S,b));var Se=b.stack;this.componentDidCatch(b.value,{componentStack:Se!==null?Se:""})}),T}var j8=typeof WeakSet=="function"?WeakSet:Set;function Dv(S){var b=S.ref;if(b!==null)if(typeof b=="function")try{b(null)}catch(T){Ch(S,T)}else b.current=null}function xI(S,b){switch(b.tag){case 0:case 11:case 15:case 22:return;case 1:if(b.flags&256&&S!==null){var T=S.memoizedProps,q=S.memoizedState;S=b.stateNode,b=S.getSnapshotBeforeUpdate(b.elementType===b.type?T:$o(b.type,T),q),S.__reactInternalSnapshotBeforeUpdate=b}return;case 3:F&&b.flags&256&&Er(b.stateNode.containerInfo);return;case 5:case 6:case 4:case 17:return}throw Error(l(163))}function e0(S,b){if(b=b.updateQueue,b=b!==null?b.lastEffect:null,b!==null){var T=b=b.next;do{if((T.tag&S)===S){var q=T.destroy;T.destroy=void 0,q!==void 0&&q()}T=T.next}while(T!==b)}}function DR(S,b,T){switch(T.tag){case 0:case 11:case 15:case 22:if(b=T.updateQueue,b=b!==null?b.lastEffect:null,b!==null){S=b=b.next;do{if((S.tag&3)===3){var q=S.create;S.destroy=q()}S=S.next}while(S!==b)}if(b=T.updateQueue,b=b!==null?b.lastEffect:null,b!==null){S=b=b.next;do{var z=S;q=z.next,z=z.tag,z&4&&z&1&&(HR(T,S),Z8(T,S)),S=q}while(S!==b)}return;case 1:S=T.stateNode,T.flags&4&&(b===null?S.componentDidMount():(q=T.elementType===T.type?b.memoizedProps:$o(T.type,b.memoizedProps),S.componentDidUpdate(q,b.memoizedState,S.__reactInternalSnapshotBeforeUpdate))),b=T.updateQueue,b!==null&&wI(T,b,S);return;case 3:if(b=T.updateQueue,b!==null){if(S=null,T.child!==null)switch(T.child.tag){case 5:S=Te(T.child.stateNode);break;case 1:S=T.child.stateNode}wI(T,b,S)}return;case 5:S=T.stateNode,b===null&&T.flags&4&&Ft(S,T.type,T.memoizedProps,T);return;case 6:return;case 4:return;case 12:return;case 13:X&&T.memoizedState===null&&(T=T.alternate,T!==null&&(T=T.memoizedState,T!==null&&(T=T.dehydrated,T!==null&&Zu(T))));return;case 19:case 17:case 20:case 21:case 23:case 24:return}throw Error(l(163))}function PR(S,b){if(F)for(var T=S;;){if(T.tag===5){var q=T.stateNode;b?Nt(q):Xt(T.stateNode,T.memoizedProps)}else if(T.tag===6)q=T.stateNode,b?hr(q):$t(q,T.memoizedProps);else if((T.tag!==23&&T.tag!==24||T.memoizedState===null||T===S)&&T.child!==null){T.child.return=T,T=T.child;continue}if(T===S)break;for(;T.sibling===null;){if(T.return===null||T.return===S)return;T=T.return}T.sibling.return=T.return,T=T.sibling}}function kI(S,b){if(vc&&typeof vc.onCommitFiberUnmount=="function")try{vc.onCommitFiberUnmount(it,b)}catch{}switch(b.tag){case 0:case 11:case 14:case 15:case 22:if(S=b.updateQueue,S!==null&&(S=S.lastEffect,S!==null)){var T=S=S.next;do{var q=T,z=q.destroy;if(q=q.tag,z!==void 0)if(q&4)HR(b,T);else{q=b;try{z()}catch(oe){Ch(q,oe)}}T=T.next}while(T!==S)}break;case 1:if(Dv(b),S=b.stateNode,typeof S.componentWillUnmount=="function")try{S.props=b.memoizedProps,S.state=b.memoizedState,S.componentWillUnmount()}catch(oe){Ch(b,oe)}break;case 5:Dv(b);break;case 4:F?TR(S,b):Z&&Z&&(b=b.stateNode.containerInfo,S=Tn(b),La(b,S))}}function xR(S,b){for(var T=b;;)if(kI(S,T),T.child===null||F&&T.tag===4){if(T===b)break;for(;T.sibling===null;){if(T.return===null||T.return===b)return;T=T.return}T.sibling.return=T.return,T=T.sibling}else T.child.return=T,T=T.child}function RI(S){S.alternate=null,S.child=null,S.dependencies=null,S.firstEffect=null,S.lastEffect=null,S.memoizedProps=null,S.memoizedState=null,S.pendingProps=null,S.return=null,S.updateQueue=null}function kR(S){return S.tag===5||S.tag===3||S.tag===4}function RR(S){if(F){e:{for(var b=S.return;b!==null;){if(kR(b))break e;b=b.return}throw Error(l(160))}var T=b;switch(b=T.stateNode,T.tag){case 5:var q=!1;break;case 3:b=b.containerInfo,q=!0;break;case 4:b=b.containerInfo,q=!0;break;default:throw Error(l(161))}T.flags&16&&(Lt(b),T.flags&=-17);e:t:for(T=S;;){for(;T.sibling===null;){if(T.return===null||kR(T.return)){T=null;break e}T=T.return}for(T.sibling.return=T.return,T=T.sibling;T.tag!==5&&T.tag!==6&&T.tag!==18;){if(T.flags&2||T.child===null||T.tag===4)continue t;T.child.return=T,T=T.child}if(!(T.flags&2)){T=T.stateNode;break e}}q?Pv(S,T,b):xv(S,T,b)}}function Pv(S,b,T){var q=S.tag,z=q===5||q===6;if(z)S=z?S.stateNode:S.stateNode.instance,b?Tt(T,S,b):Bt(T,S);else if(q!==4&&(S=S.child,S!==null))for(Pv(S,b,T),S=S.sibling;S!==null;)Pv(S,b,T),S=S.sibling}function xv(S,b,T){var q=S.tag,z=q===5||q===6;if(z)S=z?S.stateNode:S.stateNode.instance,b?Ze(T,S,b):lt(T,S);els Line truncated
Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.`)}zs!==5&&(zs=2),wt=Pm(wt,qe),gr=Se;do{switch(gr.tag){case 3:oe=wt,gr.flags|=4096,b&=-b,gr.lanes|=b;var Bi=bv(gr,oe,b);II(gr,Bi);break e;case 1:oe=wt;var Zr=gr.type,ii=gr.stateNode;if(!(gr.flags&64)&&(typeof Zr.getDerivedStateFromError=="function"||ii!==null&&typeof ii.componentDidCatch=="function"&&($l===null||!$l.has(ii)))){gr.flags|=4096,b&=-b,gr.lanes|=b;var li=km(gr,oe,b);II(gr,li);break e}}gr=gr.return}while(gr!==null)}UR(T)}catch(yn){b=yn,Cs===T&&T!==null&&(Cs=T=T.return);continue}break}while(!0)}function _R(){var S=_I.current;return _I.current=qt,S===null?qt:S}function Um(S,b){var T=Kr;Kr|=16;var q=_R();Fo===S&&oo===b||i0(S,b);do try{Y8();break}catch(z){LR(S,z)}while(!0);if(gm(),Kr=T,_I.current=q,Cs!==null)throw Error(l(261));return Fo=null,oo=0,zs}function Y8(){for(;Cs!==null;)MR(Cs)}function K8(){for(;Cs!==null&&!ul();)MR(Cs)}function MR(S){var b=qR(S.alternate,S,op);S.memoizedProps=S.pendingProps,b===null?UR(S):Cs=b,Qv.current=null}function UR(S){var b=S;do{var T=b.alternate;if(S=b.return,b.flags&2048){if(T=U8(b),T!==null){T.flags&=2047,Cs=T;return}S!==null&&(S.firstEffect=S.lastEffect=null,S.flags|=2048)}else{if(T=M8(T,b,op),T!==null){Cs=T;return}if(T=b,T.tag!==24&&T.tag!==23||T.memoizedState===null||op&1073741824||!(T.mode&4)){for(var q=0,z=T.child;z!==null;)q|=z.lanes|z.childLanes,z=z.sibling;T.childLanes=q}S!==null&&!(S.flags&2048)&&(S.firstEffect===null&&(S.firstEffect=b.firstEffect),b.lastEffect!==null&&(S.lastEffect!==null&&(S.lastEffect.nextEffect=b.firstEffect),S.lastEffect=b.lastEffect),1<b.flags&&(S.lastEffect!==null?S.lastEffect.nextEffect=b:S.firstEffect=b,S.lastEffect=b))}if(b=b.sibling,b!==null){Cs=b;return}Cs=b=S}while(b!==null);zs===0&&(zs=5)}function ap(S){var b=Ir();return Qi(99,z8.bind(null,S,b)),null}function z8(S,b){do hf();while(Nm!==null);if(Kr&48)throw Error(l(327));var T=S.finishedWork;if(T===null)return null;if(S.finishedWork=null,S.finishedLanes=0,T===S.current)throw Error(l(177));S.callbackNode=null;var q=T.lanes|T.childLanes,z=q,oe=S.pendingLanes&~z;S.pendingLanes=z,S.suspendedLanes=0,S.pingedLanes=0,S.expiredLanes&=z,S.mutableReadLanes&=z,S.entangledLanes&=z,z=S.entanglements;for(var Se=S.eventTimes,qe=S.expirationTimes;0<oe;){var wt=31-ks(oe),cr=1<<wt;z[wt]=0,Se[wt]=-1,qe[wt]=-1,oe&=~cr}if(uf!==null&&!(q&24)&&uf.has(S)&&uf.delete(S),S===Fo&&(Cs=Fo=null,oo=0),1<T.flags?T.lastEffect!==null?(T.lastEffect.nextEffect=T,q=T.firstEffect):q=T:q=T.firstEffect,q!==null){z=Kr,Kr|=32,Qv.current=null,_m=rt(S.containerInfo),Mm=!1,Br=q;do try{J8()}catch(Ke){if(Br===null)throw Error(l(330));Ch(Br,Ke),Br=Br.nextEffect}while(Br!==null);_m=null,Br=q;do try{for(Se=S;Br!==null;){var qr=Br.flags;if(qr&16&&F&&Lt(Br.stateNode),qr&128){var rn=Br.alternate;if(rn!==null){var gr=rn.ref;gr!==null&&(typeof gr=="function"?gr(null):gr.current=null)}}switch(qr&1038){case 2:RR(Br),Br.flags&=-3;break;case 6:RR(Br),Br.flags&=-3,kv(Br.alternate,Br);break;case 1024:Br.flags&=-1025;break;case 1028:Br.flags&=-1025,kv(Br.alternate,Br);break;case 4:kv(Br.alternate,Br);break;case 8:qe=Se,oe=Br,F?TR(qe,oe):xR(qe,oe);var Ii=oe.alternate;RI(oe),Ii!==null&&RI(Ii)}Br=Br.nextEffect}}catch(Ke){if(Br===null)throw Error(l(330));Ch(Br,Ke),Br=Br.nextEffect}while(Br!==null);Mm&&pt(),Ne(S.containerInfo),S.current=T,Br=q;do try{for(qr=S;Br!==null;){var ji=Br.flags;if(ji&36&&DR(qr,Br.alternate,Br),ji&128){rn=void 0;var Fc=Br.ref;if(Fc!==null){var at=Br.stateNode;switch(Br.tag){case 5:rn=Te(at);break;default:rn=at}typeof Fc=="function"?Fc(rn):Fc.current=rn}}Br=Br.nextEffect}}catch(Ke){if(Br===null)throw Error(l(330));Ch(Br,Ke),Br=Br.nextEffect}while(Br!==null);Br=null,ne(),Kr=z}else S.current=T;if(wh)wh=!1,Nm=S,Om=b;else for(Br=q;Br!==null;)b=Br.nextEffect,Br.nextEffect=null,Br.flags&8&&(ji=Br,ji.sibling=null,ji.stateNode=null),Br=b;if(q=S.pendingLanes,q===0&&($l=null),q===1?S===Gv?Lm++:(Lm=0,Gv=S):Lm=0,T=T.stateNode,vc&&typeof vc.onCommitFiberRoot=="function")try{vc.onCommitFiberRoot(it,T,void 0,(T.current.flags&64)===64)}catch{}if(Ka(S,jt()),UI)throw UI=!1,S=Uv,Uv=null,S;return Kr&8||ni(),null}function J8(){for(;Br!==null;){var S=Br.alternate;Mm||_m===null||(Br.flags&8?De(Br,_m)&&(Mm=!0,Le()):Br.tag===13&&G8(S,Br)&&De(Br,_m)&&(Mm=!0,Le()));var b=Br.flags;b&256&&xI(S,Br),!(b&512)||wh||(wh=!0,ps(97,function(){return hf(),null})),Br=Br.nextEffect}}function hf(){if(Om!==90){var S=97<Om?97:Om;return Om=90,Qi(S,X8)}return!1}function Z8(S,b){Hv.push(b,S),wh||(wh=!0,ps(97,function(){return hf(),null}))}function HR(S,b){jv.push(b,S),wh||(wh=!0,ps(97,function(){return hf(),null}))}function X8(){if(Nm===null)return!1;var S=Nm;if(Nm=null,Kr&48)throw Error(l(331));var b=Kr;Kr|=32;var T=jv;jv=[];for(var q=0;q<T.length;q+=2){var z=T[q],oe=T[q+1],Se=z.destroy;if(z.destroy=void 0,typeof Se=="function")try{Se()}catch(wt){if(oe===null)throw Error(l(330));Ch(oe,wt)}}for(T=Hv,Hv=[],q=0;q<T.length;q+=2){z=T[q],oe=T[q+1];try{va Line truncated
`+(q.join(" > ")+`
No matching component was found for:
`)+S.join(" > ")}return null},r.getPublicRootInstance=function(S){if(S=S.current,!S.child)return null;switch(S.child.tag){case 5:return Te(S.child.stateNode);default:return S.child.stateNode}},r.injectIntoDevTools=function(S){if(S={bundleType:S.bundleType,version:S.version,rendererPackageName:S.rendererPackageName,rendererConfig:S.rendererConfig,overrideHookState:null,overrideHookStateDeletePath:null,overrideHookStateRenamePath:null,overrideProps:null,overridePropsDeletePath:null,overridePropsRenamePath:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:f.ReactCurrentDispatcher,findHostInstanceByFiber:n3,findFiberByHostInstance:S.findFiberByHostInstance||i3,findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null},typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u")S=!1;else{var b=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(!b.isDisabled&&b.supportsFiber)try{it=b.inject(S),vc=b}catch{}S=!0}return S},r.observeVisibleRects=function(S,b,T,q){if(!er)throw Error(l(363));S=Tv(S,b);var z=Ue(S,T,q).disconnect;return{disconnect:function(){z()}}},r.registerMutableSourceForHydration=function(S,b){var T=b._getVersion;T=T(b._source),S.mutableSourceEagerHydrationData==null?S.mutableSourceEagerHydrationData=[b,T]:S.mutableSourceEagerHydrationData.push(b,T)},r.runWithPriority=function(S,b){var T=Yl;try{return Yl=S,b()}finally{Yl=T}},r.shouldSuspend=function(){return!1},r.unbatchedUpdates=function(S,b){var T=Kr;Kr&=-2,Kr|=8;try{return S(b)}finally{Kr=T,Kr===0&&(Ih(),ni())}},r.updateContainer=function(S,b,T,q){var z=b.current,oe=ia(),Se=Js(z);e:if(T){T=T._reactInternals;t:{if(be(T)!==T||T.tag!==1)throw Error(l(170));var qe=T;do{switch(qe.tag){case 3:qe=qe.stateNode.context;break t;case 1:if(Ei(qe.type)){qe=qe.stateNode.__reactInternalMemoizedMergedChildContext;break t}}qe=qe.return}while(qe!==null);throw Error(l(171))}if(T.tag===1){var wt=T.type;if(Ei(wt)){T=wc(T,wt,qe);break e}}T=qe}else T=Ha;return b.context===null?b.context=T:b.pendingContext=T,b=hl(oe,Se),b.payload={element:S},q=q===void 0?null:q,q!==null&&(b.callback=q),Al(z,b),yl(z,Se,oe),Se},r}});var Cbe=H((apr,wbe)=>{"use strict";wbe.exports=Ibe()});var vbe=H((cpr,Bbe)=>{"use strict";var qwt={ALIGN_COUNT:8,ALIGN_AUTO:0,ALIGN_FLEX_START:1,ALIGN_CENTER:2,ALIGN_FLEX_END:3,ALIGN_STRETCH:4,ALIGN_BASELINE:5,ALIGN_SPACE_BETWEEN:6,ALIGN_SPACE_AROUND:7,DIMENSION_COUNT:2,DIMENSION_WIDTH:0,DIMENSION_HEIGHT:1,DIRECTION_COUNT:3,DIRECTION_INHERIT:0,DIRECTION_LTR:1,DIRECTION_RTL:2,DISPLAY_COUNT:2,DISPLAY_FLEX:0,DISPLAY_NONE:1,EDGE_COUNT:9,EDGE_LEFT:0,EDGE_TOP:1,EDGE_RIGHT:2,EDGE_BOTTOM:3,EDGE_START:4,EDGE_END:5,EDGE_HORIZONTAL:6,EDGE_VERTICAL:7,EDGE_ALL:8,EXPERIMENTAL_FEATURE_COUNT:1,EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS:0,FLEX_DIRECTION_COUNT:4,FLEX_DIRECTION_COLUMN:0,FLEX_DIRECTION_COLUMN_REVERSE:1,FLEX_DIRECTION_ROW:2,FLEX_DIRECTION_ROW_REVERSE:3,JUSTIFY_COUNT:6,JUSTIFY_FLEX_START:0,JUSTIFY_CENTER:1,JUSTIFY_FLEX_END:2,JUSTIFY_SPACE_BETWEEN:3,JUSTIFY_SPACE_AROUND:4,JUSTIFY_SPACE_EVENLY:5,LOG_LEVEL_COUNT:6,LOG_LEVEL_ERROR:0,LOG_LEVEL_WARN:1,LOG_LEVEL_INFO:2,LOG_LEVEL_DEBUG:3,LOG_LEVEL_VERBOSE:4,LOG_LEVEL_FATAL:5,MEASURE_MODE_COUNT:3,MEASURE_MODE_UNDEFINED:0,MEASURE_MODE_EXACTLY:1,MEASURE_MODE_AT_MOST:2,NODE_TYPE_COUNT:2,NODE_TYPE_DEFAULT:0,NODE_TYPE_TEXT:1,OVERFLOW_COUNT:3,OVERFLOW_VISIBLE:0,OVERFLOW_HIDDEN:1,OVERFLOW_SCROLL:2,POSITION_TYPE_COUNT:2,POSITION_TYPE_RELATIVE:0,POSITION_TYPE_ABSOLUTE:1,PRINT_OPTIONS_COUNT:3,PRINT_OPTIONS_LAYOUT:1,PRINT_OPTIONS_STYLE:2,PRINT_OPTIONS_CHILDREN:4,UNIT_COUNT:4,UNIT_UNDEFINED:0,UNIT_POINT:1,UNIT_PERCENT:2,UNIT_AUTO:3,WRAP_COUNT:3,WRAP_NO_WRAP:0,WRAP_WRAP:1,WRAP_WRAP_REVERSE:2};Bbe.exports=qwt});var Pbe=H((lpr,Dbe)=>{"use strict";var Vwt=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var s in r)Object.prototype.hasOwnProperty.call(r,s)&&(t[s]=r[s])}return t},SL=function(){function t(e,r){for(var s=0;s<r.length;s++){var a=r[s];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}return function(e,r,s){return r&&t(e.prototype,r),s&&t(e,s),e}}();function OK(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function LK(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var Wf=vbe(),Wwt=function(){function t(e,r,s,a,n,l){LK(this,t),this.left=e,this.right=r,this.top=s,this.bottom=a,this.width=n,this.height=l}return SL(t,[{key:"fromJS",value:function(r){r(this.left,this.right,this.top,this.bottom,this.width,this.height)}},{key:"toString",value:function(){return"<Layout#"+this.left+":"+this.right+";"+this.top+":"+this.bottom+";"+this.width+":"+this.height+">"}}]),t}(),Sbe=function(){SL(t,null,[{key:"fromJS",value:function(r){var s=r.width,a=r.height;return new t(s,a)}}]);function t(e,r){LK(this,t),this.width=e,this.height=r}return SL(t,[{key:"fromJS",value:function(r){r(this.width,this.height)}},{key:"toStri Line truncated
`+Module.extraStackTrace()),demangleAll(t)}Module.stackTrace=stackTrace;var HEAP,buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module.HEAP8=HEAP8=new Int8Array(buffer),Module.HEAP16=HEAP16=new Int16Array(buffer),Module.HEAP32=HEAP32=new Int32Array(buffer),Module.HEAPU8=HEAPU8=new Uint8Array(buffer),Module.HEAPU16=HEAPU16=new Uint16Array(buffer),Module.HEAPU32=HEAPU32=new Uint32Array(buffer),Module.HEAPF32=HEAPF32=new Float32Array(buffer),Module.HEAPF64=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed,STACK_BASE,STACKTOP,STACK_MAX,DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0,staticSealed=!1;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module.TOTAL_STACK||5242880,TOTAL_MEMORY=Module.TOTAL_MEMORY||134217728;TOTAL_MEMORY<TOTAL_STACK&&Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+TOTAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")"),Module.buffer?buffer=Module.buffer:buffer=new ArrayBuffer(TOTAL_MEMORY),updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}if(HEAP32[0]=1668509029,HEAP16[1]=25459,HEAPU8[2]!==115||HEAPU8[3]!==99)throw"Runtime error: expected the system to be little-endian!";Module.HEAP=HEAP,Module.buffer=buffer,Module.HEAP8=HEAP8,Module.HEAP16=HEAP16,Module.HEAP32=HEAP32,Module.HEAPU8=HEAPU8,Module.HEAPU16=HEAPU16,Module.HEAPU32=HEAPU32,Module.HEAPF32=HEAPF32,Module.HEAPF64=HEAPF64;function callRuntimeCallbacks(t){for(;t.length>0;){var e=t.shift();if(typeof e=="function"){e();continue}var r=e.func;typeof r=="number"?e.arg===void 0?Module.dynCall_v(r):Module.dynCall_vi(r,e.arg):r(e.arg===void 0?null:e.arg)}}var __ATPRERUN__=[],__ATINIT__=[],__ATMAIN__=[],__ATEXIT__=[],__ATPOSTRUN__=[],runtimeInitialized=!1,runtimeExited=!1;function preRun(){if(Module.preRun)for(typeof Module.preRun=="function"&&(Module.preRun=[Module.preRun]);Module.preRun.length;)addOnPreRun(Module.preRun.shift());callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){runtimeInitialized||(runtimeInitialized=!0,callRuntimeCallbacks(__ATINIT__))}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__),runtimeExited=!0}function postRun(){if(Module.postRun)for(typeof Module.postRun=="function"&&(Module.postRun=[Module.postRun]);Module.postRun.length;)addOnPostRun(Module.postRun.shift());callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(t){__ATPRERUN__.unshift(t)}Module.addOnPreRun=addOnPreRun;function addOnInit(t){__ATINIT__.unshift(t)}Module.addOnInit=addOnInit;function addOnPreMain(t){__ATMAIN__.unshift(t)}Module.addOnPreMain=addOnPreMain;function addOnExit(t){__ATEXIT__.unshift(t)}Module.addOnExit=addOnExit;function addOnPostRun(t){__ATPOSTRUN__.unshift(t)}Module.addOnPostRun=addOnPostRun;function intArrayFromString(t,e,r){var s=r>0?r:lengthBytesUTF8(t)+1,a=new Array(s),n=stringToUTF8Array(t,a,0,a.length);return e&&(a.length=n),a}Module.intArrayFromString=intArrayFromString;function intArrayToString(t){for(var e=[],r=0;r<t.length;r++){var s=t[r];s>255&&(s&=255),e.push(String.fromCharCode(s))}return e.join("")}Module.intArrayToString=intArrayToString;function writeStringToMemory(t,e,r){Runtime.warnOnce("writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!");var s,a;r&&(a=e+lengthBytesUTF8(t),s=HEAP8[a]),stringToUTF8(t,e,1/0),r&&(HEAP8[a]=s)}Module.writeStringToMemory=writeStringToMemory;function writeArrayToMemory(t,e){HEAP8.set(t,e)}Module.writeArrayToMemory=writeArrayToMemory;function writeAsciiToMemory(t,e,r){for(var s=0;s<t.length;++s)HEAP8[e++>>0]=t.charCodeAt(s);r||(HEAP8[e>>0]=0)}if(Module.writeAsciiToMemory=writeAsciiToMemory,(!Math.imul||Math.imul(4294967295,5)!==-5)&&(Math.imul=function t(e,r){var s=e>>>16,a=e&65535,n=r>>>16,l=r&65535;return a*l+(s*l+a*n<<16)|0}),Math.imul=Math.imul,!Math.fround){var froundBuffer=new Float32Array(1);Math.fround=function(t){return froundBuffer[0]=t,froundBuffer[0]}}Math.fround=Math.fround,Math.clz32||(Math.clz32=function(t){t=t>>>0;for(var e=0;e<32;e++)if(t&1<<31-e)return e;return 32}),Math.clz32=Math.clz32,Math.trunc||(Math.trunc=function(t){return t<0?Math.ceil(t):Math.floor(t)}),Math.trunc=Math.trunc;var Math_abs=Math.abs,Math_cos=Math.cos,Math_sin=Math.sin,Math_tan=Math.tan,Math_acos=Math.acos,Math_asin=Math.asin,Math_atan=Math.atan,Math_atan2=Math.atan2,Math_exp=Math.exp,Math_log=Math.log,Math_sqrt=Math.sqrt,Math_ceil=Math.cei Line truncated
If this abort() is unexpected, build with -s ASSERTIONS=1 which can give more information.`,r="abort("+t+") at "+stackTrace()+e;throw abortDecorators&&abortDecorators.forEach(function(s){r=s(r,t)}),r}if(Module.abort=Module.abort=abort,Module.preInit)for(typeof Module.preInit=="function"&&(Module.preInit=[Module.preInit]);Module.preInit.length>0;)Module.preInit.pop()();var shouldRunNow=!0;Module.noInitialRun&&(shouldRunNow=!1),run()})});var uE=H((fpr,kbe)=>{"use strict";var Ywt=Pbe(),Kwt=xbe(),_K=!1,MK=null;Kwt({},function(t,e){if(!_K){if(_K=!0,t)throw t;MK=e}});if(!_K)throw new Error("Failed to load the yoga module - it needed to be loaded synchronously, but didn't");kbe.exports=Ywt(MK.bind,MK.lib)});var HK=H((hpr,UK)=>{"use strict";var Rbe=t=>Number.isNaN(t)?!1:t>=4352&&(t<=4447||t===9001||t===9002||11904<=t&&t<=12871&&t!==12351||12880<=t&&t<=19903||19968<=t&&t<=42182||43360<=t&&t<=43388||44032<=t&&t<=55203||63744<=t&&t<=64255||65040<=t&&t<=65049||65072<=t&&t<=65131||65281<=t&&t<=65376||65504<=t&&t<=65510||110592<=t&&t<=110593||127488<=t&&t<=127569||131072<=t&&t<=262141);UK.exports=Rbe;UK.exports.default=Rbe});var Qbe=H((Apr,Tbe)=>{"use strict";Tbe.exports=function(){return/\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E Line truncated
`))e=Math.max(e,Xwt(r));return e};GK.exports=Nbe;GK.exports.default=Nbe});var Obe=H(hP=>{"use strict";var $wt=hP&&hP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(hP,"__esModule",{value:!0});var eCt=$wt(qK()),VK={};hP.default=t=>{if(t.length===0)return{width:0,height:0};if(VK[t])return VK[t];let e=eCt.default(t),r=t.split(`
`).length;return VK[t]={width:e,height:r},{width:e,height:r}}});var Lbe=H(AP=>{"use strict";var tCt=AP&&AP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(AP,"__esModule",{value:!0});var Xn=tCt(uE()),rCt=(t,e)=>{"position"in e&&t.setPositionType(e.position==="absolute"?Xn.default.POSITION_TYPE_ABSOLUTE:Xn.default.POSITION_TYPE_RELATIVE)},nCt=(t,e)=>{"marginLeft"in e&&t.setMargin(Xn.default.EDGE_START,e.marginLeft||0),"marginRight"in e&&t.setMargin(Xn.default.EDGE_END,e.marginRight||0),"marginTop"in e&&t.setMargin(Xn.default.EDGE_TOP,e.marginTop||0),"marginBottom"in e&&t.setMargin(Xn.default.EDGE_BOTTOM,e.marginBottom||0)},iCt=(t,e)=>{"paddingLeft"in e&&t.setPadding(Xn.default.EDGE_LEFT,e.paddingLeft||0),"paddingRight"in e&&t.setPadding(Xn.default.EDGE_RIGHT,e.paddingRight||0),"paddingTop"in e&&t.setPadding(Xn.default.EDGE_TOP,e.paddingTop||0),"paddingBottom"in e&&t.setPadding(Xn.default.EDGE_BOTTOM,e.paddingBottom||0)},sCt=(t,e)=>{var r;"flexGrow"in e&&t.setFlexGrow((r=e.flexGrow)!==null&&r!==void 0?r:0),"flexShrink"in e&&t.setFlexShrink(typeof e.flexShrink=="number"?e.flexShrink:1),"flexDirection"in e&&(e.flexDirection==="row"&&t.setFlexDirection(Xn.default.FLEX_DIRECTION_ROW),e.flexDirection==="row-reverse"&&t.setFlexDirection(Xn.default.FLEX_DIRECTION_ROW_REVERSE),e.flexDirection==="column"&&t.setFlexDirection(Xn.default.FLEX_DIRECTION_COLUMN),e.flexDirection==="column-reverse"&&t.setFlexDirection(Xn.default.FLEX_DIRECTION_COLUMN_REVERSE)),"flexBasis"in e&&(typeof e.flexBasis=="number"?t.setFlexBasis(e.flexBasis):typeof e.flexBasis=="string"?t.setFlexBasisPercent(Number.parseInt(e.flexBasis,10)):t.setFlexBasis(NaN)),"alignItems"in e&&((e.alignItems==="stretch"||!e.alignItems)&&t.setAlignItems(Xn.default.ALIGN_STRETCH),e.alignItems==="flex-start"&&t.setAlignItems(Xn.default.ALIGN_FLEX_START),e.alignItems==="center"&&t.setAlignItems(Xn.default.ALIGN_CENTER),e.alignItems==="flex-end"&&t.setAlignItems(Xn.default.ALIGN_FLEX_END)),"alignSelf"in e&&((e.alignSelf==="auto"||!e.alignSelf)&&t.setAlignSelf(Xn.default.ALIGN_AUTO),e.alignSelf==="flex-start"&&t.setAlignSelf(Xn.default.ALIGN_FLEX_START),e.alignSelf==="center"&&t.setAlignSelf(Xn.default.ALIGN_CENTER),e.alignSelf==="flex-end"&&t.setAlignSelf(Xn.default.ALIGN_FLEX_END)),"justifyContent"in e&&((e.justifyContent==="flex-start"||!e.justifyContent)&&t.setJustifyContent(Xn.default.JUSTIFY_FLEX_START),e.justifyContent==="center"&&t.setJustifyContent(Xn.default.JUSTIFY_CENTER),e.justifyContent==="flex-end"&&t.setJustifyContent(Xn.default.JUSTIFY_FLEX_END),e.justifyContent==="space-between"&&t.setJustifyContent(Xn.default.JUSTIFY_SPACE_BETWEEN),e.justifyContent==="space-around"&&t.setJustifyContent(Xn.default.JUSTIFY_SPACE_AROUND))},oCt=(t,e)=>{var r,s;"width"in e&&(typeof e.width=="number"?t.setWidth(e.width):typeof e.width=="string"?t.setWidthPercent(Number.parseInt(e.width,10)):t.setWidthAuto()),"height"in e&&(typeof e.height=="number"?t.setHeight(e.height):typeof e.height=="string"?t.setHeightPercent(Number.parseInt(e.height,10)):t.setHeightAuto()),"minWidth"in e&&(typeof e.minWidth=="string"?t.setMinWidthPercent(Number.parseInt(e.minWidth,10)):t.setMinWidth((r=e.minWidth)!==null&&r!==void 0?r:0)),"minHeight"in e&&(typeof e.minHeight=="string"?t.setMinHeightPercent(Number.parseInt(e.minHeight,10)):t.setMinHeight((s=e.minHeight)!==null&&s!==void 0?s:0))},aCt=(t,e)=>{"display"in e&&t.setDisplay(e.display==="flex"?Xn.default.DISPLAY_FLEX:Xn.default.DISPLAY_NONE)},cCt=(t,e)=>{if("borderStyle"in e){let r=typeof e.borderStyle=="string"?1:0;t.setBorder(Xn.default.EDGE_TOP,r),t.setBorder(Xn.default.EDGE_BOTTOM,r),t.setBorder(Xn.default.EDGE_LEFT,r),t.setBorder(Xn.default.EDGE_RIGHT,r)}};AP.default=(t,e={})=>{rCt(t,e),nCt(t,e),iCt(t,e),sCt(t,e),oCt(t,e),aCt(t,e),cCt(t,e)}});var Ube=H((ypr,Mbe)=>{"use strict";var pP=fP(),lCt=CQ(),uCt=fQ(),YK=new Set(["\x1B","\x9B"]),fCt=39,_be=t=>`${YK.values().next().value}[${t}m`,hCt=t=>t.split(" ").map(e=>pP(e)),WK=(t,e,r)=>{let s=[...e],a=!1,n=pP(lCt(t[t.length-1]));for(let[l,f]of s.entries()){let h=pP(f);if(n+h<=r?t[t.length-1]+=f:(t.push(f),n=0),YK.has(f))a=!0;else if(a&&f==="m"){a=!1;continue}a||(n+=h,n===r&&l<s.length-1&&(t.push(""),n=0))}!n&&t[t.length-1].length>0&&t.length>1&&(t[t.length-2]+=t.pop())},ACt=t=>{let e=t.split(" "),r=e.length;for(;r>0&&!(pP(e[r-1])>0);)r--;return r===e.length?t:e.slice(0,r).join(" ")+e.slice(r).join("")},pCt=(t,e,r={})=>{if(r.trim!==!1&&t.trim()==="")return"";let s="",a="",n,l=hCt(t),f=[""];for(let[h,A]of t.split(" ").entries()){r.trim!==!1&&(f[f.length-1]=f[f.length-1].trimLeft());let m=pP(f[f.length-1]);if(h!==0&&(m>=e&&(r.wordWrap===!1||r.trim===!1)&&(f.push(""),m=0),(m>0||r.trim===!1)&&(f[f.length-1]+=" ",m++)),r.hard&&l[h]>e){let w=e-m,v=1+Math.floor((l[h]-w-1)/e);Math.floor((l[h]-1)/e)<v&&f.push(""),WK(f,A,e);continue}if(m+l[h]>e&&m>0&&l[h]>0){if(r.wordWrap===!1&&m<e){WK(f,A,e);continue}f.push("")}if(m+l[h]>e&&r.wordWrap===!1){WK(f,A,e);continue}f[f. Line truncated
`);for(let[h,A]of[...s].entries()){if(a+=A,YK.has(A)){let w=parseFloat(/\d[^m]*/.exec(s.slice(h,h+4)));n=w===fCt?null:w}let m=uCt.codes.get(Number(n));n&&m&&(s[h+1]===`
`?a+=_be(m):A===`
`&&(a+=_be(n)))}return a};Mbe.exports=(t,e,r)=>String(t).normalize().replace(/\r\n/g,`
`).split(`
`).map(s=>pCt(s,e,r)).join(`
`)});var Gbe=H((Epr,jbe)=>{"use strict";var Hbe="[\uD800-\uDBFF][\uDC00-\uDFFF]",dCt=t=>t&&t.exact?new RegExp(`^${Hbe}$`):new RegExp(Hbe,"g");jbe.exports=dCt});var KK=H((Ipr,Ybe)=>{"use strict";var gCt=HK(),mCt=Gbe(),qbe=fQ(),Wbe=["\x1B","\x9B"],bL=t=>`${Wbe[0]}[${t}m`,Vbe=(t,e,r)=>{let s=[];t=[...t];for(let a of t){let n=a;a.match(";")&&(a=a.split(";")[0][0]+"0");let l=qbe.codes.get(parseInt(a,10));if(l){let f=t.indexOf(l.toString());f>=0?t.splice(f,1):s.push(bL(e?l:n))}else if(e){s.push(bL(0));break}else s.push(bL(n))}if(e&&(s=s.filter((a,n)=>s.indexOf(a)===n),r!==void 0)){let a=bL(qbe.codes.get(parseInt(r,10)));s=s.reduce((n,l)=>l===a?[l,...n]:[...n,l],[])}return s.join("")};Ybe.exports=(t,e,r)=>{let s=[...t.normalize()],a=[];r=typeof r=="number"?r:s.length;let n=!1,l,f=0,h="";for(let[A,m]of s.entries()){let w=!1;if(Wbe.includes(m)){let v=/\d[^m]*/.exec(t.slice(A,A+18));l=v&&v.length>0?v[0]:void 0,f<r&&(n=!0,l!==void 0&&a.push(l))}else n&&m==="m"&&(n=!1,w=!0);if(!n&&!w&&++f,!mCt({exact:!0}).test(m)&&gCt(m.codePointAt())&&++f,f>e&&f<=r)h+=m;else if(f===e&&!n&&l!==void 0)h=Vbe(a);else if(f>=r){h+=Vbe(a,!0,l);break}}return h}});var zbe=H((wpr,Kbe)=>{"use strict";var wg=KK(),yCt=fP();function DL(t,e,r){if(t.charAt(e)===" ")return e;for(let s=1;s<=3;s++)if(r){if(t.charAt(e+s)===" ")return e+s}else if(t.charAt(e-s)===" ")return e-s;return e}Kbe.exports=(t,e,r)=>{r={position:"end",preferTruncationOnSpace:!1,...r};let{position:s,space:a,preferTruncationOnSpace:n}=r,l="\u2026",f=1;if(typeof t!="string")throw new TypeError(`Expected \`input\` to be a string, got ${typeof t}`);if(typeof e!="number")throw new TypeError(`Expected \`columns\` to be a number, got ${typeof e}`);if(e<1)return"";if(e===1)return l;let h=yCt(t);if(h<=e)return t;if(s==="start"){if(n){let A=DL(t,h-e+1,!0);return l+wg(t,A,h).trim()}return a===!0&&(l+=" ",f=2),l+wg(t,h-e+f,h)}if(s==="middle"){a===!0&&(l=" "+l+" ",f=3);let A=Math.floor(e/2);if(n){let m=DL(t,A),w=DL(t,h-(e-A)+1,!0);return wg(t,0,m)+l+wg(t,w,h).trim()}return wg(t,0,A)+l+wg(t,h-(e-A)+f,h)}if(s==="end"){if(n){let A=DL(t,e-1);return wg(t,0,A)+l}return a===!0&&(l=" "+l,f=2),wg(t,0,e-f)+l}throw new Error(`Expected \`options.position\` to be either \`start\`, \`middle\` or \`end\`, got ${s}`)}});var JK=H(dP=>{"use strict";var Jbe=dP&&dP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(dP,"__esModule",{value:!0});var ECt=Jbe(Ube()),ICt=Jbe(zbe()),zK={};dP.default=(t,e,r)=>{let s=t+String(e)+String(r);if(zK[s])return zK[s];let a=t;if(r==="wrap"&&(a=ECt.default(t,e,{trim:!1,hard:!0})),r.startsWith("truncate")){let n="end";r==="truncate-middle"&&(n="middle"),r==="truncate-start"&&(n="start"),a=ICt.default(t,e,{position:n})}return zK[s]=a,a}});var XK=H(ZK=>{"use strict";Object.defineProperty(ZK,"__esModule",{value:!0});var Zbe=t=>{let e="";if(t.childNodes.length>0)for(let r of t.childNodes){let s="";r.nodeName==="#text"?s=r.nodeValue:((r.nodeName==="ink-text"||r.nodeName==="ink-virtual-text")&&(s=Zbe(r)),s.length>0&&typeof r.internal_transform=="function"&&(s=r.internal_transform(s))),e+=s}return e};ZK.default=Zbe});var $K=H($i=>{"use strict";var gP=$i&&$i.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty($i,"__esModule",{value:!0});$i.setTextNodeValue=$i.createTextNode=$i.setStyle=$i.setAttribute=$i.removeChildNode=$i.insertBeforeNode=$i.appendChildNode=$i.createNode=$i.TEXT_NAME=void 0;var wCt=gP(uE()),Xbe=gP(Obe()),CCt=gP(Lbe()),BCt=gP(JK()),vCt=gP(XK());$i.TEXT_NAME="#text";$i.createNode=t=>{var e;let r={nodeName:t,style:{},attributes:{},childNodes:[],parentNode:null,yogaNode:t==="ink-virtual-text"?void 0:wCt.default.Node.create()};return t==="ink-text"&&((e=r.yogaNode)===null||e===void 0||e.setMeasureFunc(SCt.bind(null,r))),r};$i.appendChildNode=(t,e)=>{var r;e.parentNode&&$i.removeChildNode(e.parentNode,e),e.parentNode=t,t.childNodes.push(e),e.yogaNode&&((r=t.yogaNode)===null||r===void 0||r.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&PL(t)};$i.insertBeforeNode=(t,e,r)=>{var s,a;e.parentNode&&$i.removeChildNode(e.parentNode,e),e.parentNode=t;let n=t.childNodes.indexOf(r);if(n>=0){t.childNodes.splice(n,0,e),e.yogaNode&&((s=t.yogaNode)===null||s===void 0||s.insertChild(e.yogaNode,n));return}t.childNodes.push(e),e.yogaNode&&((a=t.yogaNode)===null||a===void 0||a.insertChild(e.yogaNode,t.yogaNode.getChildCount())),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&PL(t)};$i.removeChildNode=(t,e)=>{var r,s;e.yogaNode&&((s=(r=e.parentNode)===null||r===void 0?void 0:r.yogaNode)===null||s===void 0||s.removeChild(e.yogaNode)),e.parentNode=null;let a=t.childNodes.indexOf(e);a>=0&&t.childNodes.splice(a,1),(t.nodeName==="ink-text"||t.nodeName==="ink-virtual-text")&&PL(t)};$i.setAttribute=(t,e,r)=>{t.attributes[e]=r};$i.setStyle=(t,e)=>{t.style=e,t.yogaNode&&CCt.default(t.yogaNode,e)};$i.createTextNode=t=>{let e={nodeName:"#text",nodeValue:t,yogaLine truncated
`).repeat(n-2),m=rz.default(f.bottomLeft+f.horizontal.repeat(a-2)+f.bottomRight,l,"foreground");s.write(t,e,h,{transformers:[]}),s.write(t,e+1,A,{transformers:[]}),s.write(t+a-1,e+1,A,{transformers:[]}),s.write(t,e+n-1,m,{transformers:[]})}}});var pDe=H(CP=>{"use strict";var fE=CP&&CP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(CP,"__esModule",{value:!0});var QCt=fE(uE()),FCt=fE(qK()),NCt=fE(oDe()),OCt=fE(JK()),LCt=fE(aDe()),_Ct=fE(XK()),MCt=fE(hDe()),UCt=(t,e)=>{var r;let s=(r=t.childNodes[0])===null||r===void 0?void 0:r.yogaNode;if(s){let a=s.getComputedLeft(),n=s.getComputedTop();e=`
`.repeat(n)+NCt.default(e,a)}return e},ADe=(t,e,r)=>{var s;let{offsetX:a=0,offsetY:n=0,transformers:l=[],skipStaticElements:f}=r;if(f&&t.internal_static)return;let{yogaNode:h}=t;if(h){if(h.getDisplay()===QCt.default.DISPLAY_NONE)return;let A=a+h.getComputedLeft(),m=n+h.getComputedTop(),w=l;if(typeof t.internal_transform=="function"&&(w=[t.internal_transform,...l]),t.nodeName==="ink-text"){let v=_Ct.default(t);if(v.length>0){let D=FCt.default(v),I=LCt.default(h);if(D>I){let R=(s=t.style.textWrap)!==null&&s!==void 0?s:"wrap";v=OCt.default(v,I,R)}v=UCt(t,v),e.write(A,m,v,{transformers:w})}return}if(t.nodeName==="ink-box"&&MCt.default(A,m,t,e),t.nodeName==="ink-root"||t.nodeName==="ink-box")for(let v of t.childNodes)ADe(v,e,{offsetX:A,offsetY:m,transformers:w,skipStaticElements:f})}};CP.default=ADe});var mDe=H(BP=>{"use strict";var gDe=BP&&BP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(BP,"__esModule",{value:!0});var dDe=gDe(KK()),HCt=gDe(fP()),nz=class{constructor(e){this.writes=[];let{width:r,height:s}=e;this.width=r,this.height=s}write(e,r,s,a){let{transformers:n}=a;s&&this.writes.push({x:e,y:r,text:s,transformers:n})}get(){let e=[];for(let s=0;s<this.height;s++)e.push(" ".repeat(this.width));for(let s of this.writes){let{x:a,y:n,text:l,transformers:f}=s,h=l.split(`
`),A=0;for(let m of h){let w=e[n+A];if(!w)continue;let v=HCt.default(m);for(let D of f)m=D(m);e[n+A]=dDe.default(w,0,a)+m+dDe.default(w,a+v),A++}}return{output:e.map(s=>s.trimRight()).join(`
`),height:e.length}}};BP.default=nz});var IDe=H(vP=>{"use strict";var iz=vP&&vP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(vP,"__esModule",{value:!0});var jCt=iz(uE()),yDe=iz(pDe()),EDe=iz(mDe());vP.default=(t,e)=>{var r;if(t.yogaNode.setWidth(e),t.yogaNode){t.yogaNode.calculateLayout(void 0,void 0,jCt.default.DIRECTION_LTR);let s=new EDe.default({width:t.yogaNode.getComputedWidth(),height:t.yogaNode.getComputedHeight()});yDe.default(t,s,{skipStaticElements:!0});let a;!((r=t.staticNode)===null||r===void 0)&&r.yogaNode&&(a=new EDe.default({width:t.staticNode.yogaNode.getComputedWidth(),height:t.staticNode.yogaNode.getComputedHeight()}),yDe.default(t.staticNode,a,{skipStaticElements:!1}));let{output:n,height:l}=s.get();return{output:n,outputHeight:l,staticOutput:a?`${a.get().output}
`:""}}return{output:"",outputHeight:0,staticOutput:""}}});var vDe=H((Npr,BDe)=>{"use strict";var wDe=Ae("stream"),CDe=["assert","count","countReset","debug","dir","dirxml","error","group","groupCollapsed","groupEnd","info","log","table","time","timeEnd","timeLog","trace","warn"],sz={},GCt=t=>{let e=new wDe.PassThrough,r=new wDe.PassThrough;e.write=a=>t("stdout",a),r.write=a=>t("stderr",a);let s=new console.Console(e,r);for(let a of CDe)sz[a]=console[a],console[a]=s[a];return()=>{for(let a of CDe)console[a]=sz[a];sz={}}};BDe.exports=GCt});var az=H(oz=>{"use strict";Object.defineProperty(oz,"__esModule",{value:!0});oz.default=new WeakMap});var lz=H(cz=>{"use strict";Object.defineProperty(cz,"__esModule",{value:!0});var qCt=Ln(),SDe=qCt.createContext({exit:()=>{}});SDe.displayName="InternalAppContext";cz.default=SDe});var fz=H(uz=>{"use strict";Object.defineProperty(uz,"__esModule",{value:!0});var VCt=Ln(),bDe=VCt.createContext({stdin:void 0,setRawMode:()=>{},isRawModeSupported:!1,internal_exitOnCtrlC:!0});bDe.displayName="InternalStdinContext";uz.default=bDe});var Az=H(hz=>{"use strict";Object.defineProperty(hz,"__esModule",{value:!0});var WCt=Ln(),DDe=WCt.createContext({stdout:void 0,write:()=>{}});DDe.displayName="InternalStdoutContext";hz.default=DDe});var dz=H(pz=>{"use strict";Object.defineProperty(pz,"__esModule",{value:!0});var YCt=Ln(),PDe=YCt.createContext({stderr:void 0,write:()=>{}});PDe.displayName="InternalStderrContext";pz.default=PDe});var RL=H(gz=>{"use strict";Object.defineProperty(gz,"__esModule",{value:!0});var KCt=Ln(),xDe=KCt.createContext({activeId:void 0,add:()=>{},remove:()=>{},activate:()=>{},deactivate:()=>{},enableFocus:()=>{},disableFocus:()=>{},focusNext:()=>{},focusPrevious:()=>{},focus:()=>{}});xDe.displayName="InternalFocusContext";gz.default=xDe});var RDe=H((jpr,kDe)=>{"use strict";var zCt=/[|\\{}()[\]^$+*?.-]/g;kDe.exports=t=>{if(typeof t!="string")throw new TypeError("Expected a string");return t.replace(zCt,"\\$&")}});var NDe=H((Gpr,FDe)=>{"use strict";var JCt=RDe(),ZCt=typeof process=="object"&&process&&typeof process.cwd=="function"?process.cwd():".",QDe=[].concat(Ae("module").builtinModules,"bootstrap_node","node").map(t=>new RegExp(`(?:\\((?:node:)?${t}(?:\\.js)?:\\d+:\\d+\\)$|^\\s*at (?:node:)?${t}(?:\\.js)?:\\d+:\\d+$)`));QDe.push(/\((?:node:)?internal\/[^:]+:\d+:\d+\)$/,/\s*at (?:node:)?internal\/[^:]+:\d+:\d+$/,/\/\.node-spawn-wrap-\w+-\w+\/node:\d+:\d+\)?$/);var mz=class t{constructor(e){e={ignoredPackages:[],...e},"internals"in e||(e.internals=t.nodeInternals()),"cwd"in e||(e.cwd=ZCt),this._cwd=e.cwd.replace(/\\/g,"/"),this._internals=[].concat(e.internals,XCt(e.ignoredPackages)),this._wrapCallSite=e.wrapCallSite||!1}static nodeInternals(){return[...QDe]}clean(e,r=0){r=" ".repeat(r),Array.isArray(e)||(e=e.split(`
`)),!/^\s*at /.test(e[0])&&/^\s*at /.test(e[1])&&(e=e.slice(1));let s=!1,a=null,n=[];return e.forEach(l=>{if(l=l.replace(/\\/g,"/"),this._internals.some(h=>h.test(l)))return;let f=/^\s*at /.test(l);s?l=l.trimEnd().replace(/^(\s+)at /,"$1"):(l=l.trim(),f&&(l=l.slice(3))),l=l.replace(`${this._cwd}/`,""),l&&(f?(a&&(n.push(a),a=null),n.push(l)):(s=!0,a=l))}),n.map(l=>`${r}${l}
`).join("")}captureString(e,r=this.captureString){typeof e=="function"&&(r=e,e=1/0);let{stackTraceLimit:s}=Error;e&&(Error.stackTraceLimit=e);let a={};Error.captureStackTrace(a,r);let{stack:n}=a;return Error.stackTraceLimit=s,this.clean(n)}capture(e,r=this.capture){typeof e=="function"&&(r=e,e=1/0);let{prepareStackTrace:s,stackTraceLimit:a}=Error;Error.prepareStackTrace=(f,h)=>this._wrapCallSite?h.map(this._wrapCallSite):h,e&&(Error.stackTraceLimit=e);let n={};Error.captureStackTrace(n,r);let{stack:l}=n;return Object.assign(Error,{prepareStackTrace:s,stackTraceLimit:a}),l}at(e=this.at){let[r]=this.capture(1,e);if(!r)return{};let s={line:r.getLineNumber(),column:r.getColumnNumber()};TDe(s,r.getFileName(),this._cwd),r.isConstructor()&&(s.constructor=!0),r.isEval()&&(s.evalOrigin=r.getEvalOrigin()),r.isNative()&&(s.native=!0);let a;try{a=r.getTypeName()}catch{}a&&a!=="Object"&&a!=="[object Object]"&&(s.type=a);let n=r.getFunctionName();n&&(s.function=n);let l=r.getMethodName();return l&&n!==l&&(s.method=l),s}parseLine(e){let r=e&&e.match($Ct);if(!r)return null;let s=r[1]==="new",a=r[2],n=r[3],l=r[4],f=Number(r[5]),h=Number(r[6]),A=r[7],m=r[8],w=r[9],v=r[10]==="native",D=r[11]===")",I,R={};if(m&&(R.line=Number(m)),w&&(R.column=Number(w)),D&&A){let N=0;for(let U=A.length-1;U>0;U--)if(A.charAt(U)===")")N++;else if(A.charAt(U)==="("&&A.charAt(U-1)===" "&&(N--,N===-1&&A.charAt(U-1)===" ")){let V=A.slice(0,U-1);A=A.slice(U+1),a+=` (${V}`;break}}if(a){let N=a.match(e1t);N&&(a=N[1],I=N[2])}return TDe(R,A,this._cwd),s&&(R.constructor=!0),n&&(R.evalOrigin=n,R.evalLine=f,R.evalColumn=h,R.evalFile=l&&l.replace(/\\/g,"/")),v&&(R.native=!0),a&&(R.function=a),I&&a!==I&&(R.method=I),R}};function TDe(t,e,r){e&&(e=e.replace(/\\/g,"/"),e.startsWith(`${r}/`)&&(e=e.slice(r.length+1)),t.file=e)}function XCt(t){if(t.length===0)return[];let e=t.map(r=>JCt(r));return new RegExp(`[/\\\\]node_modules[/\\\\](?:${e.join("|")})[/\\\\][^:]+:\\d+:\\d+`)}var $Ct=new RegExp("^(?:\\s*at )?(?:(new) )?(?:(.*?) \\()?(?:eval at ([^ ]+) \\((.+?):(\\d+):(\\d+)\\), )?(?:(.+?):(\\d+):(\\d+)|(native))(\\)?)$"),e1t=/^(.*?) \[as (.*?)\]$/;FDe.exports=mz});var LDe=H((qpr,ODe)=>{"use strict";ODe.exports=(t,e)=>t.replace(/^\t+/gm,r=>" ".repeat(r.length*(e||2)))});var MDe=H((Vpr,_De)=>{"use strict";var t1t=LDe(),r1t=(t,e)=>{let r=[],s=t-e,a=t+e;for(let n=s;n<=a;n++)r.push(n);return r};_De.exports=(t,e,r)=>{if(typeof t!="string")throw new TypeError("Source code is missing.");if(!e||e<1)throw new TypeError("Line number must start from `1`.");if(t=t1t(t).split(/\r?\n/),!(e>t.length))return r={around:3,...r},r1t(e,r.around).filter(s=>t[s-1]!==void 0).map(s=>({line:s,value:t[s-1]}))}});var TL=H(Yf=>{"use strict";var n1t=Yf&&Yf.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r),Object.defineProperty(t,s,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),i1t=Yf&&Yf.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),s1t=Yf&&Yf.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&n1t(e,t,r);return i1t(e,t),e},o1t=Yf&&Yf.__rest||function(t,e){var r={};for(var s in t)Object.prototype.hasOwnProperty.call(t,s)&&e.indexOf(s)<0&&(r[s]=t[s]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var a=0,s=Object.getOwnPropertySymbols(t);a<s.length;a++)e.indexOf(s[a])<0&&Object.prototype.propertyIsEnumerable.call(t,s[a])&&(r[s[a]]=t[s[a]]);return r};Object.defineProperty(Yf,"__esModule",{value:!0});var UDe=s1t(Ln()),yz=UDe.forwardRef((t,e)=>{var{children:r}=t,s=o1t(t,["children"]);let a=Object.assign(Object.assign({},s),{marginLeft:s.marginLeft||s.marginX||s.margin||0,marginRight:s.marginRight||s.marginX||s.margin||0,marginTop:s.marginTop||s.marginY||s.margin||0,marginBottom:s.marginBottom||s.marginY||s.margin||0,paddingLeft:s.paddingLeft||s.paddingX||s.padding||0,paddingRight:s.paddingRight||s.paddingX||s.padding||0,paddingTop:s.paddingTop||s.paddingY||s.padding||0,paddingBottom:s.paddingBottom||s.paddingY||s.padding||0});return UDe.default.createElement("ink-box",{ref:e,style:a},r)});yz.displayName="Box";yz.defaultProps={flexDirection:"row",flexGrow:0,flexShrink:1};Yf.default=yz});var wz=H(SP=>{"use strict";var Ez=SP&&SP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(SP,"__esModule",{value:!0});var a1t=Ez(Ln()),Z1=Ez(Cw()),HDe=Ez(tz()),Iz=({color:t,backgroundColor:e,dimColor:r,bold:s,italic:a,underline:n,strikethrough:l,inverse:f,wrap:h,children:A})=>{if(A==null)return null;let m=w=>(r&&(w=Z1.default.dim(w)),t&&(w=HDe.default(w,t,"foreground")),e&&(w=HDe.default(w,e,"background")),s&&(w=Z1.default.bold(w)),a&&(w=Z1.default.italic(w)),n&&(w=Z1.default.underline(w)),l&&(w=Z1.default.strikethrough(w)),f&&(w=Z1.default.inverse(w)),w);return a1t.default.createElement("ink-text",{style:{flexGrow:0,flexSLine truncated
`).slice(1):void 0,r=e?qDe.parseLine(e[0]):void 0,s,a=0;if(r?.file&&r?.line&&jDe.existsSync(r.file)){let n=jDe.readFileSync(r.file,"utf8");if(s=f1t.default(n,r.line),s)for(let{line:l}of s)a=Math.max(a,String(l).length)}return no.default.createElement(rd.default,{flexDirection:"column",padding:1},no.default.createElement(rd.default,null,no.default.createElement(sA.default,{backgroundColor:"red",color:"white"}," ","ERROR"," "),no.default.createElement(sA.default,null," ",t.message)),r&&no.default.createElement(rd.default,{marginTop:1},no.default.createElement(sA.default,{dimColor:!0},r.file,":",r.line,":",r.column)),r&&s&&no.default.createElement(rd.default,{marginTop:1,flexDirection:"column"},s.map(({line:n,value:l})=>no.default.createElement(rd.default,{key:n},no.default.createElement(rd.default,{width:a+1},no.default.createElement(sA.default,{dimColor:n!==r.line,backgroundColor:n===r.line?"red":void 0,color:n===r.line?"white":void 0},String(n).padStart(a," "),":")),no.default.createElement(sA.default,{key:n,backgroundColor:n===r.line?"red":void 0,color:n===r.line?"white":void 0}," "+l)))),t.stack&&no.default.createElement(rd.default,{marginTop:1,flexDirection:"column"},t.stack.split(`
`).slice(1).map(n=>{let l=qDe.parseLine(n);return l?no.default.createElement(rd.default,{key:n},no.default.createElement(sA.default,{dimColor:!0},"- "),no.default.createElement(sA.default,{dimColor:!0,bold:!0},l.function),no.default.createElement(sA.default,{dimColor:!0,color:"gray"}," ","(",l.file,":",l.line,":",l.column,")")):no.default.createElement(rd.default,{key:n},no.default.createElement(sA.default,{dimColor:!0},"- "),no.default.createElement(sA.default,{dimColor:!0,bold:!0},n))})))};Kf.default=h1t});var YDe=H(zf=>{"use strict";var A1t=zf&&zf.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r),Object.defineProperty(t,s,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),p1t=zf&&zf.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),d1t=zf&&zf.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&A1t(e,t,r);return p1t(e,t),e},AE=zf&&zf.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(zf,"__esModule",{value:!0});var hE=d1t(Ln()),WDe=AE(BK()),g1t=AE(lz()),m1t=AE(fz()),y1t=AE(Az()),E1t=AE(dz()),I1t=AE(RL()),w1t=AE(VDe()),C1t=" ",B1t="\x1B[Z",v1t="\x1B",QL=class extends hE.PureComponent{constructor(){super(...arguments),this.state={isFocusEnabled:!0,activeFocusId:void 0,focusables:[],error:void 0},this.rawModeEnabledCount=0,this.handleSetRawMode=e=>{let{stdin:r}=this.props;if(!this.isRawModeSupported())throw r===process.stdin?new Error(`Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default.
Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`):new Error(`Raw mode is not supported on the stdin provided to Ink.
Read about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported`);if(r.setEncoding("utf8"),e){this.rawModeEnabledCount===0&&(r.addListener("data",this.handleInput),r.resume(),r.setRawMode(!0)),this.rawModeEnabledCount++;return}--this.rawModeEnabledCount===0&&(r.setRawMode(!1),r.removeListener("data",this.handleInput),r.pause())},this.handleInput=e=>{e===""&&this.props.exitOnCtrlC&&this.handleExit(),e===v1t&&this.state.activeFocusId&&this.setState({activeFocusId:void 0}),this.state.isFocusEnabled&&this.state.focusables.length>0&&(e===C1t&&this.focusNext(),e===B1t&&this.focusPrevious())},this.handleExit=e=>{this.isRawModeSupported()&&this.handleSetRawMode(!1),this.props.onExit(e)},this.enableFocus=()=>{this.setState({isFocusEnabled:!0})},this.disableFocus=()=>{this.setState({isFocusEnabled:!1})},this.focus=e=>{this.setState(r=>r.focusables.some(a=>a?.id===e)?{activeFocusId:e}:r)},this.focusNext=()=>{this.setState(e=>{var r;let s=(r=e.focusables[0])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findNextFocusable(e)||s}})},this.focusPrevious=()=>{this.setState(e=>{var r;let s=(r=e.focusables[e.focusables.length-1])===null||r===void 0?void 0:r.id;return{activeFocusId:this.findPreviousFocusable(e)||s}})},this.addFocusable=(e,{autoFocus:r})=>{this.setState(s=>{let a=s.activeFocusId;return!a&&r&&(a=e),{activeFocusId:a,focusables:[...s.focusables,{id:e,isActive:!0}]}})},this.removeFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.filter(s=>s.id!==e)}))},this.activateFocusable=e=>{this.setState(r=>({focusables:r.focusables.map(s=>s.id!==e?s:{id:e,isActive:!0})}))},this.deactivateFocusable=e=>{this.setState(r=>({activeFocusId:r.activeFocusId===e?void 0:r.activeFocusId,focusables:r.focusables.map(s=>s.id!==e?s:{id:e,isActive:!1})}))},this.findNextFocusable=e=>{var r;let s=e.focusables.findIndex(a=>a.id===e.activeFocusId);for(let a=s+1;a<e.focusables.length;a++)if(!((r=e.focusables[a])===null||r===void 0)&&r.isActive)return e.focusables[a].id},this.findPreviousFocusable=e=>{var r;let s=e.focusables.findIndex(a=>a.id===e.activeFocusId);for(let a=s-1;a>=0;a--)if(!((r=e.focusables[a])===null||r===void 0)&&r.isActive)return e.focusables[a].id}}static getDerivedStateFromError(e){return{error:e}}isRawModeSupported(){return this.props.stdin.isTTY}render(){return hE.default.createElement(g1t.default.Provider,{value:{exit:this.handleExit}},hE.default.createElement(m1t.default.Provider,{value:{stdin:this.props.stdin,setRawMode:this.handleSetRawMode,isRawModeSupported:this.isRawModeSupported(),internal_exitOnCtrlC:this.props.exitOnCtrlC}},hE.default.createElement(y1t.default.Provider,{value:{stdout:this.props.stdout,write:this.props.writeToStdout}},hE.default.createElement(E1t.default.Provider,{value:{stderr:this.props.stderr,write:this.props.writeToStderr}},hE.default.createElement(I1t.default.Provider,{value:{activeId:this.state.activeFocusId,add:this.addFocusable,remove:this.removeFocusable,activate:this.activateFocusable,deactivate:this.deactivateFocusable,enableFocus:this.enableFocus,disableFocus:this.disableFocus,focusNext:this.focusNext,focusPrevious:this.focusPrevious,focus:this.focus}},this.state.error?hE.default.createElement(w1t.default,{error:this.state.error}):this.props.children)))))}componentDidMount(){WDe.default.hide(this.props.stdout)}componentWillUnmount(){WDe.default.show(this.props.stdout),this.isRawModeSupported()&&this.handleSetRawMode(!1)}componentDidCatch(e){this.handleExit(e)}};zf.default=QL;QL.displayName="InternalApp"});var JDe=H(Jf=>{"use strict";var S1t=Jf&&Jf.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r),Object.defineProperty(t,s,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),b1t=Jf&&Jf.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),D1t=Jf&&Jf.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&S1t(e,t,r);return b1t(e,t),e},Zf=Jf&&Jf.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Jf,"__esModule",{value:!0});var P1t=Zf(Ln()),KDe=jSe(),x1t=Zf(ibe()),k1t=Zf(yK()),R1t=Zf(ube()),T1t=Zf(hbe()),Cz=Zf(iDe()),Q1t=Zf(IDe()),F1t=Zf(CK()),N1t=Zf(vDe()),O1t=D1t($K()),L1t=Zf(az()),_1t=Zf(YDe()),X1=process.env.CI==="false"?!1:R1t.default,zDe=()=>{},Bz=class{constructor(e){this.resolveExitPromise=()=>{},this.rejectExitPromise=()=>{},this.unsubscribeExit=()=>{},this.onRender=()=>{if(this.isUnmounted)return;let{output:r,outputHeight:s,staticOutput:a}=Q1t.default(this.rootNode,this.options.stdout.columns||80),n=a&&a!==`
`;if(this.options.debug){n&&(this.fullStaticOutput+=a),this.options.stdout.write(this.fullStaticOutput+r);return}if(X1){n&&this.options.stdout.write(a),this.lastOutput=r;return}if(n&&(this.fullStaticOutput+=a),s>=this.options.stdout.rows){this.options.stdout.write(k1t.default.clearTerminal+this.fullStaticOutput+r),this.lastOutput=r;return}n&&(this.log.clear(),this.options.stdout.write(a),this.log(r)),!n&&r!==this.lastOutput&&this.throttledLog(r),this.lastOutput=r},T1t.default(this),this.options=e,this.rootNode=O1t.createNode("ink-root"),this.rootNode.onRender=e.debug?this.onRender:KDe(this.onRender,32,{leading:!0,trailing:!0}),this.rootNode.onImmediateRender=this.onRender,this.log=x1t.default.create(e.stdout),this.throttledLog=e.debug?this.log:KDe(this.log,void 0,{leading:!0,trailing:!0}),this.isUnmounted=!1,this.lastOutput="",this.fullStaticOutput="",this.container=Cz.default.createContainer(this.rootNode,0,!1,null),this.unsubscribeExit=F1t.default(this.unmount,{alwaysLast:!1}),e.patchConsole&&this.patchConsole(),X1||(e.stdout.on("resize",this.onRender),this.unsubscribeResize=()=>{e.stdout.off("resize",this.onRender)})}render(e){let r=P1t.default.createElement(_1t.default,{stdin:this.options.stdin,stdout:this.options.stdout,stderr:this.options.stderr,writeToStdout:this.writeToStdout,writeToStderr:this.writeToStderr,exitOnCtrlC:this.options.exitOnCtrlC,onExit:this.unmount},e);Cz.default.updateContainer(r,this.container,null,zDe)}writeToStdout(e){if(!this.isUnmounted){if(this.options.debug){this.options.stdout.write(e+this.fullStaticOutput+this.lastOutput);return}if(X1){this.options.stdout.write(e);return}this.log.clear(),this.options.stdout.write(e),this.log(this.lastOutput)}}writeToStderr(e){if(!this.isUnmounted){if(this.options.debug){this.options.stderr.write(e),this.options.stdout.write(this.fullStaticOutput+this.lastOutput);return}if(X1){this.options.stderr.write(e);return}this.log.clear(),this.options.stderr.write(e),this.log(this.lastOutput)}}unmount(e){this.isUnmounted||(this.onRender(),this.unsubscribeExit(),typeof this.restoreConsole=="function"&&this.restoreConsole(),typeof this.unsubscribeResize=="function"&&this.unsubscribeResize(),X1?this.options.stdout.write(this.lastOutput+`
`):this.options.debug||this.log.done(),this.isUnmounted=!0,Cz.default.updateContainer(null,this.container,null,zDe),L1t.default.delete(this.options.stdout),e instanceof Error?this.rejectExitPromise(e):this.resolveExitPromise())}waitUntilExit(){return this.exitPromise||(this.exitPromise=new Promise((e,r)=>{this.resolveExitPromise=e,this.rejectExitPromise=r})),this.exitPromise}clear(){!X1&&!this.options.debug&&this.log.clear()}patchConsole(){this.options.debug||(this.restoreConsole=N1t.default((e,r)=>{e==="stdout"&&this.writeToStdout(r),e==="stderr"&&(r.startsWith("The above error occurred")||this.writeToStderr(r))}))}};Jf.default=Bz});var XDe=H(DP=>{"use strict";var ZDe=DP&&DP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(DP,"__esModule",{value:!0});var M1t=ZDe(JDe()),FL=ZDe(az()),U1t=Ae("stream"),H1t=(t,e)=>{let r=Object.assign({stdout:process.stdout,stdin:process.stdin,stderr:process.stderr,debug:!1,exitOnCtrlC:!0,patchConsole:!0},j1t(e)),s=G1t(r.stdout,()=>new M1t.default(r));return s.render(t),{rerender:s.render,unmount:()=>s.unmount(),waitUntilExit:s.waitUntilExit,cleanup:()=>FL.default.delete(r.stdout),clear:s.clear}};DP.default=H1t;var j1t=(t={})=>t instanceof U1t.Stream?{stdout:t,stdin:process.stdin}:t,G1t=(t,e)=>{let r;return FL.default.has(t)?r=FL.default.get(t):(r=e(),FL.default.set(t,r)),r}});var ePe=H(nd=>{"use strict";var q1t=nd&&nd.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r),Object.defineProperty(t,s,{enumerable:!0,get:function(){return e[r]}})}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),V1t=nd&&nd.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),W1t=nd&&nd.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.hasOwnProperty.call(t,r)&&q1t(e,t,r);return V1t(e,t),e};Object.defineProperty(nd,"__esModule",{value:!0});var PP=W1t(Ln()),$De=t=>{let{items:e,children:r,style:s}=t,[a,n]=PP.useState(0),l=PP.useMemo(()=>e.slice(a),[e,a]);PP.useLayoutEffect(()=>{n(e.length)},[e.length]);let f=l.map((A,m)=>r(A,a+m)),h=PP.useMemo(()=>Object.assign({position:"absolute",flexDirection:"column"},s),[s]);return PP.default.createElement("ink-box",{internal_static:!0,style:h},f)};$De.displayName="Static";nd.default=$De});var rPe=H(xP=>{"use strict";var Y1t=xP&&xP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(xP,"__esModule",{value:!0});var K1t=Y1t(Ln()),tPe=({children:t,transform:e})=>t==null?null:K1t.default.createElement("ink-text",{style:{flexGrow:0,flexShrink:1,flexDirection:"row"},internal_transform:e},t);tPe.displayName="Transform";xP.default=tPe});var iPe=H(kP=>{"use strict";var z1t=kP&&kP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(kP,"__esModule",{value:!0});var J1t=z1t(Ln()),nPe=({count:t=1})=>J1t.default.createElement("ink-text",null,`
`.repeat(t));nPe.displayName="Newline";kP.default=nPe});var aPe=H(RP=>{"use strict";var sPe=RP&&RP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(RP,"__esModule",{value:!0});var Z1t=sPe(Ln()),X1t=sPe(TL()),oPe=()=>Z1t.default.createElement(X1t.default,{flexGrow:1});oPe.displayName="Spacer";RP.default=oPe});var NL=H(TP=>{"use strict";var $1t=TP&&TP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(TP,"__esModule",{value:!0});var e2t=Ln(),t2t=$1t(fz()),r2t=()=>e2t.useContext(t2t.default);TP.default=r2t});var lPe=H(QP=>{"use strict";var n2t=QP&&QP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(QP,"__esModule",{value:!0});var cPe=Ln(),i2t=n2t(NL()),s2t=(t,e={})=>{let{stdin:r,setRawMode:s,internal_exitOnCtrlC:a}=i2t.default();cPe.useEffect(()=>{if(e.isActive!==!1)return s(!0),()=>{s(!1)}},[e.isActive,s]),cPe.useEffect(()=>{if(e.isActive===!1)return;let n=l=>{let f=String(l),h={upArrow:f==="\x1B[A",downArrow:f==="\x1B[B",leftArrow:f==="\x1B[D",rightArrow:f==="\x1B[C",pageDown:f==="\x1B[6~",pageUp:f==="\x1B[5~",return:f==="\r",escape:f==="\x1B",ctrl:!1,shift:!1,tab:f===" "||f==="\x1B[Z",backspace:f==="\b",delete:f==="\x7F"||f==="\x1B[3~",meta:!1};f<=""&&!h.return&&(f=String.fromCharCode(f.charCodeAt(0)+97-1),h.ctrl=!0),f.startsWith("\x1B")&&(f=f.slice(1),h.meta=!0);let A=f>="A"&&f<="Z",m=f>="\u0410"&&f<="\u042F";f.length===1&&(A||m)&&(h.shift=!0),h.tab&&f==="[Z"&&(h.shift=!0),(h.tab||h.backspace||h.delete)&&(f=""),(!(f==="c"&&h.ctrl)||!a)&&t(f,h)};return r?.on("data",n),()=>{r?.off("data",n)}},[e.isActive,r,a,t])};QP.default=s2t});var uPe=H(FP=>{"use strict";var o2t=FP&&FP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(FP,"__esModule",{value:!0});var a2t=Ln(),c2t=o2t(lz()),l2t=()=>a2t.useContext(c2t.default);FP.default=l2t});var fPe=H(NP=>{"use strict";var u2t=NP&&NP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(NP,"__esModule",{value:!0});var f2t=Ln(),h2t=u2t(Az()),A2t=()=>f2t.useContext(h2t.default);NP.default=A2t});var hPe=H(OP=>{"use strict";var p2t=OP&&OP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(OP,"__esModule",{value:!0});var d2t=Ln(),g2t=p2t(dz()),m2t=()=>d2t.useContext(g2t.default);OP.default=m2t});var pPe=H(_P=>{"use strict";var APe=_P&&_P.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(_P,"__esModule",{value:!0});var LP=Ln(),y2t=APe(RL()),E2t=APe(NL()),I2t=({isActive:t=!0,autoFocus:e=!1,id:r}={})=>{let{isRawModeSupported:s,setRawMode:a}=E2t.default(),{activeId:n,add:l,remove:f,activate:h,deactivate:A,focus:m}=LP.useContext(y2t.default),w=LP.useMemo(()=>r??Math.random().toString().slice(2,7),[r]);return LP.useEffect(()=>(l(w,{autoFocus:e}),()=>{f(w)}),[w,e]),LP.useEffect(()=>{t?h(w):A(w)},[t,w]),LP.useEffect(()=>{if(!(!s||!t))return a(!0),()=>{a(!1)}},[t]),{isFocused:!!w&&n===w,focus:m}};_P.default=I2t});var dPe=H(MP=>{"use strict";var w2t=MP&&MP.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(MP,"__esModule",{value:!0});var C2t=Ln(),B2t=w2t(RL()),v2t=()=>{let t=C2t.useContext(B2t.default);return{enableFocus:t.enableFocus,disableFocus:t.disableFocus,focusNext:t.focusNext,focusPrevious:t.focusPrevious,focus:t.focus}};MP.default=v2t});var gPe=H(vz=>{"use strict";Object.defineProperty(vz,"__esModule",{value:!0});vz.default=t=>{var e,r,s,a;return{width:(r=(e=t.yogaNode)===null||e===void 0?void 0:e.getComputedWidth())!==null&&r!==void 0?r:0,height:(a=(s=t.yogaNode)===null||s===void 0?void 0:s.getComputedHeight())!==null&&a!==void 0?a:0}}});var Du=H(Wo=>{"use strict";Object.defineProperty(Wo,"__esModule",{value:!0});var S2t=XDe();Object.defineProperty(Wo,"render",{enumerable:!0,get:function(){return S2t.default}});var b2t=TL();Object.defineProperty(Wo,"Box",{enumerable:!0,get:function(){return b2t.default}});var D2t=wz();Object.defineProperty(Wo,"Text",{enumerable:!0,get:function(){return D2t.default}});var P2t=ePe();Object.defineProperty(Wo,"Static",{enumerable:!0,get:function(){return P2t.default}});var x2t=rPe();Object.defineProperty(Wo,"Transform",{enumerable:!0,get:function(){return x2t.default}});var k2t=iPe();Object.defineProperty(Wo,"Newline",{enumerable:!0,get:function(){return k2t.default}});var R2t=aPe();Object.defineProperty(Wo,"Spacer",{enumerable:!0,get:function(){return R2t.default}});var T2t=lPe();Object.defineProperty(Wo,"useInput",{enumerable:!0,get:function(){return T2t.default}});var Q2t=uPe();Object.defineProperty(Wo,"useApp",{enumerable:!0,get:function(){return Q2t.default}});var F2t=NL();Object.defineProperty(Wo,"useStdin",{enumerable:!0,get:function(){return F2t.default}});var N2t=fPe();Object.defineProperty(Wo,"useStdout",{enumerable:!0,get:function(){return N2t.default}});var O2t=hPe();Object.defineProperty(Wo,"useStderr",{enumerable:!0,get:function(){ Line truncated
`:"";return l?w+=`@IF EXIST ${l} (\r
${l} ${h} ${a} ${m}%*\r
) ELSE (\r
@SETLOCAL\r
@SET PATHEXT=%PATHEXT:;.JS;=;%\r
${f} ${h} ${a} ${m}%*\r
)\r
`:w+=`@${f} ${h} ${a} ${m}%*\r
`,w}function uvt(t,e,r){let s=xu.relative(xu.dirname(e),t),a=r.prog&&r.prog.split("\\").join("/"),n;s=s.split("\\").join("/");let l=xu.isAbsolute(s)?`"${s}"`:`"$basedir/${s}"`,f=r.args||"",h=EJ(r.nodePath).posix;a?(n=`"$basedir/${r.prog}"`,s=l):(a=l,f="",s="");let A=r.progArgs?`${r.progArgs.join(" ")} `:"",m=`#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\\\,/,g')")
case \`uname\` in
*CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
esac
`,w=r.nodePath?`export NODE_PATH="${h}"
`:"";return n?m+=`${w}if [ -x ${n} ]; then
exec ${n} ${f} ${s} ${A}"$@"
else
exec ${a} ${f} ${s} ${A}"$@"
fi
`:m+=`${w}${a} ${f} ${s} ${A}"$@"
exit $?
`,m}function fvt(t,e,r){let s=xu.relative(xu.dirname(e),t),a=r.prog&&r.prog.split("\\").join("/"),n=a&&`"${a}$exe"`,l;s=s.split("\\").join("/");let f=xu.isAbsolute(s)?`"${s}"`:`"$basedir/${s}"`,h=r.args||"",A=EJ(r.nodePath),m=A.win32,w=A.posix;n?(l=`"$basedir/${r.prog}$exe"`,s=f):(n=f,h="",s="");let v=r.progArgs?`${r.progArgs.join(" ")} `:"",D=`#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
${r.nodePath?`$env_node_path=$env:NODE_PATH
$env:NODE_PATH="${m}"
`:""}if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}`;return r.nodePath&&(D+=` else {
$env:NODE_PATH="${w}"
}`),l?D+=`
$ret=0
if (Test-Path ${l}) {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & ${l} ${h} ${s} ${v}$args
} else {
& ${l} ${h} ${s} ${v}$args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & ${n} ${h} ${s} ${v}$args
} else {
& ${n} ${h} ${s} ${v}$args
}
$ret=$LASTEXITCODE
}
${r.nodePath?`$env:NODE_PATH=$env_node_path
`:""}exit $ret
`:D+=`
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & ${n} ${h} ${s} ${v}$args
} else {
& ${n} ${h} ${s} ${v}$args
}
${r.nodePath?`$env:NODE_PATH=$env_node_path
`:""}exit $LASTEXITCODE
`,D}function hvt(t,e){return e.fs_.chmod(t,493)}function EJ(t){if(!t)return{win32:"",posix:""};let e=typeof t=="string"?t.split(xu.delimiter):Array.from(t),r={};for(let s=0;s<e.length;s++){let a=e[s].split("/").join("\\"),n=kxe()?e[s].split("\\").join("/").replace(/^([^:\\/]*):/,(l,f)=>`/mnt/${f.toLowerCase()}`):e[s];r.win32=r.win32?`${r.win32};${a}`:a,r.posix=r.posix?`${r.posix}:${n}`:n,r[s]={win32:a,posix:n}}return r}Txe.exports=yJ});var TJ=H((DEr,eke)=>{eke.exports=Ae("stream")});var ike=H((PEr,nke)=>{"use strict";function tke(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(t);e&&(s=s.filter(function(a){return Object.getOwnPropertyDescriptor(t,a).enumerable})),r.push.apply(r,s)}return r}function zvt(t){for(var e=1;e<arguments.length;e++){var r=arguments[e]!=null?arguments[e]:{};e%2?tke(Object(r),!0).forEach(function(s){Jvt(t,s,r[s])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):tke(Object(r)).forEach(function(s){Object.defineProperty(t,s,Object.getOwnPropertyDescriptor(r,s))})}return t}function Jvt(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function Zvt(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function rke(t,e){for(var r=0;r<e.length;r++){var s=e[r];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(t,s.key,s)}}function Xvt(t,e,r){return e&&rke(t.prototype,e),r&&rke(t,r),t}var $vt=Ae("buffer"),l_=$vt.Buffer,eSt=Ae("util"),QJ=eSt.inspect,tSt=QJ&&QJ.custom||"inspect";function rSt(t,e,r){l_.prototype.copy.call(t,e,r)}nke.exports=function(){function t(){Zvt(this,t),this.head=null,this.tail=null,this.length=0}return Xvt(t,[{key:"push",value:function(r){var s={data:r,next:null};this.length>0?this.tail.next=s:this.head=s,this.tail=s,++this.length}},{key:"unshift",value:function(r){var s={data:r,next:this.head};this.length===0&&(this.tail=s),this.head=s,++this.length}},{key:"shift",value:function(){if(this.length!==0){var r=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,r}}},{key:"clear",value:function(){this.head=this.tail=null,this.length=0}},{key:"join",value:function(r){if(this.length===0)return"";for(var s=this.head,a=""+s.data;s=s.next;)a+=r+s.data;return a}},{key:"concat",value:function(r){if(this.length===0)return l_.alloc(0);for(var s=l_.allocUnsafe(r>>>0),a=this.head,n=0;a;)rSt(a.data,s,n),n+=a.data.length,a=a.next;return s}},{key:"consume",value:function(r,s){var a;return r<this.head.data.length?(a=this.head.data.slice(0,r),this.head.data=this.head.data.slice(r)):r===this.head.data.length?a=this.shift():a=s?this._getString(r):this._getBuffer(r),a}},{key:"first",value:function(){return this.head.data}},{key:"_getString",value:function(r){var s=this.head,a=1,n=s.data;for(r-=n.length;s=s.next;){var l=s.data,f=r>l.length?l.length:r;if(f===l.length?n+=l:n+=l.slice(0,r),r-=f,r===0){f===l.length?(++a,s.next?this.head=s.next:this.head=this.tail=null):(this.head=s,s.data=l.slice(f));break}++a}return this.length-=a,n}},{key:"_getBuffer",value:function(r){var s=l_.allocUnsafe(r),a=this.head,n=1;for(a.data.copy(s),r-=a.data.length;a=a.next;){var l=a.data,f=r>l.length?l.length:r;if(l.copy(s,s.length-r,0,f),r-=f,r===0){f===l.length?(++n,a.next?this.head=a.next:this.head=this.tail=null):(this.head=a,a.data=l.slice(f));break}++n}return this.length-=n,s}},{key:tSt,value:function(r,s){return QJ(this,zvt({},s,{depth:0,customInspect:!1}))}}]),t}()});var NJ=H((xEr,oke)=>{"use strict";function nSt(t,e){var r=this,s=this._readableState&&this._readableState.destroyed,a=this._writableState&&this._writableState.destroyed;return s||a?(e?e(t):t&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,process.nextTick(FJ,this,t)):process.nextTick(FJ,this,t)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(t||null,function(n){!e&&n?r._writableState?r._writableState.errorEmitted?process.nextTick(u_,r):(r._writableState.errorEmitted=!0,process.nextTick(ske,r,n)):process.nextTick(ske,r,n):e?(process.nextTick(u_,r),e(n)):process.nextTick(u_,r)}),this)}function ske(t,e){FJ(t,e),u_(t)}function u_(t){t._writableState&&!t._writableState.emitClose||t._readableState&&!t._readableState.emitClose||t.emit("close")}function iSt(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function FJ(t,e){t.emit("error",e)}function sSt(t,e){var r=t._readableState,s=t._writableState;r&& Line truncated
`)),t.linkname&&(e+=lZ(" linkpath="+t.linkname+`
`));var r=t.pax;if(r)for(var s in r)e+=lZ(" "+s+"="+r[s]+`
`);return Buffer.from(e)};E2.decodePax=function(t){for(var e={};t.length;){for(var r=0;r<t.length&&t[r]!==32;)r++;var s=parseInt(t.slice(0,r).toString(),10);if(!s)return e;var a=t.slice(r+1,s-1).toString(),n=a.indexOf("=");if(n===-1)return e;e[a.slice(0,n)]=a.slice(n+1),t=t.slice(s)}return e};E2.encode=function(t){var e=Zbt(512),r=t.name,s="";if(t.typeflag===5&&r[r.length-1]!=="/"&&(r+="/"),Buffer.byteLength(r)!==r.length)return null;for(;Buffer.byteLength(r)>100;){var a=r.indexOf("/");if(a===-1)return null;s+=s?"/"+r.slice(0,a):r.slice(0,a),r=r.slice(a+1)}return Buffer.byteLength(r)>100||Buffer.byteLength(s)>155||t.linkname&&Buffer.byteLength(t.linkname)>100?null:(e.write(r),e.write(Og(t.mode&nDt,6),100),e.write(Og(t.uid,6),108),e.write(Og(t.gid,6),116),e.write(Og(t.size,11),124),e.write(Og(t.mtime.getTime()/1e3|0,11),136),e[156]=oRe+oDt(t.type),t.linkname&&e.write(t.linkname,157),aRe.copy(e,xx),eDt.copy(e,uZ),t.uname&&e.write(t.uname,265),t.gname&&e.write(t.gname,297),e.write(Og(t.devmajor||0,6),329),e.write(Og(t.devminor||0,6),337),s&&e.write(s,345),e.write(Og(lRe(e),6),148),e)};E2.decode=function(t,e,r){var s=t[156]===0?0:t[156]-oRe,a=y2(t,0,100,e),n=Lg(t,100,8),l=Lg(t,108,8),f=Lg(t,116,8),h=Lg(t,124,12),A=Lg(t,136,12),m=sDt(s),w=t[157]===0?null:y2(t,157,100,e),v=y2(t,265,32),D=y2(t,297,32),I=Lg(t,329,8),R=Lg(t,337,8),N=lRe(t);if(N===8*32)return null;if(N!==Lg(t,148,8))throw new Error("Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?");if(aRe.compare(t,xx,xx+6)===0)t[345]&&(a=y2(t,345,155,e)+"/"+a);else if(!(tDt.compare(t,xx,xx+6)===0&&rDt.compare(t,uZ,uZ+2)===0)){if(!r)throw new Error("Invalid tar header: unknown format.")}return s===0&&a&&a[a.length-1]==="/"&&(s=5),{name:a,mode:n,uid:l,gid:f,size:h,mtime:new Date(1e3*A),type:m,linkname:w,uname:v,gname:D,devmajor:I,devminor:R}}});var gRe=H((zEr,dRe)=>{var fRe=Ae("util"),cDt=sRe(),kx=fZ(),hRe=m2().Writable,ARe=m2().PassThrough,pRe=function(){},uRe=function(t){return t&=511,t&&512-t},lDt=function(t,e){var r=new S_(t,e);return r.end(),r},uDt=function(t,e){return e.path&&(t.name=e.path),e.linkpath&&(t.linkname=e.linkpath),e.size&&(t.size=parseInt(e.size,10)),t.pax=e,t},S_=function(t,e){this._parent=t,this.offset=e,ARe.call(this,{autoDestroy:!1})};fRe.inherits(S_,ARe);S_.prototype.destroy=function(t){this._parent.destroy(t)};var fd=function(t){if(!(this instanceof fd))return new fd(t);hRe.call(this,t),t=t||{},this._offset=0,this._buffer=cDt(),this._missing=0,this._partial=!1,this._onparse=pRe,this._header=null,this._stream=null,this._overflow=null,this._cb=null,this._locked=!1,this._destroyed=!1,this._pax=null,this._paxGlobal=null,this._gnuLongPath=null,this._gnuLongLinkPath=null;var e=this,r=e._buffer,s=function(){e._continue()},a=function(v){if(e._locked=!1,v)return e.destroy(v);e._stream||s()},n=function(){e._stream=null;var v=uRe(e._header.size);v?e._parse(v,l):e._parse(512,w),e._locked||s()},l=function(){e._buffer.consume(uRe(e._header.size)),e._parse(512,w),s()},f=function(){var v=e._header.size;e._paxGlobal=kx.decodePax(r.slice(0,v)),r.consume(v),n()},h=function(){var v=e._header.size;e._pax=kx.decodePax(r.slice(0,v)),e._paxGlobal&&(e._pax=Object.assign({},e._paxGlobal,e._pax)),r.consume(v),n()},A=function(){var v=e._header.size;this._gnuLongPath=kx.decodeLongPath(r.slice(0,v),t.filenameEncoding),r.consume(v),n()},m=function(){var v=e._header.size;this._gnuLongLinkPath=kx.decodeLongPath(r.slice(0,v),t.filenameEncoding),r.consume(v),n()},w=function(){var v=e._offset,D;try{D=e._header=kx.decode(r.slice(0,512),t.filenameEncoding,t.allowUnknownFormat)}catch(I){e.emit("error",I)}if(r.consume(512),!D){e._parse(512,w),s();return}if(D.type==="gnu-long-path"){e._parse(D.size,A),s();return}if(D.type==="gnu-long-link-path"){e._parse(D.size,m),s();return}if(D.type==="pax-global-header"){e._parse(D.size,f),s();return}if(D.type==="pax-header"){e._parse(D.size,h),s();return}if(e._gnuLongPath&&(D.name=e._gnuLongPath,e._gnuLongPath=null),e._gnuLongLinkPath&&(D.linkname=e._gnuLongLinkPath,e._gnuLongLinkPath=null),e._pax&&(e._header=D=uDt(D,e._pax),e._pax=null),e._locked=!0,!D.size||D.type==="directory"){e._parse(512,w),e.emit("entry",D,lDt(e,v),a);return}e._stream=new S_(e,v),e.emit("entry",D,e._stream,a),e._parse(D.size,n),s()};this._onheader=w,this._parse(512,w)};fRe.inherits(fd,hRe);fd.prototype.destroy=function(t){this._destroyed||(this._destroyed=!0,t&&this.emit("error",t),this.emit("close"),this._stream&&this._stream.emit("close"))};fd.prototype._parse=function(t,e){this._destroyed||(this._offset+=t,this._missing=t,e===this._onheader&&(this._partial=!1),this._onparse=e)};fd.prototype._continue=function(){if(!this._destroyed){var t=this._cb;this._cb=pRe,this._overflow?this._write(this._overflow,void 0,t):t()}};fd.prototype._write=function(t,e,r){if(!this._destroyed){var s=this._stream,a=this._buffer,n=this._missing;if(t.length&&(this._partial=!0),t.length<n)return this._missing-=t.length,this._overflow=null,s?s.write(t,r):(a.append(t), Line truncated
Wanted: ${this.expectedSize}
Found: ${this.size}`);s.code="EBADSIZE",s.found=this.size,s.expected=this.expectedSize,s.sri=this.sri,this.emit("error",s)}else if(this.sri&&!r){let s=new Error(`${this.sri} integrity checksum failed when using ${this.algorithm}: wanted ${this.digests} but got ${e}. (${this.size} bytes)`);s.code="EINTEGRITY",s.found=e,s.expected=this.digests,s.algorithm=this.algorithm,s.sri=this.sri,this.emit("error",s)}else this.#t=this.size,this.emit("size",this.size),this.#e=e,this.emit("integrity",e),r&&(this.#r=r,this.emit("verified",r))}},pd=class{get isHash(){return!0}constructor(e,r){let s=r?.strict;this.source=e.trim(),this.digest="",this.algorithm="",this.options=[];let a=this.source.match(s?jDt:HDt);if(!a||s&&!PZ.includes(a[1]))return;this.algorithm=a[1],this.digest=a[2];let n=a[3];n&&(this.options=n.slice(1).split("?"))}hexDigest(){return this.digest&&Buffer.from(this.digest,"base64").toString("hex")}toJSON(){return this.toString()}match(e,r){let s=_l(e,r);if(!s)return!1;if(s.isIntegrity){let a=s.pickAlgorithm(r,[this.algorithm]);if(!a)return!1;let n=s[a].find(l=>l.digest===this.digest);return n||!1}return s.digest===this.digest?s:!1}toString(e){return e?.strict&&!(PZ.includes(this.algorithm)&&this.digest.match(UDt)&&this.options.every(r=>r.match(GDt)))?"":`${this.algorithm}-${this.digest}${_x(this.options)}`}};function LRe(t,e,r,s){let a=t!=="",n=!1,l="",f=s.length-1;for(let A=0;A<f;A++){let m=pd.prototype.toString.call(s[A],r);m&&(n=!0,l+=m,l+=e)}let h=pd.prototype.toString.call(s[f],r);return h&&(n=!0,l+=h),a&&n?t+e+l:t+l}var DE=class{get isIntegrity(){return!0}toJSON(){return this.toString()}isEmpty(){return Object.keys(this).length===0}toString(e){let r=e?.sep||" ",s="";if(e?.strict){r=r.replace(/\S+/g," ");for(let a of PZ)this[a]&&(s=LRe(s,r,e,this[a]))}else for(let a of Object.keys(this))s=LRe(s,r,e,this[a]);return s}concat(e,r){let s=typeof e=="string"?e:Ox(e,r);return _l(`${this.toString(r)} ${s}`,r)}hexDigest(){return _l(this,{single:!0}).hexDigest()}merge(e,r){let s=_l(e,r);for(let a in s)if(this[a]){if(!this[a].find(n=>s[a].find(l=>n.digest===l.digest)))throw new Error("hashes do not match, cannot update integrity")}else this[a]=s[a]}match(e,r){let s=_l(e,r);if(!s)return!1;let a=s.pickAlgorithm(r,Object.keys(this));return!!a&&this[a]&&s[a]&&this[a].find(n=>s[a].find(l=>n.digest===l.digest))||!1}pickAlgorithm(e,r){let s=e?.pickAlgorithm||ZDt,a=Object.keys(this).filter(n=>r?.length?r.includes(n):!0);return a.length?a.reduce((n,l)=>s(n,l)||n):null}};AA.exports.parse=_l;function _l(t,e){if(!t)return null;if(typeof t=="string")return DZ(t,e);if(t.algorithm&&t.digest){let r=new DE;return r[t.algorithm]=[t],DZ(Ox(r,e),e)}else return DZ(Ox(t,e),e)}function DZ(t,e){if(e?.single)return new pd(t,e);let r=t.trim().split(/\s+/).reduce((s,a)=>{let n=new pd(a,e);if(n.algorithm&&n.digest){let l=n.algorithm;s[l]||(s[l]=[]),s[l].push(n)}return s},new DE);return r.isEmpty()?null:r}AA.exports.stringify=Ox;function Ox(t,e){return t.algorithm&&t.digest?pd.prototype.toString.call(t,e):typeof t=="string"?Ox(_l(t,e),e):DE.prototype.toString.call(t,e)}AA.exports.fromHex=qDt;function qDt(t,e,r){let s=_x(r?.options);return _l(`${e}-${Buffer.from(t,"hex").toString("base64")}${s}`,r)}AA.exports.fromData=VDt;function VDt(t,e){let r=e?.algorithms||[...kZ],s=_x(e?.options);return r.reduce((a,n)=>{let l=Lx.createHash(n).update(t).digest("base64"),f=new pd(`${n}-${l}${s}`,e);if(f.algorithm&&f.digest){let h=f.algorithm;a[h]||(a[h]=[]),a[h].push(f)}return a},new DE)}AA.exports.fromStream=WDt;function WDt(t,e){let r=RZ(e);return new Promise((s,a)=>{t.pipe(r),t.on("error",a),r.on("error",a);let n;r.on("integrity",l=>{n=l}),r.on("end",()=>s(n)),r.resume()})}AA.exports.checkData=YDt;function YDt(t,e,r){if(e=_l(e,r),!e||!Object.keys(e).length){if(r?.error)throw Object.assign(new Error("No valid integrity hashes to check against"),{code:"EINTEGRITY"});return!1}let s=e.pickAlgorithm(r),a=Lx.createHash(s).update(t).digest("base64"),n=_l({algorithm:s,digest:a}),l=n.match(e,r);if(r=r||{},l||!r.error)return l;if(typeof r.size=="number"&&t.length!==r.size){let f=new Error(`data size mismatch when checking ${e}.
Wanted: ${r.size}
Found: ${t.length}`);throw f.code="EBADSIZE",f.found=t.length,f.expected=r.size,f.sri=e,f}else{let f=new Error(`Integrity checksum failed when using ${s}: Wanted ${e}, but got ${n}. (${t.length} bytes)`);throw f.code="EINTEGRITY",f.found=n,f.expected=e,f.algorithm=s,f.sri=e,f}}AA.exports.checkStream=KDt;function KDt(t,e,r){if(r=r||Object.create(null),r.integrity=e,e=_l(e,r),!e||!Object.keys(e).length)return Promise.reject(Object.assign(new Error("No valid integrity hashes to check against"),{code:"EINTEGRITY"}));let s=RZ(r);return new Promise((a,n)=>{t.pipe(s),t.on("error",n),s.on("error",n);let l;s.on("verified",f=>{l=f}),s.on("end",()=>a(l)),s.resume()})}AA.exports.integrityStream=RZ;function RZ(t=Object.create(null)){return new xZ(t)}AA.exports.create=zDt;function zDt(t){let e=t?.algorithms||[...kZ],r=_x(t?.options),s=e.map(Lx.createHash);return{update:function(a,n){return s.forEach(l=>l.update(a,n)),this},digest:function(){return e.reduce((n,l)=>{let f=s.shift().digest("base64"),h=new pd(`${l}-${f}${r}`,t);if(h.algorithm&&h.digest){let A=h.algorithm;n[A]||(n[A]=[]),n[A].push(h)}return n},new DE)}}}var JDt=Lx.getHashes(),_Re=["md5","whirlpool","sha1","sha224","sha256","sha384","sha512","sha3","sha3-256","sha3-384","sha3-512","sha3_256","sha3_384","sha3_512"].filter(t=>JDt.includes(t));function ZDt(t,e){return _Re.indexOf(t.toLowerCase())>=_Re.indexOf(e.toLowerCase())?t:e}});var U_=H(Mg=>{"use strict";Object.defineProperty(Mg,"__esModule",{value:!0});Mg.Signature=Mg.Envelope=void 0;Mg.Envelope={fromJSON(t){return{payload:M_(t.payload)?Buffer.from(URe(t.payload)):Buffer.alloc(0),payloadType:M_(t.payloadType)?globalThis.String(t.payloadType):"",signatures:globalThis.Array.isArray(t?.signatures)?t.signatures.map(e=>Mg.Signature.fromJSON(e)):[]}},toJSON(t){let e={};return t.payload.length!==0&&(e.payload=HRe(t.payload)),t.payloadType!==""&&(e.payloadType=t.payloadType),t.signatures?.length&&(e.signatures=t.signatures.map(r=>Mg.Signature.toJSON(r))),e}};Mg.Signature={fromJSON(t){return{sig:M_(t.sig)?Buffer.from(URe(t.sig)):Buffer.alloc(0),keyid:M_(t.keyid)?globalThis.String(t.keyid):""}},toJSON(t){let e={};return t.sig.length!==0&&(e.sig=HRe(t.sig)),t.keyid!==""&&(e.keyid=t.keyid),e}};function URe(t){return Uint8Array.from(globalThis.Buffer.from(t,"base64"))}function HRe(t){return globalThis.Buffer.from(t).toString("base64")}function M_(t){return t!=null}});var GRe=H(H_=>{"use strict";Object.defineProperty(H_,"__esModule",{value:!0});H_.Timestamp=void 0;H_.Timestamp={fromJSON(t){return{seconds:jRe(t.seconds)?globalThis.String(t.seconds):"0",nanos:jRe(t.nanos)?globalThis.Number(t.nanos):0}},toJSON(t){let e={};return t.seconds!=="0"&&(e.seconds=t.seconds),t.nanos!==0&&(e.nanos=Math.round(t.nanos)),e}};function jRe(t){return t!=null}});var dd=H(sn=>{"use strict";Object.defineProperty(sn,"__esModule",{value:!0});sn.TimeRange=sn.X509CertificateChain=sn.SubjectAlternativeName=sn.X509Certificate=sn.DistinguishedName=sn.ObjectIdentifierValuePair=sn.ObjectIdentifier=sn.PublicKeyIdentifier=sn.PublicKey=sn.RFC3161SignedTimestamp=sn.LogId=sn.MessageSignature=sn.HashOutput=sn.SubjectAlternativeNameType=sn.PublicKeyDetails=sn.HashAlgorithm=void 0;sn.hashAlgorithmFromJSON=VRe;sn.hashAlgorithmToJSON=WRe;sn.publicKeyDetailsFromJSON=YRe;sn.publicKeyDetailsToJSON=KRe;sn.subjectAlternativeNameTypeFromJSON=zRe;sn.subjectAlternativeNameTypeToJSON=JRe;var XDt=GRe(),$c;(function(t){t[t.HASH_ALGORITHM_UNSPECIFIED=0]="HASH_ALGORITHM_UNSPECIFIED",t[t.SHA2_256=1]="SHA2_256",t[t.SHA2_384=2]="SHA2_384",t[t.SHA2_512=3]="SHA2_512",t[t.SHA3_256=4]="SHA3_256",t[t.SHA3_384=5]="SHA3_384"})($c||(sn.HashAlgorithm=$c={}));function VRe(t){switch(t){case 0:case"HASH_ALGORITHM_UNSPECIFIED":return $c.HASH_ALGORITHM_UNSPECIFIED;case 1:case"SHA2_256":return $c.SHA2_256;case 2:case"SHA2_384":return $c.SHA2_384;case 3:case"SHA2_512":return $c.SHA2_512;case 4:case"SHA3_256":return $c.SHA3_256;case 5:case"SHA3_384":return $c.SHA3_384;default:throw new globalThis.Error("Unrecognized enum value "+t+" for enum HashAlgorithm")}}function WRe(t){switch(t){case $c.HASH_ALGORITHM_UNSPECIFIED:return"HASH_ALGORITHM_UNSPECIFIED";case $c.SHA2_256:return"SHA2_256";case $c.SHA2_384:return"SHA2_384";case $c.SHA2_512:return"SHA2_512";case $c.SHA3_256:return"SHA3_256";case $c.SHA3_384:return"SHA3_384";default:throw new globalThis.Error("Unrecognized enum value "+t+" for enum HashAlgorithm")}}var tn;(function(t){t[t.PUBLIC_KEY_DETAILS_UNSPECIFIED=0]="PUBLIC_KEY_DETAILS_UNSPECIFIED",t[t.PKCS1_RSA_PKCS1V5=1]="PKCS1_RSA_PKCS1V5",t[t.PKCS1_RSA_PSS=2]="PKCS1_RSA_PSS",t[t.PKIX_RSA_PKCS1V5=3]="PKIX_RSA_PKCS1V5",t[t.PKIX_RSA_PSS=4]="PKIX_RSA_PSS",t[t.PKIX_RSA_PKCS1V15_2048_SHA256=9]="PKIX_RSA_PKCS1V15_2048_SHA256",t[t.PKIX_RSA_PKCS1V15_3072_SHA256=10]="PKIX_RSA_PKCS1V15_3072_SHA256",t[t.PKIX_RSA_PKCS1V15_4096_SHA256=11]="PKIX_RSA_PKCS1V15_4096_SHA256",t[t.PKIX_RSA_PSS_2048_SHA256=16]="PKIX_RSA_PSS_2048_SHA256",t[t.PKIX_RSA_PSS_3072_SHA256=17]="PKIX_RSA_PSS_3072_SHA256",t[t.PKIX_RS Line truncated
`).forEach(r=>{r.match(qPt)||r.match(VPt)||(e+=r)}),Buffer.from(e,"base64")}function YPt(t,e="CERTIFICATE"){let s=t.toString("base64").match(/.{1,64}/g)||"";return[`-----BEGIN ${e}-----`,...s,`-----END ${e}-----`].join(`
`).concat(`
`)}});var cM=H(Vg=>{"use strict";Object.defineProperty(Vg,"__esModule",{value:!0});Vg.SHA2_HASH_ALGOS=Vg.RSA_SIGNATURE_ALGOS=Vg.ECDSA_SIGNATURE_ALGOS=void 0;Vg.ECDSA_SIGNATURE_ALGOS={"1.2.840.10045.4.3.1":"sha224","1.2.840.10045.4.3.2":"sha256","1.2.840.10045.4.3.3":"sha384","1.2.840.10045.4.3.4":"sha512"};Vg.RSA_SIGNATURE_ALGOS={"1.2.840.113549.1.1.14":"sha224","1.2.840.113549.1.1.11":"sha256","1.2.840.113549.1.1.12":"sha384","1.2.840.113549.1.1.13":"sha512"};Vg.SHA2_HASH_ALGOS={"2.16.840.1.101.3.4.2.1":"sha256","2.16.840.1.101.3.4.2.2":"sha384","2.16.840.1.101.3.4.2.3":"sha512"}});var ZZ=H(lM=>{"use strict";Object.defineProperty(lM,"__esModule",{value:!0});lM.RFC3161TimestampVerificationError=void 0;var JZ=class extends Error{};lM.RFC3161TimestampVerificationError=JZ});var PTe=H(yA=>{"use strict";var KPt=yA&&yA.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(e,r);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,a)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),zPt=yA&&yA.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),JPt=yA&&yA.__importStar||function(){var t=function(e){return t=Object.getOwnPropertyNames||function(r){var s=[];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(s[s.length]=a);return s},t(e)};return function(e){if(e&&e.__esModule)return e;var r={};if(e!=null)for(var s=t(e),a=0;a<s.length;a++)s[a]!=="default"&&KPt(r,e,s[a]);return zPt(r,e),r}}();Object.defineProperty(yA,"__esModule",{value:!0});yA.TSTInfo=void 0;var DTe=JPt(x2()),ZPt=cM(),XPt=ZZ(),XZ=class{root;constructor(e){this.root=e}get version(){return this.root.subs[0].toInteger()}get genTime(){return this.root.subs[4].toDate()}get messageImprintHashAlgorithm(){let e=this.messageImprintObj.subs[0].subs[0].toOID();return ZPt.SHA2_HASH_ALGOS[e]}get messageImprintHashedMessage(){return this.messageImprintObj.subs[1].value}get raw(){return this.root.toDER()}verify(e){let r=DTe.digest(this.messageImprintHashAlgorithm,e);if(!DTe.bufferEqual(r,this.messageImprintHashedMessage))throw new XPt.RFC3161TimestampVerificationError("message imprint does not match artifact")}get messageImprintObj(){return this.root.subs[2]}};yA.TSTInfo=XZ});var kTe=H(EA=>{"use strict";var $Pt=EA&&EA.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(e,r);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,a)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),ext=EA&&EA.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),txt=EA&&EA.__importStar||function(){var t=function(e){return t=Object.getOwnPropertyNames||function(r){var s=[];for(var a in r)Object.prototype.hasOwnProperty.call(r,a)&&(s[s.length]=a);return s},t(e)};return function(e){if(e&&e.__esModule)return e;var r={};if(e!=null)for(var s=t(e),a=0;a<s.length;a++)s[a]!=="default"&&$Pt(r,e,s[a]);return ext(r,e),r}}();Object.defineProperty(EA,"__esModule",{value:!0});EA.RFC3161Timestamp=void 0;var rxt=sM(),$Z=txt(x2()),xTe=cM(),jx=ZZ(),nxt=PTe(),ixt="1.2.840.113549.1.7.2",sxt="1.2.840.113549.1.9.16.1.4",oxt="1.2.840.113549.1.9.4",eX=class t{root;constructor(e){this.root=e}static parse(e){let r=rxt.ASN1Obj.parseBuffer(e);return new t(r)}get status(){return this.pkiStatusInfoObj.subs[0].toInteger()}get contentType(){return this.contentTypeObj.toOID()}get eContentType(){return this.eContentTypeObj.toOID()}get signingTime(){return this.tstInfo.genTime}get signerIssuer(){return this.signerSidObj.subs[0].value}get signerSerialNumber(){return this.signerSidObj.subs[1].value}get signerDigestAlgorithm(){let e=this.signerDigestAlgorithmObj.subs[0].toOID();return xTe.SHA2_HASH_ALGOS[e]}get signatureAlgorithm(){let e=this.signatureAlgorithmObj.subs[0].toOID();return xTe.ECDSA_SIGNATURE_ALGOS[e]}get signatureValue(){return this.signatureValueObj.value}get tstInfo(){return new nxt.TSTInfo(this.eContentObj.subs[0].subs[0])}verify(e,r){if(!this.timeStampTokenObj)throw new jx.RFC3161TimestampVerificationError("timeStampToken is missing");if(this.contentType!==ixt)throw new jx.RFC3161TimestampVerificationError(`incorrect content type: ${this.contentType}`);if(this.eContentType!==sxt)throw new jx.RFC3161TimestampVerificationError(`incorrect encapsulated content type: ${this.eContentType}`);this.tstInfo.verify(e),this.verifyMessageDigest(),this.verifySignature(r)}verifyMessageDigest(){let e=$Z.digest(this.signerDigestAlgorithm,this.tstInfo.raw),r=this.messageDigestAttributeObj.subs[1].subs[0].value;if(!$Z.bufferEqual(e,r))throw new jx.RFC3161TimestampVerificationError("signed data does not match tstInfo")}verifySignature(e){let r=this.signedAttrsObj.toDER();if(r[0]=49,!$Z.verify( Line truncated
\v\f\r\x1B !"#$\u066A&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~\x7F\xB0\xB7\u2219\u221A\u2592\u2500\u2502\u253C\u2524\u252C\u251C\u2534\u2510\u250C\u2514\u2518\u03B2\u221E\u03C6\xB1\xBD\xBC\u2248\xAB\xBB\uFEF7\uFEF8\uFFFD\uFFFD\uFEFB\uFEFC\uFFFD\xA0\xAD\uFE82\xA3\xA4\uFE84\uFFFD\uFFFD\uFE8E\uFE8F\uFE95\uFE99\u060C\uFE9D\uFEA1\uFEA5\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\uFED1\u061B\uFEB1\uFEB5\uFEB9\u061F\xA2\uFE80\uFE81\uFE83\uFE85\uFECA\uFE8B\uFE8D\uFE91\uFE93\uFE97\uFE9B\uFE9F\uFEA3\uFEA7\uFEA9\uFEAB\uFEAD\uFEAF\uFEB3\uFEB7\uFEBB\uFEBF\uFEC1\uFEC5\uFECB\uFECF\xA6\xAC\xF7\xD7\uFEC9\u0640\uFED3\uFED7\uFEDB\uFEDF\uFEE3\uFEE7\uFEEB\uFEED\uFEEF\uFEF3\uFEBD\uFECC\uFECE\uFECD\uFEE1\uFE7D\u0651\uFEE5\uFEE9\uFEEC\uFEF0\uFEF2\uFED0\uFED5\uFEF5\uFEF6\uFEDD\uFED9\uFEF1\u25A0\uFFFD`},ibm864:"cp864",csibm864:"cp864",cp865:{type:"_sbcs",chars:"\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xF8\xA3\xD8\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xA4\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0"},ibm865:"cp865",csibm865:"cp865",cp866:{type:"_sbcs",chars:"\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041A\u041B\u041C\u041D\u041E\u041F\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042A\u042B\u042C\u042D\u042E\u042F\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043A\u043B\u043C\u043D\u043E\u043F\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044A\u044B\u044C\u044D\u044E\u044F\u0401\u0451\u0404\u0454\u0407\u0457\u040E\u045E\xB0\u2219\xB7\u221A\u2116\xA4\u25A0\xA0"},ibm866:"cp866",csibm866:"cp866",cp869:{type:"_sbcs",chars:"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0386\uFFFD\xB7\xAC\xA6\u2018\u2019\u0388\u2015\u0389\u038A\u03AA\u038C\uFFFD\uFFFD\u038E\u03AB\xA9\u038F\xB2\xB3\u03AC\xA3\u03AD\u03AE\u03AF\u03CA\u0390\u03CC\u03CD\u0391\u0392\u0393\u0394\u0395\u0396\u0397\xBD\u0398\u0399\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u039A\u039B\u039C\u039D\u2563\u2551\u2557\u255D\u039E\u039F\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u03A0\u03A1\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u03A3\u03A4\u03A5\u03A6\u03A7\u03A8\u03A9\u03B1\u03B2\u03B3\u2518\u250C\u2588\u2584\u03B4\u03B5\u2580\u03B6\u03B7\u03B8\u03B9\u03BA\u03BB\u03BC\u03BD\u03BE\u03BF\u03C0\u03C1\u03C3\u03C2\u03C4\u0384\xAD\xB1\u03C5\u03C6\u03C7\xA7\u03C8\u0385\xB0\xA8\u03C9\u03CB\u03B0\u03CE\u25A0\xA0"},ibm869:"cp869",csibm869:"cp869",cp922:{type:"_sbcs",chars:"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\u203E\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\u0160\xD1\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\u017D\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\u0161\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\u017E\xFF"},ibm922:"cp922",csibm922:"cp922",cp1046:{type:"_sbcs",chars:"\uFE88\xD7\xF7\uF8F6\uF8F5\uF8F4\uF8F7\uFE71\x88\u25A0\u2502\u2500\u2510\u250C\u2514\u2518\uFE79\uFE7B\uFE7D\uFE7F\uFE77\uFE8A\uFEF0\uFEF3\uFEF2\uFECE\uFECF\uFED0\uFEF6\uFEF8\uFEFA\uFEFC\xA0\uF8FA\uF8F9\uF8F8\xA4\uF8FB\uFE8B\uFE91\uFE97\uFE9B\uFE9F\uFEA3\u060C\xAD\uFEA7\uFEB3\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\uFEB7\u061B\uFEBB\uFEBF\uFECA\u061F\uFECB\u0621\u0622\u0623\u0624\u0625\u0626\u0627\u0628\u0629\u062A\u062B\u062C\u062D\u062E\u062F\u0630\u0631\u0632\u0633\u0634\u0635\u0636\u0637\uFEC7\u0639\u063A\uFECC\uFE82\uFE84\uFE8E\uFED3\u0640\u0641\u0642\u0643\u0644\u0645\u0646\u0647\u0648\u0649\u064A\u064B\u064C\u064D\u064E\u064F\u0650\u0651\u0652\uFED7\uFEDB\uFEDF\uF8FC\uFEF5\uFEF7\uFEF9\uFEFB\uFEE3\uFEE7\uFEEC\uFEE9\uFFFD"},ibm1046:"cp1046",csibm1046:"cp1046",cp1124:{type:"_sbcs",chars:"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\u0401\u0402\u0490\u0404\u0405\u0406\u0407\u0408\u0409\u040A\u040B\u040C\xAD\u040E\u040F\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041A\u041B\u041C\u041D\u041E\u041FLine truncated
\v\f\r\u1EE8\u1EF0\u1EF2\u1EF6\u1EF8\xDD\u1EF4\x1B !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~\x7F\xC0\u1EA2\xC3\xC1\u1EA0\u1EB6\u1EAC\xC8\u1EBA\u1EBC\xC9\u1EB8\u1EC6\xCC\u1EC8\u0128\xCD\u1ECA\xD2\u1ECE\xD5\xD3\u1ECC\u1ED8\u1EDC\u1EDE\u1EE0\u1EDA\u1EE2\xD9\u1EE6\u0168\xA0\u0102\xC2\xCA\xD4\u01A0\u01AF\u0110\u0103\xE2\xEA\xF4\u01A1\u01B0\u0111\u1EB0\u0300\u0309\u0303\u0301\u0323\xE0\u1EA3\xE3\xE1\u1EA1\u1EB2\u1EB1\u1EB3\u1EB5\u1EAF\u1EB4\u1EAE\u1EA6\u1EA8\u1EAA\u1EA4\u1EC0\u1EB7\u1EA7\u1EA9\u1EAB\u1EA5\u1EAD\xE8\u1EC2\u1EBB\u1EBD\xE9\u1EB9\u1EC1\u1EC3\u1EC5\u1EBF\u1EC7\xEC\u1EC9\u1EC4\u1EBE\u1ED2\u0129\xED\u1ECB\xF2\u1ED4\u1ECF\xF5\xF3\u1ECD\u1ED3\u1ED5\u1ED7\u1ED1\u1ED9\u1EDD\u1EDF\u1EE1\u1EDB\u1EE3\xF9\u1ED6\u1EE7\u0169\xFA\u1EE5\u1EEB\u1EED\u1EEF\u1EE9\u1EF1\u1EF3\u1EF7\u1EF9\xFD\u1EF5\u1ED0`},georgianacademy:{type:"_sbcs",chars:"\x80\x81\u201A\u0192\u201E\u2026\u2020\u2021\u02C6\u2030\u0160\u2039\u0152\x8D\x8E\x8F\x90\u2018\u2019\u201C\u201D\u2022\u2013\u2014\u02DC\u2122\u0161\u203A\u0153\x9D\x9E\u0178\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\u10D0\u10D1\u10D2\u10D3\u10D4\u10D5\u10D6\u10D7\u10D8\u10D9\u10DA\u10DB\u10DC\u10DD\u10DE\u10DF\u10E0\u10E1\u10E2\u10E3\u10E4\u10E5\u10E6\u10E7\u10E8\u10E9\u10EA\u10EB\u10EC\u10ED\u10EE\u10EF\u10F0\u10F1\u10F2\u10F3\u10F4\u10F5\u10F6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"},georgianps:{type:"_sbcs",chars:"\x80\x81\u201A\u0192\u201E\u2026\u2020\u2021\u02C6\u2030\u0160\u2039\u0152\x8D\x8E\x8F\x90\u2018\u2019\u201C\u201D\u2022\u2013\u2014\u02DC\u2122\u0161\u203A\u0153\x9D\x9E\u0178\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\u10D0\u10D1\u10D2\u10D3\u10D4\u10D5\u10D6\u10F1\u10D7\u10D8\u10D9\u10DA\u10DB\u10DC\u10F2\u10DD\u10DE\u10DF\u10E0\u10E1\u10E2\u10F3\u10E3\u10E4\u10E5\u10E6\u10E7\u10E8\u10E9\u10EA\u10EB\u10EC\u10ED\u10EE\u10F4\u10EF\u10F0\u10F5\xE6\xE7\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"},pt154:{type:"_sbcs",chars:"\u0496\u0492\u04EE\u0493\u201E\u2026\u04B6\u04AE\u04B2\u04AF\u04A0\u04E2\u04A2\u049A\u04BA\u04B8\u0497\u2018\u2019\u201C\u201D\u2022\u2013\u2014\u04B3\u04B7\u04A1\u04E3\u04A3\u049B\u04BB\u04B9\xA0\u040E\u045E\u0408\u04E8\u0498\u04B0\xA7\u0401\xA9\u04D8\xAB\xAC\u04EF\xAE\u049C\xB0\u04B1\u0406\u0456\u0499\u04E9\xB6\xB7\u0451\u2116\u04D9\xBB\u0458\u04AA\u04AB\u049D\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041A\u041B\u041C\u041D\u041E\u041F\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042A\u042B\u042C\u042D\u042E\u042F\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043A\u043B\u043C\u043D\u043E\u043F\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044A\u044B\u044C\u044D\u044E\u044F"},viscii:{type:"_sbcs",chars:`\0\u1EB2\u1EB4\u1EAA\x07\b
\v\f\r\u1EF6\u1EF8\x1B\u1EF4 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}~\x7F\u1EA0\u1EAE\u1EB0\u1EB6\u1EA4\u1EA6\u1EA8\u1EAC\u1EBC\u1EB8\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EE2\u1EDA\u1EDC\u1EDE\u1ECA\u1ECE\u1ECC\u1EC8\u1EE6\u0168\u1EE4\u1EF2\xD5\u1EAF\u1EB1\u1EB7\u1EA5\u1EA7\u1EA9\u1EAD\u1EBD\u1EB9\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1ED1\u1ED3\u1ED5\u1ED7\u1EE0\u01A0\u1ED9\u1EDD\u1EDF\u1ECB\u1EF0\u1EE8\u1EEA\u1EEC\u01A1\u1EDB\u01AF\xC0\xC1\xC2\xC3\u1EA2\u0102\u1EB3\u1EB5\xC8\xC9\xCA\u1EBA\xCC\xCD\u0128\u1EF3\u0110\u1EE9\xD2\xD3\xD4\u1EA1\u1EF7\u1EEB\u1EED\xD9\xDA\u1EF9\u1EF5\xDD\u1EE1\u01B0\xE0\xE1\xE2\xE3\u1EA3\u0103\u1EEF\u1EAB\xE8\xE9\xEA\u1EBB\xEC\xED\u0129\u1EC9\u0111\u1EF1\xF2\xF3\xF4\xF5\u1ECF\u1ECD\u1EE5\xF9\xFA\u0169\u1EE7\xFD\u1EE3\u1EEE`},iso646cn:{type:"_sbcs",chars:`\0\x07\b
\v\f\r\x1B !"#\xA5%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_\`abcdefghijklmnopqrstuvwxyz{|}\u203E\x7F\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD`},iso646jp:{type:"_sbcs",chars:`\0\x07\b
\v\f\r\x1B !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\xA5]^_\`abcdefghijklmnopqrstuvwxyz{|}\u203E\x7F\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD`},hproman8:{type:"_sbcs",chars:"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xC0\xC2\xC8\xCA\xCB\xCE\xCF\xB4\u02CB\u02C6\xA8\u02DC\xD9\xDB\u20A4\xAF\xDD\xFD\xB0\xC7\xE7\xD1\xF1\xA1\xBF\xA4\xA3\xA5\xA7\u0192\xA2\xE2\xEA\xF4\xFB\xE1\xE9\xF3\xFA\xE0\xE8\xF2\xF9\xE4\xEB\xF6\xFC\xC5\xEE\xD8\xC6\xE5\xED\xF8\xE6\xC4\xEC\xD6\xDC\xC9\xEF\xDF\xD4\xC1\xC3\xE3\xD0\xF0\xCD\xCC\xD3\xD2\xD5\xF5\u0160\u0161\xDA\u0178\xFF\xDE\xFE\xB7\xB5\xB6\xBE\u2014\xBC\xBD\xAA\xBA\xAB\u25A0\xBB\xB1\uFFFD"},macintosh:{type:"_sbcs",chars:"\xC4\xC5\xC7\xC9\xD1\xD6\xDC\xE1\xE0\xE2\xE4\xE3\xE5\xE7\xE9\xE8\xEA\xEB\xED\xEC\xEE\xEF\xF1\xF3\xF2\xF4\xF6\xF5\xFA\xF9\xFB\xFC\u2020\xB0\xA2\xA3\xA7\u2022\xB6\xDF\xAE\xA9\u2122\xB4\xA8\u2260\xC6\xD8\u221E\xB1\u2264\u2265\xA5\xB5\u2202\u2211\u220F\u03C0\u222B\xAA\xBA\u2126\xE6\xF8\xBF\xA1\xAC\u221A\u0192\u2248\u2206\xAB\xBB\u2026\xA0\xC0\xC3\xD5\u0152\u0153\u2013\u2014\u201C\u201D\u2018\u2019\xF7\u25CA\xFF\u0178\u2044\xA4\u2039\u203A\uFB01\uFB02\u2021\xB7\u201A\u201E\u2030\xC2\xCA\xC1\xCB\xC8\xCD\xCE\xCF\xCC\xD3\xD4\uFFFD\xD2\xDA\xDB\xD9\u0131\u02C6\u02DC\xAF\u02D8\u02D9\u02DA\xB8\u02DD\u02DB\u02C7"},ascii:{type:"_sbcs",chars:"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD"},tis620:{type:"_sbcs",chars:"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0E01\u0E02\u0E03\u0E04\u0E05\u0E06\u0E07\u0E08\u0E09\u0E0A\u0E0B\u0E0C\u0E0D\u0E0E\u0E0F\u0E10\u0E11\u0E12\u0E13\u0E14\u0E15\u0E16\u0E17\u0E18\u0E19\u0E1A\u0E1B\u0E1C\u0E1D\u0E1E\u0E1F\u0E20\u0E21\u0E22\u0E23\u0E24\u0E25\u0E26\u0E27\u0E28\u0E29\u0E2A\u0E2B\u0E2C\u0E2D\u0E2E\u0E2F\u0E30\u0E31\u0E32\u0E33\u0E34\u0E35\u0E36\u0E37\u0E38\u0E39\u0E3A\uFFFD\uFFFD\uFFFD\uFFFD\u0E3F\u0E40\u0E41\u0E42\u0E43\u0E44\u0E45\u0E46\u0E47\u0E48\u0E49\u0E4A\u0E4B\u0E4C\u0E4D\u0E4E\u0E4F\u0E50\u0E51\u0E52\u0E53\u0E54\u0E55\u0E56\u0E57\u0E58\u0E59\u0E5A\u0E5B\uFFFD\uFFFD\uFFFD\uFFFD"}}});var NQe=H(FQe=>{"use strict";var v$=Bd().Buffer;FQe._dbcs=vd;var zo=-1,QQe=-2,Lu=-10,dc=-1e3,L2=new Array(256),Xx=-1;for(FM=0;FM<256;FM++)L2[FM]=zo;var FM;function vd(t,e){if(this.encodingName=t.encodingName,!t)throw new Error("DBCS codec is called without the data.");if(!t.table)throw new Error("Encoding '"+this.encodingName+"' has no data.");var r=t.table();this.decodeTables=[],this.decodeTables[0]=L2.slice(0),this.decodeTableSeq=[];for(var s=0;s<r.length;s++)this._addDecodeChunk(r[s]);if(typeof t.gb18030=="function"){this.gb18030=t.gb18030();var a=this.decodeTables.length;this.decodeTables.push(L2.slice(0));var n=this.decodeTables.length;this.decodeTables.push(L2.slice(0));for(var l=this.decodeTables[0],s=129;s<=254;s++)for(var f=this.decodeTables[dc-l[s]],h=48;h<=57;h++){if(f[h]===zo)f[h]=dc-a;else if(f[h]>dc)throw new Error("gb18030 decode tables conflict at byte 2");for(var A=this.decodeTables[dc-f[h]],m=129;m<=254;m++){if(A[m]===zo)A[m]=dc-n;else{if(A[m]===dc-n)continue;if(A[m]>dc)throw new Error("gb18030 decode tables conflict at byte 3")}for(var w=this.decodeTables[dc-A[m]],v=48;v<=57;v++)w[v]===zo&&(w[v]=QQe)}}}this.defaultCharUnicode=e.defaultCharUnicode,this.encodeTable=[],this.encodeTableSeq=[];var D={};if(t.encodeSkipVals)for(var s=0;s<t.encodeSkipValsLine truncated
Wanted: ${this.expectedSize}
Found: ${this.size}`);s.code="EBADSIZE",s.found=this.size,s.expected=this.expectedSize,s.sri=this.sri,this.emit("error",s)}else if(this.sri&&!r){let s=new Error(`${this.sri} integrity checksum failed when using ${this.algorithm}: wanted ${this.digests} but got ${e}. (${this.size} bytes)`);s.code="EINTEGRITY",s.found=e,s.expected=this.digests,s.algorithm=this.algorithm,s.sri=this.sri,this.emit("error",s)}else this.#t=this.size,this.emit("size",this.size),this.#e=e,this.emit("integrity",e),r&&(this.#r=r,this.emit("verified",r))}},Pd=class{get isHash(){return!0}constructor(e,r){let s=r?.strict;this.source=e.trim(),this.digest="",this.algorithm="",this.options=[];let a=this.source.match(s?FRt:QRt);if(!a||s&&!V$.includes(a[1]))return;this.algorithm=a[1],this.digest=a[2];let n=a[3];n&&(this.options=n.slice(1).split("?"))}hexDigest(){return this.digest&&Buffer.from(this.digest,"base64").toString("hex")}toJSON(){return this.toString()}match(e,r){let s=Ul(e,r);if(!s)return!1;if(s.isIntegrity){let a=s.pickAlgorithm(r,[this.algorithm]);if(!a)return!1;let n=s[a].find(l=>l.digest===this.digest);return n||!1}return s.digest===this.digest?s:!1}toString(e){return e?.strict&&!(V$.includes(this.algorithm)&&this.digest.match(TRt)&&this.options.every(r=>r.match(NRt)))?"":`${this.algorithm}-${this.digest}${ak(this.options)}`}};function GFe(t,e,r,s){let a=t!=="",n=!1,l="",f=s.length-1;for(let A=0;A<f;A++){let m=Pd.prototype.toString.call(s[A],r);m&&(n=!0,l+=m,l+=e)}let h=Pd.prototype.toString.call(s[f],r);return h&&(n=!0,l+=h),a&&n?t+e+l:t+l}var jE=class{get isIntegrity(){return!0}toJSON(){return this.toString()}isEmpty(){return Object.keys(this).length===0}toString(e){let r=e?.sep||" ",s="";if(e?.strict){r=r.replace(/\S+/g," ");for(let a of V$)this[a]&&(s=GFe(s,r,e,this[a]))}else for(let a of Object.keys(this))s=GFe(s,r,e,this[a]);return s}concat(e,r){let s=typeof e=="string"?e:sk(e,r);return Ul(`${this.toString(r)} ${s}`,r)}hexDigest(){return Ul(this,{single:!0}).hexDigest()}merge(e,r){let s=Ul(e,r);for(let a in s)if(this[a]){if(!this[a].find(n=>s[a].find(l=>n.digest===l.digest)))throw new Error("hashes do not match, cannot update integrity")}else this[a]=s[a]}match(e,r){let s=Ul(e,r);if(!s)return!1;let a=s.pickAlgorithm(r,Object.keys(this));return!!a&&this[a]&&s[a]&&this[a].find(n=>s[a].find(l=>n.digest===l.digest))||!1}pickAlgorithm(e,r){let s=e?.pickAlgorithm||GRt,a=Object.keys(this).filter(n=>r?.length?r.includes(n):!0);return a.length?a.reduce((n,l)=>s(n,l)||n):null}};bA.exports.parse=Ul;function Ul(t,e){if(!t)return null;if(typeof t=="string")return q$(t,e);if(t.algorithm&&t.digest){let r=new jE;return r[t.algorithm]=[t],q$(sk(r,e),e)}else return q$(sk(t,e),e)}function q$(t,e){if(e?.single)return new Pd(t,e);let r=t.trim().split(/\s+/).reduce((s,a)=>{let n=new Pd(a,e);if(n.algorithm&&n.digest){let l=n.algorithm;s[l]||(s[l]=[]),s[l].push(n)}return s},new jE);return r.isEmpty()?null:r}bA.exports.stringify=sk;function sk(t,e){return t.algorithm&&t.digest?Pd.prototype.toString.call(t,e):typeof t=="string"?sk(Ul(t,e),e):jE.prototype.toString.call(t,e)}bA.exports.fromHex=ORt;function ORt(t,e,r){let s=ak(r?.options);return Ul(`${e}-${Buffer.from(t,"hex").toString("base64")}${s}`,r)}bA.exports.fromData=LRt;function LRt(t,e){let r=e?.algorithms||[...Y$],s=ak(e?.options);return r.reduce((a,n)=>{let l=ok.createHash(n).update(t).digest("base64"),f=new Pd(`${n}-${l}${s}`,e);if(f.algorithm&&f.digest){let h=f.algorithm;a[h]||(a[h]=[]),a[h].push(f)}return a},new jE)}bA.exports.fromStream=_Rt;function _Rt(t,e){let r=K$(e);return new Promise((s,a)=>{t.pipe(r),t.on("error",a),r.on("error",a);let n;r.on("integrity",l=>{n=l}),r.on("end",()=>s(n)),r.resume()})}bA.exports.checkData=MRt;function MRt(t,e,r){if(e=Ul(e,r),!e||!Object.keys(e).length){if(r?.error)throw Object.assign(new Error("No valid integrity hashes to check against"),{code:"EINTEGRITY"});return!1}let s=e.pickAlgorithm(r),a=ok.createHash(s).update(t).digest("base64"),n=Ul({algorithm:s,digest:a}),l=n.match(e,r);if(r=r||{},l||!r.error)return l;if(typeof r.size=="number"&&t.length!==r.size){let f=new Error(`data size mismatch when checking ${e}.
Wanted: ${r.size}
Found: ${t.length}`);throw f.code="EBADSIZE",f.found=t.length,f.expected=r.size,f.sri=e,f}else{let f=new Error(`Integrity checksum failed when using ${s}: Wanted ${e}, but got ${n}. (${t.length} bytes)`);throw f.code="EINTEGRITY",f.found=n,f.expected=e,f.algorithm=s,f.sri=e,f}}bA.exports.checkStream=URt;function URt(t,e,r){if(r=r||Object.create(null),r.integrity=e,e=Ul(e,r),!e||!Object.keys(e).length)return Promise.reject(Object.assign(new Error("No valid integrity hashes to check against"),{code:"EINTEGRITY"}));let s=K$(r);return new Promise((a,n)=>{t.pipe(s),t.on("error",n),s.on("error",n);let l;s.on("verified",f=>{l=f}),s.on("end",()=>a(l)),s.resume()})}bA.exports.integrityStream=K$;function K$(t=Object.create(null)){return new W$(t)}bA.exports.create=HRt;function HRt(t){let e=t?.algorithms||[...Y$],r=ak(t?.options),s=e.map(ok.createHash);return{update:function(a,n){return s.forEach(l=>l.update(a,n)),this},digest:function(){return e.reduce((n,l)=>{let f=s.shift().digest("base64"),h=new Pd(`${l}-${f}${r}`,t);if(h.algorithm&&h.digest){let A=h.algorithm;n[A]||(n[A]=[]),n[A].push(h)}return n},new jE)}}}var jRt=ok.getHashes(),qFe=["md5","whirlpool","sha1","sha224","sha256","sha384","sha512","sha3","sha3-256","sha3-384","sha3-512","sha3_256","sha3_384","sha3_512"].filter(t=>jRt.includes(t));function GRt(t,e){return qFe.indexOf(t.toLowerCase())>=qFe.indexOf(e.toLowerCase())?t:e}});var J$=H((rCr,zFe)=>{var VFe=IG(),WFe=jFe(),qRt=Zg(),YFe={shared:!1,ignoreCargoCult:!0},VRt={status:200,headers:{}},H2=t=>{let e={method:t.method,url:t.url,headers:{},compress:t.compress};return t.headers.forEach((r,s)=>{e.headers[s]=r}),e},KFe=t=>{let e={status:t.status,headers:{}};return t.headers.forEach((r,s)=>{e.headers[s]=r}),e},z$=class{constructor({entry:e,request:r,response:s,options:a}){this.entry=e,this.request=H2(r),this.response=KFe(s),this.options=a,this.policy=new VFe(this.request,this.response,YFe),this.entry&&(this.policy._responseTime=this.entry.metadata.time)}static storable(e,r){return!r.cachePath||r.cache==="no-store"||!["GET","HEAD"].includes(e.method)?!1:new VFe(H2(e),VRt,YFe).storable()}satisfies(e){let r=H2(e);if(this.request.headers.host!==r.headers.host||this.request.compress!==r.compress)return!1;let s=new WFe(this.request),a=new WFe(r);return JSON.stringify(s.mediaTypes())!==JSON.stringify(a.mediaTypes())||JSON.stringify(s.languages())!==JSON.stringify(a.languages())||JSON.stringify(s.encodings())!==JSON.stringify(a.encodings())?!1:this.options.integrity?qRt.parse(this.options.integrity).match(this.entry.integrity):!0}storable(){return this.policy.storable()}get mustRevalidate(){return!!this.policy._rescc["must-revalidate"]}needsRevalidation(e){let r=H2(e);return r.method="GET",!this.policy.satisfiesWithoutRevalidation(r)}responseHeaders(){return this.policy.responseHeaders()}revalidationHeaders(e){let r=H2(e);return this.policy.revalidationHeaders(r)}revalidated(e,r){let s=H2(e),a=KFe(r);return!this.policy.revalidatedPolicy(s,a).modified}};zFe.exports=z$});var ZFe=H((nCr,JFe)=>{var Z$=class extends Error{constructor(e){super(`request to ${e} failed: cache mode is 'only-if-cached' but no cached response is available.`),this.code="ENOTCACHED"}};JFe.exports={NotCachedError:Z$}});var KM=H((iCr,tNe)=>{var WRt=vM(),XFe=Symbol("_flush"),$Fe=Symbol("_flushed"),eNe=Symbol("_flushing"),X$=class extends WRt{constructor(e={}){if(typeof e=="function"&&(e={flush:e}),super(e),typeof e.flush!="function"&&typeof this.flush!="function")throw new TypeError("must provide flush function in options");this[XFe]=e.flush||this.flush}emit(e,...r){if(e!=="end"&&e!=="finish"||this[$Fe])return super.emit(e,...r);if(this[eNe])return;this[eNe]=!0;let s=n=>{this[$Fe]=!0,n?super.emit("error",n):super.emit("end")},a=this[XFe](s);a&&a.then&&a.then(()=>s(),n=>s(n))}};tNe.exports=X$});var ree=H((sCr,tee)=>{var{Minipass:rNe}=Ko(),j2=Symbol("_data"),G2=Symbol("_length"),$$=class extends rNe{constructor(e){super(e),this[j2]=[],this[G2]=0}write(e,r,s){typeof r=="function"&&(s=r,r="utf8"),r||(r="utf8");let a=Buffer.isBuffer(e)?e:Buffer.from(e,r);return this[j2].push(a),this[G2]+=a.length,s&&s(),!0}end(e,r,s){typeof e=="function"&&(s=e,e=null),typeof r=="function"&&(s=r,r="utf8"),e&&this.write(e,r);let a=Buffer.concat(this[j2],this[G2]);return super.write(a),super.end(s)}};tee.exports=$$;var eee=class extends rNe{constructor(e){super(e),this[j2]=[],this[G2]=0}write(e,r,s){typeof r=="function"&&(s=r,r="utf8"),r||(r="utf8");let a=Buffer.isBuffer(e)?e:Buffer.from(e,r);return this[j2].push(a),this[G2]+=a.length,super.write(e,r,s)}end(e,r,s){typeof e=="function"&&(s=e,e=null),typeof r=="function"&&(s=r,r="utf8"),e&&this.write(e,r);let a=Buffer.concat(this[j2],this[G2]);return this.emit("collect",a),super.end(s)}};tee.exports.PassThrough=eee});var q2=H((oCr,oNe)=>{var YRt=vM(),KRt=Ae("events"),zRt=t=>t&&t instanceof KRt&&(typeof t.pipe=="function"||typeof t.write=="function"&&typeof t.end=="function"),GE=Symbol("_head"),Hl=Symbol("_tail"),nee=Symbol( Line truncated
`+l.map(v=>{let D=JSON.stringify(v);return`${n4(D)} ${D}`}).join(`
`),h=async()=>{let v=EQt(PA.join(t,"tmp"),s.tmpPrefix);return await Iee(PA.dirname(v),{recursive:!0}),{target:v,moved:!1}},A=async v=>{if(!v.moved)return $Ne(v.target,{recursive:!0,force:!0})},m=async v=>{await gQt(v.target,f,{flag:"wx"}),await Iee(PA.dirname(a),{recursive:!0}),await BQt(v.target,a),v.moved=!0},w=await h();try{await m(w)}finally{await A(w)}return l.reverse().map(v=>i4(t,v,!0))}jl.exports.insert=eOe;async function eOe(t,e,r,s={}){let{metadata:a,size:n,time:l}=s,f=fk(t,e),h={key:e,integrity:r&&yQt.stringify(r),time:l||Date.now(),size:n,metadata:a};try{await Iee(PA.dirname(f),{recursive:!0});let A=JSON.stringify(h);await AQt(f,`
${n4(A)} ${A}`)}catch(A){if(A.code==="ENOENT")return;throw A}return i4(t,h)}jl.exports.find=SQt;async function SQt(t,e){let r=fk(t,e);try{return(await r4(r)).reduce((a,n)=>n&&n.key===e?i4(t,n):a,null)}catch(s){if(s.code==="ENOENT")return null;throw s}}jl.exports.delete=bQt;function bQt(t,e,r={}){if(!r.removeFully)return eOe(t,e,null,r);let s=fk(t,e);return $Ne(s,{recursive:!0,force:!0})}jl.exports.lsStream=tOe;function tOe(t){let e=wee(t),r=new mQt({objectMode:!0});return Promise.resolve().then(async()=>{let{default:s}=await Promise.resolve().then(()=>(t4(),e4)),a=await Eee(e);return await s(a,async n=>{let l=PA.join(e,n),f=await Eee(l);await s(f,async h=>{let A=PA.join(l,h),m=await Eee(A);await s(m,async w=>{let v=PA.join(A,w);try{let I=(await r4(v)).reduce((R,N)=>(R.set(N.key,N),R),new Map);for(let R of I.values()){let N=i4(t,R);N&&r.write(N)}}catch(D){if(D.code==="ENOENT")return;throw D}},{concurrency:yee})},{concurrency:yee})},{concurrency:yee}),r.end(),r}).catch(s=>r.emit("error",s)),r}jl.exports.ls=DQt;async function DQt(t){return(await tOe(t).collect()).reduce((r,s)=>(r[s.key]=s,r),{})}jl.exports.bucketEntries=r4;async function r4(t,e){let r=await pQt(t,"utf8");return PQt(r,e)}function PQt(t){let e=[];return t.split(`
`).forEach(r=>{if(!r)return;let s=r.split(" ");if(!s[1]||n4(s[1])!==s[0])return;let a;try{a=JSON.parse(s[1])}catch{}a&&e.push(a)}),e}jl.exports.bucketDir=wee;function wee(t){return PA.join(t,`index-v${CQt}`)}jl.exports.bucketPath=fk;function fk(t,e){let r=rOe(e);return PA.join.apply(PA,[wee(t)].concat(wQt(r)))}jl.exports.hashKey=rOe;function rOe(t){return nOe(t,"sha256")}jl.exports.hashEntry=n4;function n4(t){return nOe(t,"sha1")}function nOe(t,e){return hQt.createHash(e).update(t).digest("hex")}function i4(t,e,r){return!e.integrity&&!r?null:{key:e.key,integrity:e.integrity,path:e.integrity?IQt(t,e.integrity):void 0,size:e.size,time:e.time,metadata:e.metadata}}function Eee(t){return dQt(t).catch(e=>{if(e.code==="ENOENT"||e.code==="ENOTDIR")return[];throw e})}});var z2=H(o4=>{"use strict";Object.defineProperty(o4,"__esModule",{value:!0});o4.LRUCache=void 0;var xQt=typeof performance=="object"&&performance&&typeof performance.now=="function"?performance:Date,sOe=new Set,Cee=typeof process=="object"&&process?process:{},oOe=(t,e,r,s)=>{typeof Cee.emitWarning=="function"?Cee.emitWarning(t,e,r,s):console.error(`[${r}] ${e}: ${t}`)},s4=globalThis.AbortController,iOe=globalThis.AbortSignal;if(typeof s4>"u"){iOe=class{onabort;_onabort=[];reason;aborted=!1;addEventListener(s,a){this._onabort.push(a)}},s4=class{constructor(){e()}signal=new iOe;abort(s){if(!this.signal.aborted){this.signal.reason=s,this.signal.aborted=!0;for(let a of this.signal._onabort)a(s);this.signal.onabort?.(s)}}};let t=Cee.env?.LRU_CACHE_IGNORE_AC_WARNING!=="1",e=()=>{t&&(t=!1,oOe("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.","NO_ABORT_CONTROLLER","ENOTSUP",e))}}var kQt=t=>!sOe.has(t),PCr=Symbol("type"),Xg=t=>t&&t===Math.floor(t)&&t>0&&isFinite(t),aOe=t=>Xg(t)?t<=Math.pow(2,8)?Uint8Array:t<=Math.pow(2,16)?Uint16Array:t<=Math.pow(2,32)?Uint32Array:t<=Number.MAX_SAFE_INTEGER?K2:null:null,K2=class extends Array{constructor(e){super(e),this.fill(0)}},Bee=class t{heap;length;static#e=!1;static create(e){let r=aOe(e);if(!r)return[];t.#e=!0;let s=new t(e,r);return t.#e=!1,s}constructor(e,r){if(!t.#e)throw new TypeError("instantiate Stack using Stack.create(n)");this.heap=new r(e),this.length=0}push(e){this.heap[this.length++]=e}pop(){return this.heap[--this.length]}},vee=class t{#e;#t;#r;#n;#s;#i;#l;#u;get perf(){return this.#u}ttl;ttlResolution;ttlAutopurge;updateAgeOnGet;updateAgeOnHas;allowStale;noDisposeOnSet;noUpdateTTL;maxEntrySize;sizeCalculation;noDeleteOnFetchRejection;noDeleteOnStaleGet;allowStaleOnFetchAbort;allowStaleOnFetchRejection;ignoreFetchAbort;#c;#A;#p;#f;#a;#d;#w;#I;#g;#P;#m;#v;#S;#y;#E;#C;#b;#o;#F;static unsafeExposeInternals(e){return{starts:e.#S,ttls:e.#y,autopurgeTimers:e.#E,sizes:e.#v,keyMap:e.#p,keyList:e.#f,valList:e.#a,next:e.#d,prev:e.#w,get head(){return e.#I},get tail(){return e.#g},free:e.#P,isBackgroundFetch:r=>e.#h(r),backgroundFetch:(r,s,a,n)=>e.#j(r,s,a,n),moveToTail:r=>e.#O(r),indexes:r=>e.#k(r),rindexes:r=>e.#R(r),isStale:r=>e.#B(r)}}get max(){return this.#e}get maxSize(){return this.#t}get calculatedSize(){return this.#A}get size(){return this.#c}get fetchMethod(){return this.#i}get memoMethod(){return this.#l}get dispose(){return this.#r}get onInsert(){return this.#n}get disposeAfter(){return this.#s}constructor(e){let{max:r=0,ttl:s,ttlResolution:a=1,ttlAutopurge:n,updateAgeOnGet:l,updateAgeOnHas:f,allowStale:h,dispose:A,onInsert:m,disposeAfter:w,noDisposeOnSet:v,noUpdateTTL:D,maxSize:I=0,maxEntrySize:R=0,sizeCalculation:N,fetchMethod:U,memoMethod:V,noDeleteOnFetchRejection:ee,noDeleteOnStaleGet:te,allowStaleOnFetchRejection:ie,allowStaleOnFetchAbort:ae,ignoreFetchAbort:ge,perf:de}=e;if(de!==void 0&&typeof de?.now!="function")throw new TypeError("perf option must have a now() method if specified");if(this.#u=de??xQt,r!==0&&!Xg(r))throw new TypeError("max option must be a nonnegative integer");let xe=r?aOe(r):Array;if(!xe)throw new Error("invalid max value: "+r);if(this.#e=r,this.#t=I,this.maxEntrySize=R||this.#t,this.sizeCalculation=N,this.sizeCalculation){if(!this.#t&&!this.maxEntrySize)throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");if(typeof this.sizeCalculation!="function")throw new TypeError("sizeCalculation set to non-function")}if(V!==void 0&&typeof V!="function")throw new TypeError("memoMethod must be a function if defined");if(this.#l=V,U!==void 0&&typeof U!="function")throw new TypeError("fetchMethod must be a function if specified");if(this.#i=U,this.#b=!!U,this.#p=new Map,this.#f=new Array(r).fill(void 0),this.#a=new Array(r).fill(void 0),this.#d=new xe(r),this.#w=new xe(r),this.#I=0,this.#g=0 Line truncated
Wanted: ${t}
Found: ${e}`);return r.code="EINTEGRITY",r.expected=t,r.found=e,r}});var xOe=H((NCr,_ee)=>{"use strict";var SOe=Y2(),bOe=hk(),DOe=vOe(),hFt=KM(),{PassThrough:AFt}=ree(),pFt=q2(),POe=t=>({algorithms:["sha512"],...t});_ee.exports=dFt;async function dFt(t,e,r,s={}){let{memoize:a}=s;s=POe(s);let n=await DOe(t,r,s),l=await SOe.insert(t,e,n.integrity,{...s,size:n.size});return a&&bOe.put(t,l,r,s),n.integrity}_ee.exports.stream=gFt;function gFt(t,e,r={}){let{memoize:s}=r;r=POe(r);let a,n,l,f,h=new pFt;if(s){let m=new AFt().on("collect",w=>{f=w});h.push(m)}let A=DOe.stream(t,r).on("integrity",m=>{a=m}).on("size",m=>{n=m}).on("error",m=>{l=m});return h.push(A),h.push(new hFt({async flush(){if(!l){let m=await SOe.insert(t,e,a,{...r,size:n});s&&f&&bOe.put(t,m,f,r),h.emit("integrity",a),h.emit("size",n)}}})),h}});var ROe=H(KE=>{"use strict";Object.defineProperty(KE,"__esModule",{value:!0});KE.range=KE.balanced=void 0;var mFt=(t,e,r)=>{let s=t instanceof RegExp?kOe(t,r):t,a=e instanceof RegExp?kOe(e,r):e,n=s!==null&&a!=null&&(0,KE.range)(s,a,r);return n&&{start:n[0],end:n[1],pre:r.slice(0,n[0]),body:r.slice(n[0]+s.length,n[1]),post:r.slice(n[1]+a.length)}};KE.balanced=mFt;var kOe=(t,e)=>{let r=e.match(t);return r?r[0]:null},yFt=(t,e,r)=>{let s,a,n,l,f,h=r.indexOf(t),A=r.indexOf(e,h+1),m=h;if(h>=0&&A>0){if(t===e)return[h,A];for(s=[],n=r.length;m>=0&&!f;){if(m===h)s.push(m),h=r.indexOf(t,m+1);else if(s.length===1){let w=s.pop();w!==void 0&&(f=[w,A])}else a=s.pop(),a!==void 0&&a<n&&(n=a,l=A),A=r.indexOf(e,m+1);m=h<A&&h>=0?h:A}s.length&&l!==void 0&&(f=[n,l])}return f};KE.range=yFt});var _Oe=H(Hee=>{"use strict";Object.defineProperty(Hee,"__esModule",{value:!0});Hee.expand=RFt;var TOe=ROe(),QOe="\0SLASH"+Math.random()+"\0",FOe="\0OPEN"+Math.random()+"\0",Uee="\0CLOSE"+Math.random()+"\0",NOe="\0COMMA"+Math.random()+"\0",OOe="\0PERIOD"+Math.random()+"\0",EFt=new RegExp(QOe,"g"),IFt=new RegExp(FOe,"g"),wFt=new RegExp(Uee,"g"),CFt=new RegExp(NOe,"g"),BFt=new RegExp(OOe,"g"),vFt=/\\\\/g,SFt=/\\{/g,bFt=/\\}/g,DFt=/\\,/g,PFt=/\\./g;function Mee(t){return isNaN(t)?t.charCodeAt(0):parseInt(t,10)}function xFt(t){return t.replace(vFt,QOe).replace(SFt,FOe).replace(bFt,Uee).replace(DFt,NOe).replace(PFt,OOe)}function kFt(t){return t.replace(EFt,"\\").replace(IFt,"{").replace(wFt,"}").replace(CFt,",").replace(BFt,".")}function LOe(t){if(!t)return[""];let e=[],r=(0,TOe.balanced)("{","}",t);if(!r)return t.split(",");let{pre:s,body:a,post:n}=r,l=s.split(",");l[l.length-1]+="{"+a+"}";let f=LOe(n);return n.length&&(l[l.length-1]+=f.shift(),l.push.apply(l,f)),e.push.apply(e,l),e}function RFt(t){return t?(t.slice(0,2)==="{}"&&(t="\\{\\}"+t.slice(2)),Ek(xFt(t),!0).map(kFt)):[]}function TFt(t){return"{"+t+"}"}function QFt(t){return/^-?0\d/.test(t)}function FFt(t,e){return t<=e}function NFt(t,e){return t>=e}function Ek(t,e){let r=[],s=(0,TOe.balanced)("{","}",t);if(!s)return[t];let a=s.pre,n=s.post.length?Ek(s.post,!1):[""];if(/\$$/.test(s.pre))for(let l=0;l<n.length;l++){let f=a+"{"+s.body+"}"+n[l];r.push(f)}else{let l=/^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(s.body),f=/^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(s.body),h=l||f,A=s.body.indexOf(",")>=0;if(!h&&!A)return s.post.match(/,(?!,).*\}/)?(t=s.pre+"{"+s.body+Uee+s.post,Ek(t)):[t];let m;if(h)m=s.body.split(/\.\./);else if(m=LOe(s.body),m.length===1&&m[0]!==void 0&&(m=Ek(m[0],!1).map(TFt),m.length===1))return n.map(v=>s.pre+m[0]+v);let w;if(h&&m[0]!==void 0&&m[1]!==void 0){let v=Mee(m[0]),D=Mee(m[1]),I=Math.max(m[0].length,m[1].length),R=m.length===3&&m[2]!==void 0?Math.abs(Mee(m[2])):1,N=FFt;D<v&&(R*=-1,N=NFt);let V=m.some(QFt);w=[];for(let ee=v;N(ee,D);ee+=R){let te;if(f)te=String.fromCharCode(ee),te==="\\"&&(te="");else if(te=String(ee),V){let ie=I-te.length;if(ie>0){let ae=new Array(ie+1).join("0");ee<0?te="-"+ae+te.slice(1):te=ae+te}}w.push(te)}}else{w=[];for(let v=0;v<m.length;v++)w.push.apply(w,Ek(m[v],!1))}for(let v=0;v<w.length;v++)for(let D=0;D<n.length;D++){let I=a+w[v]+n[D];(!e||h||I)&&r.push(I)}}return r}});var MOe=H(m4=>{"use strict";Object.defineProperty(m4,"__esModule",{value:!0});m4.assertValidPattern=void 0;var OFt=1024*64,LFt=t=>{if(typeof t!="string")throw new TypeError("invalid pattern");if(t.length>OFt)throw new TypeError("pattern is too long")};m4.assertValidPattern=LFt});var HOe=H(y4=>{"use strict";Object.defineProperty(y4,"__esModule",{value:!0});y4.parseClass=void 0;var _Ft={"[:alnum:]":["\\p{L}\\p{Nl}\\p{Nd}",!0],"[:alpha:]":["\\p{L}\\p{Nl}",!0],"[:ascii:]":["\\x00-\\x7f",!1],"[:blank:]":["\\p{Zs}\\t",!0],"[:cntrl:]":["\\p{Cc}",!0],"[:digit:]":["\\p{Nd}",!0],"[:graph:]":["\\p{Z}\\p{C}",!0,!0],"[:lower:]":["\\p{Ll}",!0],"[:print:]":["\\p{C}",!0],"[:punct:]":["\\p{P}",!0],"[:space:]":["\\p{Z}\\t\\r\\n\\v\\f",!0],"[:upper:]":["\\p{Lu}",!0],"[:word:]":["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}",!0],"[:xdigit:]":["A-Fa-f0-9",!1]},Ik=t=>t.replace(/[[\]\\-]/g,"\\$&"),MFt=t=>t.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),UOe=t=>t.join(""),UFt=(t,e)=>{let r=e;if(t.charAt(r)!=="[")throw new Line truncated
globstar while`,e,v,r,D,I),this.matchOne(e.slice(v),r.slice(D),s))return this.debug("globstar found match!",v,h,I),!0;if(I==="."||I===".."||!a.dot&&I.charAt(0)==="."){this.debug("dot detected!",e,v,r,D);break}this.debug("globstar swallow a segment, and continue"),v++}return!!(s&&(this.debug(`
>>> no match, partial?`,e,v,r,D),v===h))}let R;if(typeof m=="string"?(R=w===m,this.debug("string match",m,w,R)):(R=m.test(w),this.debug("pattern match",m,w,R)),!R)return!1}if(l===h&&f===A)return!0;if(l===h)return s;if(f===A)return l===h-1&&e[l]==="";throw new Error("wtf?")}braceExpand(){return(0,_r.braceExpand)(this.pattern,this.options)}parse(e){(0,S4.assertValidPattern)(e);let r=this.options;if(e==="**")return _r.GLOBSTAR;if(e==="")return"";let s,a=null;(s=e.match(uNt))?a=r.dot?hNt:fNt:(s=e.match(eNt))?a=(r.nocase?r.dot?iNt:nNt:r.dot?rNt:tNt)(s[1]):(s=e.match(ANt))?a=(r.nocase?r.dot?dNt:pNt:r.dot?gNt:mNt)(s):(s=e.match(sNt))?a=r.dot?aNt:oNt:(s=e.match(cNt))&&(a=lNt);let n=YOe.AST.fromGlob(e,this.options).toMMPattern();return a&&typeof n=="object"&&Reflect.defineProperty(n,"test",{value:a}),n}makeRe(){if(this.regexp||this.regexp===!1)return this.regexp;let e=this.set;if(!e.length)return this.regexp=!1,this.regexp;let r=this.options,s=r.noglobstar?ENt:r.dot?INt:wNt,a=new Set(r.nocase?["i"]:[]),n=e.map(h=>{let A=h.map(w=>{if(w instanceof RegExp)for(let v of w.flags.split(""))a.add(v);return typeof w=="string"?DNt(w):w===_r.GLOBSTAR?_r.GLOBSTAR:w._src});A.forEach((w,v)=>{let D=A[v+1],I=A[v-1];w!==_r.GLOBSTAR||I===_r.GLOBSTAR||(I===void 0?D!==void 0&&D!==_r.GLOBSTAR?A[v+1]="(?:\\/|"+s+"\\/)?"+D:A[v]=s:D===void 0?A[v-1]=I+"(?:\\/|\\/"+s+")?":D!==_r.GLOBSTAR&&(A[v-1]=I+"(?:\\/|\\/"+s+"\\/)"+D,A[v+1]=_r.GLOBSTAR))});let m=A.filter(w=>w!==_r.GLOBSTAR);if(this.partial&&m.length>=1){let w=[];for(let v=1;v<=m.length;v++)w.push(m.slice(0,v).join("/"));return"(?:"+w.join("|")+")"}return m.join("/")}).join("|"),[l,f]=e.length>1?["(?:",")"]:["",""];n="^"+l+n+f+"$",this.partial&&(n="^(?:\\/|"+l+n.slice(1,-1)+f+")$"),this.negate&&(n="^(?!"+n+").+$");try{this.regexp=new RegExp(n,[...a].join(""))}catch{this.regexp=!1}return this.regexp}slashSplit(e){return this.preserveMultipleSlashes?e.split("/"):this.isWindows&&/^\/\/[^\/]+/.test(e)?["",...e.split(/\/+/)]:e.split(/\/+/)}match(e,r=this.partial){if(this.debug("match",e,this.pattern),this.comment)return!1;if(this.empty)return e==="";if(e==="/"&&r)return!0;let s=this.options;this.isWindows&&(e=e.split("\\").join("/"));let a=this.slashSplit(e);this.debug(this.pattern,"split",a);let n=this.set;this.debug(this.pattern,"set",n);let l=a[a.length-1];if(!l)for(let f=a.length-2;!l&&f>=0;f--)l=a[f];for(let f=0;f<n.length;f++){let h=n[f],A=a;if(s.matchBase&&h.length===1&&(A=[l]),this.matchOne(A,h,r))return s.flipNegate?!0:!this.negate}return s.flipNegate?!1:this.negate}static defaults(e){return _r.minimatch.defaults(e).Minimatch}};_r.Minimatch=zE;var PNt=qee();Object.defineProperty(_r,"AST",{enumerable:!0,get:function(){return PNt.AST}});var xNt=Vee();Object.defineProperty(_r,"escape",{enumerable:!0,get:function(){return xNt.escape}});var kNt=I4();Object.defineProperty(_r,"unescape",{enumerable:!0,get:function(){return kNt.unescape}});_r.minimatch.AST=YOe.AST;_r.minimatch.Minimatch=zE;_r.minimatch.escape=ZFt.escape;_r.minimatch.unescape=XFt.unescape});var uLe=H(yi=>{"use strict";var RNt=yi&&yi.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(e,r);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,a)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),TNt=yi&&yi.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),QNt=yi&&yi.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&RNt(e,t,r);return TNt(e,t),e};Object.defineProperty(yi,"__esModule",{value:!0});yi.PathScurry=yi.Path=yi.PathScurryDarwin=yi.PathScurryPosix=yi.PathScurryWin32=yi.PathScurryBase=yi.PathPosix=yi.PathWin32=yi.PathBase=yi.ChildrenCache=yi.ResolveCache=void 0;var Q4=z2(),k4=Ae("node:path"),FNt=Ae("node:url"),Ck=Ae("fs"),NNt=QNt(Ae("node:fs")),ONt=Ck.realpathSync.native,b4=Ae("node:fs/promises"),ZOe=Ko(),Bk={lstatSync:Ck.lstatSync,readdir:Ck.readdir,readdirSync:Ck.readdirSync,readlinkSync:Ck.readlinkSync,realpathSync:ONt,promises:{lstat:b4.lstat,readdir:b4.readdir,readlink:b4.readlink,realpath:b4.realpath}},rLe=t=>!t||t===Bk||t===NNt?Bk:{...Bk,...t,promises:{...Bk.promises,...t.promises||{}}},nLe=/^\\\\\?\\([a-z]:)\\?$/i,LNt=t=>t.replace(/\//g,"\\").replace(nLe,"$1\\"),_Nt=/[\\\/]/,Uu=0,iLe=1,sLe=2,kA=4,oLe=6,aLe=8,JE=10,cLe=12,Mu=15,wk=~Mu,Wee=16,XOe=32,vk=64,nh=128,D4=256,x4=512,$Oe=vk|nh|x4,MNt=1023,Yee=t=>t.isFile()?aLe:t.isDirectory()?kA:t.isSymbolicLink()?JE:t.isCharacterDevice()?sLe:t.isBlockDevice()?oLe:t.isSocket()?cLe:t.isFIFO()?iLe:Uu,eLe=new Q4.LRUCache({max:2**12}),Sk=t=>{let e=eLe.get(t);if(e)return e;let r=t.normalize("NFKD");return eLe.set(t,r),r},tLe=new Q4.LRUCache({max:2**12}),P4=t=>{let e=tLe.get(t);if(e)return e;let r=Sk(t.toLowerCase());return tLe.set(t,r),r},bk=class extends Q4.LRUCache{ Line truncated
`).join(`
`+n),t.push(a+"m+"+Z4.exports.humanize(this.diff)+"\x1B[0m")}else t[0]=NLt()+e+" "+t[0]}function NLt(){return xo.inspectOpts.hideDate?"":new Date().toISOString()+" "}function OLt(...t){return process.stderr.write(J4.formatWithOptions(xo.inspectOpts,...t)+`
`)}function LLt(t){t?process.env.DEBUG=t:delete process.env.DEBUG}function _Lt(){return process.env.DEBUG}function MLt(t){t.inspectOpts={};let e=Object.keys(xo.inspectOpts);for(let r=0;r<e.length;r++)t.inspectOpts[e[r]]=xo.inspectOpts[e[r]]}Z4.exports=Ste()(xo);var{formatters:i_e}=Z4.exports;i_e.o=function(t){return this.inspectOpts.colors=this.useColors,J4.inspect(t,this.inspectOpts).split(`
`).map(e=>e.trim()).join(" ")};i_e.O=function(t){return this.inspectOpts.colors=this.useColors,J4.inspect(t,this.inspectOpts)}});var $E=H((g1r,bte)=>{typeof process>"u"||process.type==="renderer"||process.browser===!0||process.__nwjs?bte.exports=n_e():bte.exports=s_e()});var c_e=H(sl=>{"use strict";var ULt=sl&&sl.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(e,r);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,a)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),HLt=sl&&sl.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),o_e=sl&&sl.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&ULt(e,t,r);return HLt(e,t),e};Object.defineProperty(sl,"__esModule",{value:!0});sl.req=sl.json=sl.toBuffer=void 0;var jLt=o_e(Ae("http")),GLt=o_e(Ae("https"));async function a_e(t){let e=0,r=[];for await(let s of t)e+=s.length,r.push(s);return Buffer.concat(r,e)}sl.toBuffer=a_e;async function qLt(t){let r=(await a_e(t)).toString("utf8");try{return JSON.parse(r)}catch(s){let a=s;throw a.message+=` (input: ${r})`,a}}sl.json=qLt;function VLt(t,e={}){let s=((typeof t=="string"?t:t.href).startsWith("https:")?GLt:jLt).request(t,e),a=new Promise((n,l)=>{s.once("response",n).once("error",l).end()});return s.then=a.then.bind(a),s}sl.req=VLt});var Ok=H(Gl=>{"use strict";var u_e=Gl&&Gl.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(e,r);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,a)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),WLt=Gl&&Gl.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),f_e=Gl&&Gl.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&u_e(e,t,r);return WLt(e,t),e},YLt=Gl&&Gl.__exportStar||function(t,e){for(var r in t)r!=="default"&&!Object.prototype.hasOwnProperty.call(e,r)&&u_e(e,t,r)};Object.defineProperty(Gl,"__esModule",{value:!0});Gl.Agent=void 0;var KLt=f_e(Ae("net")),l_e=f_e(Ae("http")),zLt=Ae("https");YLt(c_e(),Gl);var TA=Symbol("AgentBaseInternalState"),Dte=class extends l_e.Agent{constructor(e){super(e),this[TA]={}}isSecureEndpoint(e){if(e){if(typeof e.secureEndpoint=="boolean")return e.secureEndpoint;if(typeof e.protocol=="string")return e.protocol==="https:"}let{stack:r}=new Error;return typeof r!="string"?!1:r.split(`
`).some(s=>s.indexOf("(https.js:")!==-1||s.indexOf("node:https:")!==-1)}incrementSockets(e){if(this.maxSockets===1/0&&this.maxTotalSockets===1/0)return null;this.sockets[e]||(this.sockets[e]=[]);let r=new KLt.Socket({writable:!1});return this.sockets[e].push(r),this.totalSocketCount++,r}decrementSockets(e,r){if(!this.sockets[e]||r===null)return;let s=this.sockets[e],a=s.indexOf(r);a!==-1&&(s.splice(a,1),this.totalSocketCount--,s.length===0&&delete this.sockets[e])}getName(e){return this.isSecureEndpoint(e)?zLt.Agent.prototype.getName.call(this,e):super.getName(e)}createSocket(e,r,s){let a={...r,secureEndpoint:this.isSecureEndpoint(r)},n=this.getName(a),l=this.incrementSockets(n);Promise.resolve().then(()=>this.connect(e,a)).then(f=>{if(this.decrementSockets(n,l),f instanceof l_e.Agent)try{return f.addRequest(e,a)}catch(h){return s(h)}this[TA].currentSocket=f,super.createSocket(e,r,s)},f=>{this.decrementSockets(n,l),s(f)})}createConnection(){let e=this[TA].currentSocket;if(this[TA].currentSocket=void 0,!e)throw new Error("No socket was returned in the `connect()` function");return e}get defaultPort(){return this[TA].defaultPort??(this.protocol==="https:"?443:80)}set defaultPort(e){this[TA]&&(this[TA].defaultPort=e)}get protocol(){return this[TA].protocol??(this.isSecureEndpoint()?"https:":"http:")}set protocol(e){this[TA]&&(this[TA].protocol=e)}};Gl.Agent=Dte});var p_e=H(Hu=>{"use strict";var JLt=Hu&&Hu.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(e,r);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,a)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),ZLt=Hu&&Hu.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),A_e=Hu&&Hu.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&JLt(e,t,r);return ZLt(e,t),e},XLt=Hu&&Hu.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(Hu,"__esModule",{value:!0});Hu.HttpProxyAgent=void 0;var $Lt=A_e(Ae("net")),e_t=A_e(Ae("tls")),t_t=XLt($E()),r_t=Ae("events"),n_t=Ok(),h_e=Ae("url"),uB=(0,t_t.default)("http-proxy-agent"),X4=class extends n_t.Agent{constructor(e,r){super(r),this.proxy=typeof e=="string"?new h_e.URL(e):e,this.proxyHeaders=r?.headers??{},uB("Creating new HttpProxyAgent instance: %o",this.proxy.href);let s=(this.proxy.hostname||this.proxy.host).replace(/^\[|\]$/g,""),a=this.proxy.port?parseInt(this.proxy.port,10):this.proxy.protocol==="https:"?443:80;this.connectOpts={...r?i_t(r,"headers"):null,host:s,port:a}}addRequest(e,r){e._header=null,this.setRequestProps(e,r),super.addRequest(e,r)}setRequestProps(e,r){let{proxy:s}=this,a=r.secureEndpoint?"https:":"http:",n=e.getHeader("host")||"localhost",l=`${a}//${n}`,f=new h_e.URL(e.path,l);r.port!==80&&(f.port=String(r.port)),e.path=String(f);let h=typeof this.proxyHeaders=="function"?this.proxyHeaders():{...this.proxyHeaders};if(s.username||s.password){let A=`${decodeURIComponent(s.username)}:${decodeURIComponent(s.password)}`;h["Proxy-Authorization"]=`Basic ${Buffer.from(A).toString("base64")}`}h["Proxy-Connection"]||(h["Proxy-Connection"]=this.keepAlive?"Keep-Alive":"close");for(let A of Object.keys(h)){let m=h[A];m&&e.setHeader(A,m)}}async connect(e,r){e._header=null,e.path.includes("://")||this.setRequestProps(e,r);let s,a;uB("Regenerating stored HTTP header string for request"),e._implicitHeader(),e.outputData&&e.outputData.length>0&&(uB("Patching connection write() output buffer with updated header"),s=e.outputData[0].data,a=s.indexOf(`\r
\r
`)+4,e.outputData[0].data=e._header+s.substring(a),uB("Output buffer: %o",e.outputData[0].data));let n;return this.proxy.protocol==="https:"?(uB("Creating `tls.Socket`: %o",this.connectOpts),n=e_t.connect(this.connectOpts)):(uB("Creating `net.Socket`: %o",this.connectOpts),n=$Lt.connect(this.connectOpts)),await(0,r_t.once)(n,"connect"),n}};X4.protocols=["http","https"];Hu.HttpProxyAgent=X4;function i_t(t,...e){let r={},s;for(s in t)e.includes(s)||(r[s]=t[s]);return r}});var d_e=H(fB=>{"use strict";var s_t=fB&&fB.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(fB,"__esModule",{value:!0});fB.parseProxyResponse=void 0;var o_t=s_t($E()),$4=(0,o_t.default)("https-proxy-agent:parse-proxy-response");function a_t(t){return new Promise((e,r)=>{let s=0,a=[];function n(){let m=t.read();m?A(m):t.once("readable",n)}function l(){t.removeListener("end",f),t.removeListener("error",h),t.removeListener("readable",n)}function f(){l(),$4("onend"),r(new Error("Proxy connection ended before receiving CONNECT response"))}function h(m){l(),$4("onerror %o",m),r(m)}function A(m){a.push(m),s+=m.length;let w=Buffer.concat(a,s),v=w.indexOf(`\r
\r
`);if(v===-1){$4("have not received end of HTTP headers yet..."),n();return}let D=w.slice(0,v).toString("ascii").split(`\r
`),I=D.shift();if(!I)return t.destroy(),r(new Error("No header received from proxy CONNECT response"));let R=I.split(" "),N=+R[1],U=R.slice(2).join(" "),V={};for(let ee of D){if(!ee)continue;let te=ee.indexOf(":");if(te===-1)return t.destroy(),r(new Error(`Invalid header from proxy CONNECT response: "${ee}"`));let ie=ee.slice(0,te).toLowerCase(),ae=ee.slice(te+1).trimStart(),ge=V[ie];typeof ge=="string"?V[ie]=[ge,ae]:Array.isArray(ge)?ge.push(ae):V[ie]=ae}$4("got proxy server response: %o %o",I,V),l(),e({connect:{statusCode:N,statusText:U,headers:V},buffered:w})}t.on("error",h),t.on("end",f),n()})}fB.parseProxyResponse=a_t});var w_e=H(ju=>{"use strict";var c_t=ju&&ju.__createBinding||(Object.create?function(t,e,r,s){s===void 0&&(s=r);var a=Object.getOwnPropertyDescriptor(e,r);(!a||("get"in a?!e.__esModule:a.writable||a.configurable))&&(a={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,s,a)}:function(t,e,r,s){s===void 0&&(s=r),t[s]=e[r]}),l_t=ju&&ju.__setModuleDefault||(Object.create?function(t,e){Object.defineProperty(t,"default",{enumerable:!0,value:e})}:function(t,e){t.default=e}),E_e=ju&&ju.__importStar||function(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var r in t)r!=="default"&&Object.prototype.hasOwnProperty.call(t,r)&&c_t(e,t,r);return l_t(e,t),e},I_e=ju&&ju.__importDefault||function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(ju,"__esModule",{value:!0});ju.HttpsProxyAgent=void 0;var eU=E_e(Ae("net")),g_e=E_e(Ae("tls")),u_t=I_e(Ae("assert")),f_t=I_e($E()),h_t=Ok(),A_t=Ae("url"),p_t=d_e(),Lk=(0,f_t.default)("https-proxy-agent"),m_e=t=>t.servername===void 0&&t.host&&!eU.isIP(t.host)?{...t,servername:t.host}:t,tU=class extends h_t.Agent{constructor(e,r){super(r),this.options={path:void 0},this.proxy=typeof e=="string"?new A_t.URL(e):e,this.proxyHeaders=r?.headers??{},Lk("Creating new HttpsProxyAgent instance: %o",this.proxy.href);let s=(this.proxy.hostname||this.proxy.host).replace(/^\[|\]$/g,""),a=this.proxy.port?parseInt(this.proxy.port,10):this.proxy.protocol==="https:"?443:80;this.connectOpts={ALPNProtocols:["http/1.1"],...r?y_e(r,"headers"):null,host:s,port:a}}async connect(e,r){let{proxy:s}=this;if(!r.host)throw new TypeError('No "host" provided');let a;s.protocol==="https:"?(Lk("Creating `tls.Socket`: %o",this.connectOpts),a=g_e.connect(m_e(this.connectOpts))):(Lk("Creating `net.Socket`: %o",this.connectOpts),a=eU.connect(this.connectOpts));let n=typeof this.proxyHeaders=="function"?this.proxyHeaders():{...this.proxyHeaders},l=eU.isIPv6(r.host)?`[${r.host}]`:r.host,f=`CONNECT ${l}:${r.port} HTTP/1.1\r
`;if(s.username||s.password){let v=`${decodeURIComponent(s.username)}:${decodeURIComponent(s.password)}`;n["Proxy-Authorization"]=`Basic ${Buffer.from(v).toString("base64")}`}n.Host=`${l}:${r.port}`,n["Proxy-Connection"]||(n["Proxy-Connection"]=this.keepAlive?"Keep-Alive":"close");for(let v of Object.keys(n))f+=`${v}: ${n[v]}\r
`;let h=(0,p_t.parseProxyResponse)(a);a.write(`${f}\r
`);let{connect:A,buffered:m}=await h;if(e.emit("proxyConnect",A),this.emit("proxyConnect",A,e),A.statusCode===200)return e.once("socket",d_t),r.secureEndpoint?(Lk("Upgrading socket connection to TLS"),g_e.connect({...y_e(m_e(r),"host","path","port"),socket:a})):a;a.destroy();let w=new eU.Socket({writable:!1});return w.readable=!0,e.once("socket",v=>{Lk("Replaying proxy buffer for failed request"),(0,u_t.default)(v.listenerCount("data")>0),v.push(m),v.push(null)}),w}};tU.protocols=["http","https"];ju.HttpsProxyAgent=tU;function d_t(t){t.resume()}function y_e(t,...e){let r={},s;for(s in t)e.includes(s)||(r[s]=t[s]);return r}});var S_e=H(Nd=>{"use strict";Object.defineProperty(Nd,"__esModule",{value:!0});var C_e=Ae("buffer"),eI={INVALID_ENCODING:"Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.",INVALID_SMARTBUFFER_SIZE:"Invalid size provided. Size must be a valid integer greater than zero.",INVALID_SMARTBUFFER_BUFFER:"Invalid Buffer provided in SmartBufferOptions.",INVALID_SMARTBUFFER_OBJECT:"Invalid SmartBufferOptions object supplied to SmartBuffer constructor or factory methods.",INVALID_OFFSET:"An invalid offset value was provided.",INVALID_OFFSET_NON_NUMBER:"An invalid offset value was provided. A numeric value is required.",INVALID_LENGTH:"An invalid length value was provided.",INVALID_LENGTH_NON_NUMBER:"An invalid length value was provived. A numeric value is required.",INVALID_TARGET_OFFSET:"Target offset is beyond the bounds of the internal SmartBuffer data.",INVALID_TARGET_LENGTH:"Specified length value moves cursor beyong the bounds of the internal SmartBuffer data.",INVALID_READ_BEYOND_BOUNDS:"Attempted to read beyond the bounds of the managed data.",INVALID_WRITE_BEYOND_BOUNDS:"Attempted to write beyond the bounds of the managed data."};Nd.ERRORS=eI;function g_t(t){if(!C_e.Buffer.isEncoding(t))throw new Error(eI.INVALID_ENCODING)}Nd.checkEncoding=g_t;function B_e(t){return typeof t=="number"&&isFinite(t)&&I_t(t)}Nd.isFiniteInteger=B_e;function v_e(t,e){if(typeof t=="number"){if(!B_e(t)||t<0)throw new Error(e?eI.INVALID_OFFSET:eI.INVALID_LENGTH)}else throw new Error(e?eI.INVALID_OFFSET_NON_NUMBER:eI.INVALID_LENGTH_NON_NUMBER)}function m_t(t){v_e(t,!1)}Nd.checkLengthValue=m_t;function y_t(t){v_e(t,!0)}Nd.checkOffsetValue=y_t;function E_t(t,e){if(t<0||t>e.length)throw new Error(eI.INVALID_TARGET_OFFSET)}Nd.checkTargetOffset=E_t;function I_t(t){return typeof t=="number"&&isFinite(t)&&Math.floor(t)===t}function w_t(t){if(typeof BigInt>"u")throw new Error("Platform does not support JS BigInt type.");if(typeof C_e.Buffer.prototype[t]>"u")throw new Error(`Platform does not support Buffer.prototype.${t}.`)}Nd.bigIntAndBufferInt64Check=w_t});var D_e=H(xte=>{"use strict";Object.defineProperty(xte,"__esModule",{value:!0});var bn=S_e(),b_e=4096,C_t="utf8",Pte=class t{constructor(e){if(this.length=0,this._encoding=C_t,this._writeOffset=0,this._readOffset=0,t.isSmartBufferOptions(e))if(e.encoding&&(bn.checkEncoding(e.encoding),this._encoding=e.encoding),e.size)if(bn.isFiniteInteger(e.size)&&e.size>0)this._buff=Buffer.allocUnsafe(e.size);else throw new Error(bn.ERRORS.INVALID_SMARTBUFFER_SIZE);else if(e.buff)if(Buffer.isBuffer(e.buff))this._buff=e.buff,this.length=e.buff.length;else throw new Error(bn.ERRORS.INVALID_SMARTBUFFER_BUFFER);else this._buff=Buffer.allocUnsafe(b_e);else{if(typeof e<"u")throw new Error(bn.ERRORS.INVALID_SMARTBUFFER_OBJECT);this._buff=Buffer.allocUnsafe(b_e)}}static fromSize(e,r){return new this({size:e,encoding:r})}static fromBuffer(e,r){return new this({buff:e,encoding:r})}static fromOptions(e){return new this(e)}static isSmartBufferOptions(e){let r=e;return r&&(r.encoding!==void 0||r.size!==void 0||r.buff!==void 0)}readInt8(e){return this._readNumberValue(Buffer.prototype.readInt8,1,e)}readInt16BE(e){return this._readNumberValue(Buffer.prototype.readInt16BE,2,e)}readInt16LE(e){return this._readNumberValue(Buffer.prototype.readInt16LE,2,e)}readInt32BE(e){return this._readNumberValue(Buffer.prototype.readInt32BE,4,e)}readInt32LE(e){return this._readNumberValue(Buffer.prototype.readInt32LE,4,e)}readBigInt64BE(e){return bn.bigIntAndBufferInt64Check("readBigInt64BE"),this._readNumberValue(Buffer.prototype.readBigInt64BE,8,e)}readBigInt64LE(e){return bn.bigIntAndBufferInt64Check("readBigInt64LE"),this._readNumberValue(Buffer.prototype.readBigInt64LE,8,e)}writeInt8(e,r){return this._writeNumberValue(Buffer.prototype.writeInt8,1,e,r),this}insertInt8(e,r){return this._insertNumberValue(Buffer.prototype.writeInt8,1,e,r)}writeInt16BE(e,r){return this._writeNumberValue(Buffer.prototype.writeInt16BE,2,e,r)}insertInt16BE(e,r){return this._insertNumberValue(Buffer.prototype.writeInt16BE,2,e,r)}writeInt16LE(e,r){return this._writeNumberValue(Buffer.prototype.writeInt16LE,2,e,r)}insertInt16LE(e,r){return this._insertNumberValue(Buffer.prototype.writeInt16LE,2,e,r)}writeInt32BE(e,r){return this._writeNumberValue(Buffer.prototype.writeInt32BE,4,e,r)}insert Line truncated
`,lHt=/\u2014 (\S+) (\S+)\n/g;function uHt(t,e){let r=t.inclusionProof,s=$ne.fromString(r.checkpoint.envelope),a=C8.fromString(s.note);if(!fHt(s,e))throw new lR.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:"invalid checkpoint signature"});return a}function fHt(t,e){let r=Buffer.from(t.note,"utf-8");return t.signatures.some(s=>{let a=e.find(n=>CUe.crypto.bufferEqual(n.logID.subarray(0,4),s.keyHint)&&n.baseURL.match(s.name));return a?CUe.crypto.verify(r,a.publicKey,s.signature):!1})}var $ne=class t{note;signatures;constructor(e,r){this.note=e,this.signatures=r}static fromString(e){if(!e.includes(Xne))throw new lR.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:"missing checkpoint separator"});let r=e.indexOf(Xne),s=e.slice(0,r+1),n=e.slice(r+Xne.length).matchAll(lHt),l=Array.from(n,f=>{let[,h,A]=f,m=Buffer.from(A,"base64");if(m.length<5)throw new lR.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:"malformed checkpoint signature"});return{name:h,keyHint:m.subarray(0,4),signature:m.subarray(4)}});if(l.length===0)throw new lR.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:"no signatures found in checkpoint"});return new t(s,l)}},C8=class t{origin;logSize;logHash;rest;constructor(e,r,s,a){this.origin=e,this.logSize=r,this.logHash=s,this.rest=a}static fromString(e){let r=e.trimEnd().split(`
`);if(r.length<3)throw new lR.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:"too few lines in checkpoint header"});let s=r[0],a=BigInt(r[1]),n=Buffer.from(r[2],"base64"),l=r.slice(3);return new t(s,a,n,l)}};uR.LogCheckpoint=C8});var vUe=H(nie=>{"use strict";Object.defineProperty(nie,"__esModule",{value:!0});nie.verifyMerkleInclusion=pHt;var rie=tl(),eie=Na(),hHt=Buffer.from([0]),AHt=Buffer.from([1]);function pHt(t,e){let r=t.inclusionProof,s=BigInt(r.logIndex),a=BigInt(e.logSize);if(s<0n||s>=a)throw new eie.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:`invalid index: ${s}`});let{inner:n,border:l}=dHt(s,a);if(r.hashes.length!==n+l)throw new eie.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:"invalid hash count"});let f=r.hashes.slice(0,n),h=r.hashes.slice(n),A=wHt(t.canonicalizedBody),m=mHt(gHt(A,f,s),h);if(!rie.crypto.bufferEqual(m,e.logHash))throw new eie.VerificationError({code:"TLOG_INCLUSION_PROOF_ERROR",message:"calculated root hash does not match inclusion proof"})}function dHt(t,e){let r=yHt(t,e),s=EHt(t>>BigInt(r));return{inner:r,border:s}}function gHt(t,e,r){return e.reduce((s,a,n)=>r>>BigInt(n)&BigInt(1)?tie(a,s):tie(s,a),t)}function mHt(t,e){return e.reduce((r,s)=>tie(s,r),t)}function yHt(t,e){return IHt(t^e-BigInt(1))}function EHt(t){return t.toString(2).split("1").length-1}function IHt(t){return t===0n?0:t.toString(2).length}function tie(t,e){return rie.crypto.digest("sha256",AHt,t,e)}function wHt(t){return rie.crypto.digest("sha256",hHt,t)}});var bUe=H(iie=>{"use strict";Object.defineProperty(iie,"__esModule",{value:!0});iie.verifyTLogSET=vHt;var SUe=tl(),CHt=Na(),BHt=MB();function vHt(t,e){if(!(0,BHt.filterTLogAuthorities)(e,{logID:t.logId.keyId,targetDate:new Date(Number(t.integratedTime)*1e3)}).some(a=>{let n=SHt(t),l=Buffer.from(SUe.json.canonicalize(n),"utf8"),f=t.inclusionPromise.signedEntryTimestamp;return SUe.crypto.verify(l,a.publicKey,f)}))throw new CHt.VerificationError({code:"TLOG_INCLUSION_PROMISE_ERROR",message:"inclusion promise could not be verified"})}function SHt(t){let{integratedTime:e,logIndex:r,logId:s,canonicalizedBody:a}=t;return{body:a.toString("base64"),integratedTime:Number(e),logIndex:Number(r),logID:s.keyId.toString("hex")}}});var PUe=H(B8=>{"use strict";Object.defineProperty(B8,"__esModule",{value:!0});B8.verifyTLogBody=kHt;B8.verifyTLogInclusion=RHt;var DUe=Ere(),aie=Na(),sie=EUe(),oie=IUe(),bHt=wUe(),DHt=BUe(),PHt=vUe(),xHt=bUe();function kHt(t,e){let{kind:r,version:s}=t.kindVersion,a=JSON.parse(t.canonicalizedBody.toString("utf8"));if(r!==a.kind||s!==a.apiVersion)throw new aie.VerificationError({code:"TLOG_BODY_ERROR",message:`kind/version mismatch - expected: ${r}/${s}, received: ${a.kind}/${a.apiVersion}`});switch(r){case"dsse":if(s==sie.DSSE_API_VERSION_V1)return(0,sie.verifyDSSETLogBody)(a,e);{let n=DUe.Entry.fromJSON(a);return(0,sie.verifyDSSETLogBodyV2)(n,e)}case"intoto":return(0,bHt.verifyIntotoTLogBody)(a,e);case"hashedrekord":if(s==oie.HASHEDREKORD_API_VERSION_V1)return(0,oie.verifyHashedRekordTLogBody)(a,e);{let n=DUe.Entry.fromJSON(a);return(0,oie.verifyHashedRekordTLogBodyV2)(n,e)}default:throw new aie.VerificationError({code:"TLOG_BODY_ERROR",message:`unsupported kind: ${r}`})}}function RHt(t,e){let r=!1;if(THt(t)&&((0,xHt.verifyTLogSET)(t,e),r=!0),QHt(t)){let s=(0,DHt.verifyCheckpoint)(t,e);(0,PHt.verifyMerkleInclusion)(t,s),r=!0}if(!r)throw new aie.VerificationError({code:"TLOG_MISSING_INCLUSION_ERROR",message:"inclusion could not be verified"})}function THt(t){return t.inclusionPromise!==void 0}function QHt(t){return t.inclusionProof!==void 0}});var QUe=H(v8=>{"use strict";Object.defineProperty(v8,"__esModule",{value:!0});v8.Verifier=void 0;var FHt=Ae("util"),UB=Na(),xUe=pUe(),cie=dUe(),kUe=yUe(),RUe=PUe(),lie=class{trustMaterial;options;constructor(e,r={}){this.trustMaterial=e,this.options={ctlogThreshold:r.ctlogThreshold??1,tlogThreshold:r.tlogThreshold??1,timestampThreshold:r.timestampThreshold??r.tsaThreshold??1,tsaThreshold:0}}verify(e,r){let s=this.verifyTimestamps(e),a=this.verifySigningKey(e,s);return this.verifyTLogs(e),this.verifySignature(e,a),r&&this.verifyPolicy(r,a.identity||{}),a}verifyTimestamps(e){let r=[];for(let s of e.timestamps)switch(s.$case){case"timestamp-authority":r.push((0,kUe.getTSATimestamp)(s.timestamp,e.signature.signature,this.trustMaterial.timestampAuthorities));break;case"transparency-log":{let a=(0,kUe.getTLogTimestamp)(s.tlogEntry);a&&r.push(a);break}}if(TUe(r))throw new UB.VerificationError({code:"TIMESTAMP_ERROR",message:"duplicate timestamp"});if(r.length<this.options.timestampThreshold)throw new UB.VerificationError({code:"TIMESTAMP_ERROR",message:`expected ${this.options.timestampThreshold} timestamps, got ${r.length}`});return r.map(s=>s.timestamp)}verifySigningKey({key:e},r){switch(e.$case){case"public-key":return(0,xUe.verifyPublicKey)(e.hint,r,this.trustMaterial);case"certificate":{let s=(0,xUe.verifyCertificate)(e.certificate,r,this.trustMaterial);if(TUe(s Line truncated
Try running the command again with the package name prefixed: ${pe.pretty(r,"yarn add",pe.Type.CODE)} ${pe.pretty(r,G.makeDescriptor(G.makeIdent(null,"my-package"),`${te[0]}...`),pe.Type.DESCRIPTOR)}`);if(!ee)throw new ht(`The ${pe.pretty(r,V,pe.Type.CODE)} string didn't match the required format (package-name@range). Did you perhaps forget to explicitly reference the package name?`);let ie=omt(a,ee,{dev:this.dev,peer:this.peer,preferDev:this.preferDev,optional:this.optional});return await Promise.all(ie.map(async ge=>{let de=await ED(ee,{project:s,workspace:a,cache:n,fixed:l,target:ge,modifier:A,strategies:m,maxResults:w});return{request:ee,suggestedDescriptors:de,target:ge}}))})).then(V=>V.flat()),I=await tA.start({configuration:r,stdout:this.context.stdout,suggestInstall:!1},async V=>{for(let{request:ee,suggestedDescriptors:{suggestions:te,rejections:ie}}of D)if(te.filter(ge=>ge.descriptor!==null).length===0){let[ge]=ie;if(typeof ge>"u")throw new Error("Assertion failed: Expected an error to have been set");s.configuration.get("enableNetwork")?V.reportError(27,`${G.prettyDescriptor(r,ee)} can't be resolved to a satisfying range`):V.reportError(27,`${G.prettyDescriptor(r,ee)} can't be resolved to a satisfying range (note: network resolution has been disabled)`),V.reportSeparator(),V.reportExceptionOnce(ge)}});if(I.hasErrors())return I.exitCode();let R=!1,N=[],U=[];for(let{suggestedDescriptors:{suggestions:V},target:ee}of D){let te,ie=V.filter(xe=>xe.descriptor!==null),ae=ie[0].descriptor,ge=ie.every(xe=>G.areDescriptorsEqual(xe.descriptor,ae));ie.length===1||ge?te=ae:(R=!0,{answer:te}=await(0,f2e.prompt)({type:"select",name:"answer",message:"Which range do you want to use?",choices:V.map(({descriptor:xe,name:we,reason:d})=>xe?{name:we,hint:d,descriptor:xe}:{name:we,hint:d,disabled:!0}),onCancel:()=>process.exit(130),result(xe){return this.find(xe,"descriptor")},stdin:this.context.stdin,stdout:this.context.stdout}));let de=a.manifest[ee].get(te.identHash);(typeof de>"u"||de.descriptorHash!==te.descriptorHash)&&(a.manifest[ee].set(te.identHash,te),this.optional&&(ee==="dependencies"?a.manifest.ensureDependencyMeta({...te,range:"unknown"}).optional=!0:ee==="peerDependencies"&&(a.manifest.ensurePeerDependencyMeta({...te,range:"unknown"}).optional=!0)),typeof de>"u"?N.push([a,ee,te,m]):U.push([a,ee,de,te]))}return await r.triggerMultipleHooks(V=>V.afterWorkspaceDependencyAddition,N),await r.triggerMultipleHooks(V=>V.afterWorkspaceDependencyReplacement,U),R&&this.context.stdout.write(`
`),await s.installWithNewReport({json:this.json,stdout:this.context.stdout,quiet:this.context.quiet},{cache:n,mode:this.mode})}};function omt(t,e,{dev:r,peer:s,preferDev:a,optional:n}){let l=t.manifest.dependencies.has(e.identHash),f=t.manifest.devDependencies.has(e.identHash),h=t.manifest.peerDependencies.has(e.identHash);if((r||s)&&l)throw new ht(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a regular dependency - remove the -D,-P flags or remove it from your dependencies first`);if(!r&&!s&&h)throw new ht(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a peer dependency - use either of -D or -P, or remove it from your peer dependencies first`);if(n&&f)throw new ht(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a dev dependency - remove the -O flag or remove it from your dev dependencies first`);if(n&&!s&&h)throw new ht(`Package "${G.prettyIdent(t.project.configuration,e)}" is already listed as a peer dependency - remove the -O flag or add the -P flag or remove it from your peer dependencies first`);if((r||a)&&n)throw new ht(`Package "${G.prettyIdent(t.project.configuration,e)}" cannot simultaneously be a dev dependency and an optional dependency`);let A=[];return s&&A.push("peerDependencies"),(r||a)&&A.push("devDependencies"),n&&A.push("dependencies"),A.length>0?A:f?["devDependencies"]:h?["peerDependencies"]:["dependencies"]}We();We();sr();var MC=class extends mt{constructor(){super(...arguments);this.verbose=ye.Boolean("-v,--verbose",!1,{description:"Print both the binary name and the locator of the package that provides the binary"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.name=ye.String({required:!1})}static{this.paths=[["bin"]]}static{this.usage=At.Usage({description:"get the path to a binary script",details:`
When used without arguments, this command will print the list of all the binaries available in the current workspace. Adding the \`-v,--verbose\` flag will cause the output to contain both the binary name and the locator of the package that provides the binary.
When an argument is specified, this command will just print the path to the binary on the standard output and exit. Note that the reported path may be stored within a zip archive.
`,examples:[["List all the available binaries","$0 bin"],["Print the path to a specific binary","$0 bin eslint"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,locator:a}=await Yt.find(r,this.context.cwd);if(await s.restoreInstallState(),this.name){let f=(await qn.getPackageAccessibleBinaries(a,{project:s})).get(this.name);if(!f)throw new ht(`Couldn't find a binary named "${this.name}" for package "${G.prettyLocator(r,a)}"`);let[,h]=f;return this.context.stdout.write(`${h}
`),0}return(await Wt.start({configuration:r,json:this.json,stdout:this.context.stdout},async l=>{let f=await qn.getPackageAccessibleBinaries(a,{project:s}),A=Array.from(f.keys()).reduce((m,w)=>Math.max(m,w.length),0);for(let[m,[w,v]]of f)l.reportJson({name:m,source:G.stringifyIdent(w),path:v});if(this.verbose)for(let[m,[w]]of f)l.reportInfo(null,`${m.padEnd(A," ")} ${G.prettyLocator(r,w)}`);else for(let m of f.keys())l.reportInfo(null,m)})).exitCode()}};We();Mt();sr();var UC=class extends mt{constructor(){super(...arguments);this.mirror=ye.Boolean("--mirror",!1,{description:"Remove the global cache files instead of the local cache files"});this.all=ye.Boolean("--all",!1,{description:"Remove both the global cache files and the local cache files of the current project"})}static{this.paths=[["cache","clean"],["cache","clear"]]}static{this.usage=At.Usage({description:"remove the shared cache files",details:`
This command will remove all the files from the cache.
`,examples:[["Remove all the local archives","$0 cache clean"],["Remove all the archives stored in the ~/.yarn directory","$0 cache clean --mirror"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins);if(!r.get("enableCacheClean"))throw new ht("Cache cleaning is currently disabled. To enable it, set `enableCacheClean: true` in your configuration file. Note: Cache cleaning is typically not required and should be avoided when using Zero-Installs.");let s=await gn.find(r);return(await Wt.start({configuration:r,stdout:this.context.stdout},async()=>{let n=(this.all||this.mirror)&&s.mirrorCwd!==null,l=!this.mirror;n&&(await fe.removePromise(s.mirrorCwd),await r.triggerHook(f=>f.cleanGlobalArtifacts,r)),l&&await fe.removePromise(s.cwd)})).exitCode()}};We();sr();xl();var OW=Ae("util"),HC=class extends mt{constructor(){super(...arguments);this.why=ye.Boolean("--why",!1,{description:"Print the explanation for why a setting has its value"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.unsafe=ye.Boolean("--no-redacted",!1,{description:"Don't redact secrets (such as tokens) from the output"});this.name=ye.String()}static{this.paths=[["config","get"]]}static{this.usage=At.Usage({description:"read a configuration settings",details:`
This command will print a configuration setting.
Secrets (such as tokens) will be redacted from the output by default. If this behavior isn't desired, set the \`--no-redacted\` to get the untransformed value.
`,examples:[["Print a simple configuration setting","yarn config get yarnPath"],["Print a complex configuration setting","yarn config get packageExtensions"],["Print a nested field from the configuration",`yarn config get 'npmScopes["my-company"].npmRegistryServer'`],["Print a token from the configuration","yarn config get npmAuthToken --no-redacted"],["Print a configuration setting as JSON","yarn config get packageExtensions --json"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=this.name.replace(/[.[].*$/,""),a=this.name.replace(/^[^.[]*/,"");if(typeof r.settings.get(s)>"u")throw new ht(`Couldn't find a configuration settings named "${s}"`);let l=r.getSpecial(s,{hideSecrets:!this.unsafe,getNativePaths:!0}),f=Ye.convertMapsToIndexableObjects(l),h=a?rc(f,a):f,A=await Wt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async m=>{m.reportJson(h)});if(!this.json){if(typeof h=="string")return this.context.stdout.write(`${h}
`),A.exitCode();OW.inspect.styles.name="cyan",this.context.stdout.write(`${(0,OW.inspect)(h,{depth:1/0,colors:r.get("enableColors"),compact:!1})}
`)}return A.exitCode()}};We();sr();xl();var LW=Ae("util"),jC=class extends mt{constructor(){super(...arguments);this.json=ye.Boolean("--json",!1,{description:"Set complex configuration settings to JSON values"});this.home=ye.Boolean("-H,--home",!1,{description:"Update the home configuration instead of the project configuration"});this.name=ye.String();this.value=ye.String()}static{this.paths=[["config","set"]]}static{this.usage=At.Usage({description:"change a configuration settings",details:`
This command will set a configuration setting.
When used without the \`--json\` flag, it can only set a simple configuration setting (a string, a number, or a boolean).
When used with the \`--json\` flag, it can set both simple and complex configuration settings, including Arrays and Objects.
`,examples:[["Set a simple configuration setting (a string, a number, or a boolean)","yarn config set initScope myScope"],["Set a simple configuration setting (a string, a number, or a boolean) using the `--json` flag",'yarn config set initScope --json \\"myScope\\"'],["Set a complex configuration setting (an Array) using the `--json` flag",`yarn config set unsafeHttpWhitelist --json '["*.example.com", "example.com"]'`],["Set a complex configuration setting (an Object) using the `--json` flag",`yarn config set packageExtensions --json '{ "@babel/parser@*": { "dependencies": { "@babel/types": "*" } } }'`],["Set a nested configuration setting",'yarn config set npmScopes.company.npmRegistryServer "https://npm.example.com"'],["Set a nested configuration setting using indexed access for non-simple keys",`yarn config set 'npmRegistries["//npm.example.com"].npmAuthToken' "ffffffff-ffff-ffff-ffff-ffffffffffff"`]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=()=>{if(!r.projectCwd)throw new ht("This command must be run from within a project folder");return r.projectCwd},a=this.name.replace(/[.[].*$/,""),n=this.name.replace(/^[^.[]*\.?/,"");if(typeof r.settings.get(a)>"u")throw new ht(`Couldn't find a configuration settings named "${a}"`);if(a==="enableStrictSettings")throw new ht("This setting only affects the file it's in, and thus cannot be set from the CLI");let f=this.json?JSON.parse(this.value):this.value;await(this.home?I=>$e.updateHomeConfiguration(I):I=>$e.updateConfiguration(s(),I))(I=>{if(n){let R=F0(I);return Ey(R,this.name,f),R}else return{...I,[a]:f}});let m=(await $e.find(this.context.cwd,this.context.plugins)).getSpecial(a,{hideSecrets:!0,getNativePaths:!0}),w=Ye.convertMapsToIndexableObjects(m),v=n?rc(w,n):w;return(await Wt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async I=>{LW.inspect.styles.name="cyan",I.reportInfo(0,`Successfully set ${this.name} to ${(0,LW.inspect)(v,{depth:1/0,colors:r.get("enableColors"),compact:!1})}`)})).exitCode()}};We();sr();xl();var GC=class extends mt{constructor(){super(...arguments);this.home=ye.Boolean("-H,--home",!1,{description:"Update the home configuration instead of the project configuration"});this.name=ye.String()}static{this.paths=[["config","unset"]]}static{this.usage=At.Usage({description:"unset a configuration setting",details:`
This command will unset a configuration setting.
`,examples:[["Unset a simple configuration setting","yarn config unset initScope"],["Unset a complex configuration setting","yarn config unset packageExtensions"],["Unset a nested configuration setting","yarn config unset npmScopes.company.npmRegistryServer"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=()=>{if(!r.projectCwd)throw new ht("This command must be run from within a project folder");return r.projectCwd},a=this.name.replace(/[.[].*$/,""),n=this.name.replace(/^[^.[]*\.?/,"");if(typeof r.settings.get(a)>"u")throw new ht(`Couldn't find a configuration settings named "${a}"`);let f=this.home?A=>$e.updateHomeConfiguration(A):A=>$e.updateConfiguration(s(),A);return(await Wt.start({configuration:r,includeFooter:!1,stdout:this.context.stdout},async A=>{let m=!1;await f(w=>{if(!_S(w,this.name))return A.reportWarning(0,`Configuration doesn't contain setting ${this.name}; there is nothing to unset`),m=!0,w;let v=n?F0(w):{...w};return N0(v,this.name),v}),m||A.reportInfo(0,`Successfully unset ${this.name}`)})).exitCode()}};We();Mt();sr();var WO=Ae("util"),qC=class extends mt{constructor(){super(...arguments);this.noDefaults=ye.Boolean("--no-defaults",!1,{description:"Omit the default values from the display"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.verbose=ye.Boolean("-v,--verbose",{hidden:!0});this.why=ye.Boolean("--why",{hidden:!0});this.names=ye.Rest()}static{this.paths=[["config"]]}static{this.usage=At.Usage({description:"display the current configuration",details:`
This command prints the current active configuration settings.
`,examples:[["Print the active configuration settings","$0 config"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins,{strict:!1}),s=await dC({configuration:r,stdout:this.context.stdout,forceError:this.json},[{option:this.verbose,message:"The --verbose option is deprecated, the settings' descriptions are now always displayed"},{option:this.why,message:"The --why option is deprecated, the settings' sources are now always displayed"}]);if(s!==null)return s;let a=this.names.length>0?[...new Set(this.names)].sort():[...r.settings.keys()].sort(),n,l=await Wt.start({configuration:r,json:this.json,stdout:this.context.stdout,includeFooter:!1},async f=>{if(r.invalid.size>0&&!this.json){for(let[h,A]of r.invalid)f.reportError(34,`Invalid configuration key "${h}" in ${A}`);f.reportSeparator()}if(this.json)for(let h of a){if(this.noDefaults&&!r.sources.has(h))continue;let A=r.settings.get(h);typeof A>"u"&&f.reportError(34,`No configuration key named "${h}"`);let m=r.getSpecial(h,{hideSecrets:!0,getNativePaths:!0}),w=r.sources.get(h)??"<default>",v=w&&w[0]!=="<"?me.fromPortablePath(w):w;f.reportJson({key:h,effective:m,source:v,...A})}else{let h={breakLength:1/0,colors:r.get("enableColors"),maxArrayLength:2},A={},m={children:A};for(let w of a){if(this.noDefaults&&!r.sources.has(w))continue;let v=r.settings.get(w),D=r.sources.get(w)??"<default>",I=r.getSpecial(w,{hideSecrets:!0,getNativePaths:!0}),R={Description:{label:"Description",value:pe.tuple(pe.Type.MARKDOWN,{text:v.description,format:this.cli.format(),paragraphs:!1})},Source:{label:"Source",value:pe.tuple(D[0]==="<"?pe.Type.CODE:pe.Type.PATH,D)}};A[w]={value:pe.tuple(pe.Type.CODE,w),children:R};let N=(U,V)=>{for(let[ee,te]of V)if(te instanceof Map){let ie={};U[ee]={children:ie},N(ie,te)}else U[ee]={label:ee,value:pe.tuple(pe.Type.NO_HINT,(0,WO.inspect)(te,h))}};I instanceof Map?N(R,I):R.Value={label:"Value",value:pe.tuple(pe.Type.NO_HINT,(0,WO.inspect)(I,h))}}a.length!==1&&(n=void 0),bs.emitTree(m,{configuration:r,json:this.json,stdout:this.context.stdout,separators:2})}});if(!this.json&&typeof n<"u"){let f=a[0],h=(0,WO.inspect)(r.getSpecial(f,{hideSecrets:!0,getNativePaths:!0}),{colors:r.get("enableColors")});this.context.stdout.write(`
`),this.context.stdout.write(`${h}
`)}return l.exitCode()}};We();sr();ga();var YO={};lr(YO,{Strategy:()=>ID,acceptedStrategies:()=>amt,dedupe:()=>_W});We();We();var h2e=st(ma()),ID=(e=>(e.HIGHEST="highest",e))(ID||{}),amt=new Set(Object.values(ID)),cmt={highest:async(t,e,{resolver:r,fetcher:s,resolveOptions:a,fetchOptions:n})=>{let l=new Map;for(let[h,A]of t.storedResolutions){let m=t.storedDescriptors.get(h);if(typeof m>"u")throw new Error(`Assertion failed: The descriptor (${h}) should have been registered`);Ye.getSetWithDefault(l,m.identHash).add(A)}let f=new Map(Ye.mapAndFilter(t.storedDescriptors.values(),h=>G.isVirtualDescriptor(h)?Ye.mapAndFilter.skip:[h.descriptorHash,Ye.makeDeferred()]));for(let h of t.storedDescriptors.values()){let A=f.get(h.descriptorHash);if(typeof A>"u")throw new Error(`Assertion failed: The descriptor (${h.descriptorHash}) should have been registered`);let m=t.storedResolutions.get(h.descriptorHash);if(typeof m>"u")throw new Error(`Assertion failed: The resolution (${h.descriptorHash}) should have been registered`);let w=t.originalPackages.get(m);if(typeof w>"u")throw new Error(`Assertion failed: The package (${m}) should have been registered`);Promise.resolve().then(async()=>{let v=r.getResolutionDependencies(h,a),D=Object.fromEntries(await Ye.allSettledSafe(Object.entries(v).map(async([ee,te])=>{let ie=f.get(te.descriptorHash);if(typeof ie>"u")throw new Error(`Assertion failed: The descriptor (${te.descriptorHash}) should have been registered`);let ae=await ie.promise;if(!ae)throw new Error("Assertion failed: Expected the dependency to have been through the dedupe process itself");return[ee,ae.updatedPackage]})));if(e.length&&!h2e.default.isMatch(G.stringifyIdent(h),e)||!r.shouldPersistResolution(w,a))return w;let I=l.get(h.identHash);if(typeof I>"u")throw new Error(`Assertion failed: The resolutions (${h.identHash}) should have been registered`);if(I.size===1)return w;let R=[...I].map(ee=>{let te=t.originalPackages.get(ee);if(typeof te>"u")throw new Error(`Assertion failed: The package (${ee}) should have been registered`);return te}),N=await r.getSatisfying(h,D,R,a),U=N.locators?.[0];if(typeof U>"u"||!N.sorted)return w;let V=t.originalPackages.get(U.locatorHash);if(typeof V>"u")throw new Error(`Assertion failed: The package (${U.locatorHash}) should have been registered`);return V}).then(async v=>{let D=await t.preparePackage(v,{resolver:r,resolveOptions:a});A.resolve({descriptor:h,currentPackage:w,updatedPackage:v,resolvedPackage:D})}).catch(v=>{A.reject(v)})}return[...f.values()].map(h=>h.promise)}};async function _W(t,{strategy:e,patterns:r,cache:s,report:a}){let{configuration:n}=t,l=new rs,f=n.makeResolver(),h=n.makeFetcher(),A={cache:s,checksums:t.storedChecksums,fetcher:h,project:t,report:l,cacheOptions:{skipIntegrityCheck:!0}},m={project:t,resolver:f,report:l,fetchOptions:A};return await a.startTimerPromise("Deduplication step",async()=>{let w=cmt[e],v=await w(t,r,{resolver:f,resolveOptions:m,fetcher:h,fetchOptions:A}),D=jo.progressViaCounter(v.length);await a.reportProgress(D);let I=0;await Promise.all(v.map(U=>U.then(V=>{if(V===null||V.currentPackage.locatorHash===V.updatedPackage.locatorHash)return;I++;let{descriptor:ee,currentPackage:te,updatedPackage:ie}=V;a.reportInfo(0,`${G.prettyDescriptor(n,ee)} can be deduped from ${G.prettyLocator(n,te)} to ${G.prettyLocator(n,ie)}`),a.reportJson({descriptor:G.stringifyDescriptor(ee),currentResolution:G.stringifyLocator(te),updatedResolution:G.stringifyLocator(ie)}),t.storedResolutions.set(ee.descriptorHash,ie.locatorHash)}).finally(()=>D.tick())));let R;switch(I){case 0:R="No packages";break;case 1:R="One package";break;default:R=`${I} packages`}let N=pe.pretty(n,e,pe.Type.CODE);return a.reportInfo(0,`${R} can be deduped using the ${N} strategy`),I})}var VC=class extends mt{constructor(){super(...arguments);this.strategy=ye.String("-s,--strategy","highest",{description:"The strategy to use when deduping dependencies",validator:$s(ID)});this.check=ye.Boolean("-c,--check",!1,{description:"Exit with exit code 1 when duplicates are found, without persisting the dependency tree"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.mode=ye.String("--mode",{description:"Change what artifacts installs generate",validator:$s(uc)});this.patterns=ye.Rest()}static{this.paths=[["dedupe"]]}static{this.usage=At.Usage({description:"deduplicate dependencies with overlapping ranges",details:"\n Duplicates are defined as descriptors with overlapping ranges being resolved and locked to different locators. They are a natural consequence of Yarn's deterministic installs, but they can sometimes pile up and unnecessarily increase the size of your project.\n\n This command dedupes dependencies in the current project using different strategies (only one is implemented at the moment):\n\n - `highest`: Reuses (where possible) the locators with the highest versions. This means that dependencies can only be upgraded, never dow Line truncated
`)}};var YC=class extends mt{static{this.paths=[["help"],["--help"],["-h"]]}async execute(){this.context.stdout.write(this.cli.usage(null))}};We();Mt();sr();var KC=class extends mt{constructor(){super(...arguments);this.leadingArgument=ye.String();this.args=ye.Proxy()}async execute(){if(this.leadingArgument.match(/[\\/]/)&&!G.tryParseIdent(this.leadingArgument)){let r=Y.resolve(this.context.cwd,me.toPortablePath(this.leadingArgument));return await this.cli.run(this.args,{cwd:r})}else return await this.cli.run(["run",this.leadingArgument,...this.args])}};We();var zC=class extends mt{static{this.paths=[["-v"],["--version"]]}async execute(){this.context.stdout.write(`${Fn||"<unknown>"}
`)}};We();We();sr();var JC=class extends mt{constructor(){super(...arguments);this.commandName=ye.String();this.args=ye.Proxy()}static{this.paths=[["exec"]]}static{this.usage=At.Usage({description:"execute a shell script",details:`
This command simply executes a shell script within the context of the root directory of the active workspace using the portable shell.
It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment).
`,examples:[["Execute a single shell command","$0 exec echo Hello World"],["Execute a shell script",'$0 exec "tsc & babel src --out-dir lib"']]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,locator:a}=await Yt.find(r,this.context.cwd);return await s.restoreInstallState(),await qn.executePackageShellcode(a,this.commandName,this.args,{cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,project:s})}};We();sr();ga();var ZC=class extends mt{constructor(){super(...arguments);this.hash=ye.String({required:!1,validator:P0(_h(),[xp(/^p[0-9a-f]{6}$/)])})}static{this.paths=[["explain","peer-requirements"]]}static{this.usage=At.Usage({description:"explain a set of peer requirements",details:`
A peer requirement represents all peer requests that a subject must satisfy when providing a requested package to requesters.
When the hash argument is specified, this command prints a detailed explanation of the peer requirement corresponding to the hash and whether it is satisfied or not.
When used without arguments, this command lists all peer requirements and the corresponding hash that can be used to get detailed information about a given requirement.
**Note:** A hash is a seven-letter code consisting of the letter 'p' followed by six characters that can be obtained from peer dependency warnings or from the list of all peer requirements(\`yarn explain peer-requirements\`).
`,examples:[["Explain the corresponding peer requirement for a hash","$0 explain peer-requirements p1a4ed"],["List all peer requirements","$0 explain peer-requirements"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s}=await Yt.find(r,this.context.cwd);return await s.restoreInstallState({restoreResolutions:!1}),await s.applyLightResolution(),typeof this.hash<"u"?await umt(this.hash,s,{stdout:this.context.stdout}):await fmt(s,{stdout:this.context.stdout})}};async function umt(t,e,r){let s=e.peerRequirementNodes.get(t);if(typeof s>"u")throw new Error(`No peerDependency requirements found for hash: "${t}"`);let a=new Set,n=h=>a.has(h.requester.locatorHash)?{value:pe.tuple(pe.Type.DEPENDENT,{locator:h.requester,descriptor:h.descriptor}),children:h.children.size>0?[{value:pe.tuple(pe.Type.NO_HINT,"...")}]:[]}:(a.add(h.requester.locatorHash),{value:pe.tuple(pe.Type.DEPENDENT,{locator:h.requester,descriptor:h.descriptor}),children:Object.fromEntries(Array.from(h.children.values(),A=>[G.stringifyLocator(A.requester),n(A)]))}),l=e.peerWarnings.find(h=>h.hash===t);return(await Wt.start({configuration:e.configuration,stdout:r.stdout,includeFooter:!1,includePrefix:!1},async h=>{let A=pe.mark(e.configuration),m=l?A.Cross:A.Check;if(h.reportInfo(0,`Package ${pe.pretty(e.configuration,s.subject,pe.Type.LOCATOR)} is requested to provide ${pe.pretty(e.configuration,s.ident,pe.Type.IDENT)} by its descendants`),h.reportSeparator(),h.reportInfo(0,pe.pretty(e.configuration,s.subject,pe.Type.LOCATOR)),bs.emitTree({children:Object.fromEntries(Array.from(s.requests.values(),w=>[G.stringifyLocator(w.requester),n(w)]))},{configuration:e.configuration,stdout:r.stdout,json:!1}),h.reportSeparator(),s.provided.range==="missing:"){let w=l?"":" , but all peer requests are optional";h.reportInfo(0,`${m} Package ${pe.pretty(e.configuration,s.subject,pe.Type.LOCATOR)} does not provide ${pe.pretty(e.configuration,s.ident,pe.Type.IDENT)}${w}.`)}else{let w=e.storedResolutions.get(s.provided.descriptorHash);if(!w)throw new Error("Assertion failed: Expected the descriptor to be registered");let v=e.storedPackages.get(w);if(!v)throw new Error("Assertion failed: Expected the package to be registered");h.reportInfo(0,`${m} Package ${pe.pretty(e.configuration,s.subject,pe.Type.LOCATOR)} provides ${pe.pretty(e.configuration,s.ident,pe.Type.IDENT)} with version ${G.prettyReference(e.configuration,v.version??"0.0.0")}, ${l?"which does not satisfy all requests.":"which satisfies all requests"}`),l?.type===3&&(l.range?h.reportInfo(0,` The combined requested range is ${pe.pretty(e.configuration,l.range,pe.Type.RANGE)}`):h.reportInfo(0," Unfortunately, the requested ranges have no overlap"))}})).exitCode()}async function fmt(t,e){return(await Wt.start({configuration:t.configuration,stdout:e.stdout,includeFooter:!1,includePrefix:!1},async s=>{let a=pe.mark(t.configuration),n=Ye.sortMap(t.peerRequirementNodes,[([,l])=>G.stringifyLocator(l.subject),([,l])=>G.stringifyIdent(l.ident)]);for(let[,l]of n.values()){if(!l.root)continue;let f=t.peerWarnings.find(m=>m.hash===l.hash),h=[...G.allPeerRequests(l)],A;if(h.length>2?A=` and ${h.length-1} other dependencies`:h.length===2?A=" and 1 other dependency":A="",l.provided.range!=="missing:"){let m=t.storedResolutions.get(l.provided.descriptorHash);if(!m)throw new Error("Assertion failed: Expected the resolution to have been registered");let w=t.storedPackages.get(m);if(!w)throw new Error("Assertion failed: Expected the provided package to have been registered");let v=`${pe.pretty(t.configuration,l.hash,pe.Type.CODE)} \u2192 ${f?a.Cross:a.Check} ${G.prettyLocator(t.configuration,l.subject)} provides ${G.prettyLocator(t.configuration,w)} to ${G.prettyLocator(t.configuration,h[0].requester)}${A}`;f?s.reportWarning(0,v):s.reportInfo(0,v)}else{let m=`${pe.pretty(t.configuration,l.hash,pe.Type.CODE)} \u2192 ${f?a.Cross:a.Check} ${G.prettyLocator(t.configuration,l.subject)} doesn't provide ${G.prettyIdent(t.configuration,l.ident)} to ${G.prettyLocator(t.configuration,h[0].requester)}${A}`;f?s.reportWarning(0,m):s.reportInfo(0,m)}}})).exitCode()}We();sr();ga();We();We();Mt();sr();var p2e=st(Di()),XC=class extends mt{constructor(){super(...arguments);this.useYarnPath=ye.Boolean("--yarn-path",{description:"Set the yarnPath setting even if the version can be accessed by Corepack"});this.onlyIfNeeded=ye.Boolean("--only-if-needed",!1,{description:"Only lock the Yarn version if it isn't already locked"});this.version=ye.String()}static{this.paths=[["set","version"]]}static{this.usage=At.Usage({description:"lock the Yarn version used by the project",details:"\n This command will set a specific release of Yarn to be used by Corepack: https://nodejs.org/api/corepack.html.\n\n By default it only will set the `packageManager` field at the root of your project, but if the referenced release cannot be represented this way, if you already have `yarnPath` configured, or if you set th Line truncated
${e}`)})}let f=t.projectCwd??t.startingCwd,h=Y.resolve(f,".yarn/releases"),A=Y.resolve(h,`yarn-${e}.cjs`),m=Y.relative(t.startingCwd,A),w=Ye.isTaggedYarnVersion(e),v=t.get("yarnPath"),D=!w,I=D||!!v||!!a;if(a===!1){if(D)throw new Zt(0,"You explicitly opted out of yarnPath usage in your command line, but the version you specified cannot be represented by Corepack");I=!1}else!I&&!process.env.COREPACK_ROOT&&(s.reportWarning(0,`You don't seem to have ${pe.applyHyperlink(t,"Corepack","https://nodejs.org/api/corepack.html")} enabled; we'll have to rely on ${pe.applyHyperlink(t,"yarnPath","https://yarnpkg.com/configuration/yarnrc#yarnPath")} instead`),I=!0);if(I){let ee=await l();s.reportInfo(0,`Saving the new release in ${pe.pretty(t,m,"magenta")}`),await fe.removePromise(Y.dirname(A)),await fe.mkdirPromise(Y.dirname(A),{recursive:!0}),await fe.writeFilePromise(A,ee,{mode:493}),await $e.updateConfiguration(f,{yarnPath:Y.relative(f,A)})}else await fe.removePromise(Y.dirname(A)),await $e.updateConfiguration(f,{yarnPath:$e.deleteProperty});let R=await nr.tryFind(f)||new nr;R.packageManager=`yarn@${w?e:await wD(t,"stable")}`;let N={};R.exportTo(N);let U=Y.join(f,nr.fileName),V=`${JSON.stringify(N,null,R.indent)}
`;return await fe.changeFilePromise(U,V,{automaticNewlines:!0}),{bundleVersion:e}}function d2e(t){return Tr[KT(t)]}var Amt=/## (?<code>YN[0-9]{4}) - `(?<name>[A-Z_]+)`\n\n(?<details>(?:.(?!##))+)/gs;async function pmt(t){let r=`https://repo.yarnpkg.com/${Ye.isTaggedYarnVersion(Fn)?Fn:await wD(t,"canary")}/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx`,s=await Sn.get(r,{configuration:t});return new Map(Array.from(s.toString().matchAll(Amt),({groups:a})=>{if(!a)throw new Error("Assertion failed: Expected the match to have been successful");let n=d2e(a.code);if(a.name!==n)throw new Error(`Assertion failed: Invalid error code data: Expected "${a.name}" to be named "${n}"`);return[a.code,a.details]}))}var $C=class extends mt{constructor(){super(...arguments);this.code=ye.String({required:!1,validator:gS(_h(),[xp(/^YN[0-9]{4}$/)])});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["explain"]]}static{this.usage=At.Usage({description:"explain an error code",details:`
When the code argument is specified, this command prints its name and its details.
When used without arguments, this command lists all error codes and their names.
`,examples:[["Explain an error code","$0 explain YN0006"],["List all error codes","$0 explain"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins);if(typeof this.code<"u"){let s=d2e(this.code),a=pe.pretty(r,s,pe.Type.CODE),n=this.cli.format().header(`${this.code} - ${a}`),f=(await pmt(r)).get(this.code),h=typeof f<"u"?pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.MARKDOWN,{text:f,format:this.cli.format(),paragraphs:!0})):`This error code does not have a description.
You can help us by editing this page on GitHub \u{1F642}:
${pe.jsonOrPretty(this.json,r,pe.tuple(pe.Type.URL,"https://github.com/yarnpkg/berry/blob/master/packages/docusaurus/docs/advanced/01-general-reference/error-codes.mdx"))}
`;this.json?this.context.stdout.write(`${JSON.stringify({code:this.code,name:s,details:h})}
`):this.context.stdout.write(`${n}
${h}
`)}else{let s={children:Ye.mapAndFilter(Object.entries(Tr),([a,n])=>Number.isNaN(Number(a))?Ye.mapAndFilter.skip:{label:Mh(Number(a)),value:pe.tuple(pe.Type.CODE,n)})};bs.emitTree(s,{configuration:r,stdout:this.context.stdout,json:this.json})}}};We();Mt();sr();var g2e=st(ma()),e1=class extends mt{constructor(){super(...arguments);this.all=ye.Boolean("-A,--all",!1,{description:"Print versions of a package from the whole project"});this.recursive=ye.Boolean("-R,--recursive",!1,{description:"Print information for all packages, including transitive dependencies"});this.extra=ye.Array("-X,--extra",[],{description:"An array of requests of extra data provided by plugins"});this.cache=ye.Boolean("--cache",!1,{description:"Print information about the cache entry of a package (path, size, checksum)"});this.dependents=ye.Boolean("--dependents",!1,{description:"Print all dependents for each matching package"});this.manifest=ye.Boolean("--manifest",!1,{description:"Print data obtained by looking at the package archive (license, homepage, ...)"});this.nameOnly=ye.Boolean("--name-only",!1,{description:"Only print the name for the matching packages"});this.virtuals=ye.Boolean("--virtuals",!1,{description:"Print each instance of the virtual packages"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.patterns=ye.Rest()}static{this.paths=[["info"]]}static{this.usage=At.Usage({description:"see information related to packages",details:"\n This command prints various information related to the specified packages, accepting glob patterns.\n\n By default, if the locator reference is missing, Yarn will default to print the information about all the matching direct dependencies of the package for the active workspace. To instead print all versions of the package that are direct dependencies of any of your workspaces, use the `-A,--all` flag. Adding the `-R,--recursive` flag will also report transitive dependencies.\n\n Some fields will be hidden by default in order to keep the output readable, but can be selectively displayed by using additional options (`--dependents`, `--manifest`, `--virtuals`, ...) described in the option descriptions.\n\n Note that this command will only print the information directly related to the selected packages - if you wish to know why the package is there in the first place, use `yarn why` which will do just that (it also provides a `-R,--recursive` flag that may be of some help).\n ",examples:[["Show information about Lodash","$0 info lodash"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd),n=await gn.find(r);if(!a&&!this.all)throw new Dr(s.cwd,this.context.cwd);await s.restoreInstallState();let l=new Set(this.extra);this.cache&&l.add("cache"),this.dependents&&l.add("dependents"),this.manifest&&l.add("manifest");let f=(te,{recursive:ie})=>{let ae=te.anchoredLocator.locatorHash,ge=new Map,de=[ae];for(;de.length>0;){let xe=de.shift();if(ge.has(xe))continue;let we=s.storedPackages.get(xe);if(typeof we>"u")throw new Error("Assertion failed: Expected the package to be registered");if(ge.set(xe,we),G.isVirtualLocator(we)&&de.push(G.devirtualizeLocator(we).locatorHash),!(!ie&&xe!==ae))for(let d of we.dependencies.values()){let be=s.storedResolutions.get(d.descriptorHash);if(typeof be>"u")throw new Error("Assertion failed: Expected the resolution to be registered");de.push(be)}}return ge.values()},h=({recursive:te})=>{let ie=new Map;for(let ae of s.workspaces)for(let ge of f(ae,{recursive:te}))ie.set(ge.locatorHash,ge);return ie.values()},A=({all:te,recursive:ie})=>te&&ie?s.storedPackages.values():te?h({recursive:ie}):f(a,{recursive:ie}),m=({all:te,recursive:ie})=>{let ae=A({all:te,recursive:ie}),ge=this.patterns.map(we=>{let d=G.parseLocator(we),be=g2e.default.makeRe(G.stringifyIdent(d)),Ce=G.isVirtualLocator(d),Ee=Ce?G.devirtualizeLocator(d):d;return he=>{let $=G.stringifyIdent(he);if(!be.test($))return!1;if(d.reference==="unknown")return!0;let De=G.isVirtualLocator(he),Te=De?G.devirtualizeLocator(he):he;return!(Ce&&De&&d.reference!==he.reference||Ee.reference!==Te.reference)}}),de=Ye.sortMap([...ae],we=>G.stringifyLocator(we));return{selection:de.filter(we=>ge.length===0||ge.some(d=>d(we))),sortedLookup:de}},{selection:w,sortedLookup:v}=m({all:this.all,recursive:this.recursive});if(w.length===0)throw new ht("No package matched your request");let D=new Map;if(this.dependents)for(let te of v)for(let ie of te.dependencies.values()){let ae=s.storedResolutions.get(ie.descriptorHash);if(typeof ae>"u")throw new Error("Assertion failed: Expected the resolution to be registered");Ye.getArrayWithDefault(D,ae).push(te)}let I=new Map;for(let te of v){if(!G.isVirtualLocator(te))continue;let ie=G.devirtualizeLocator(te);Ye.getArrayWithDefault(I,ie.locatorHash).push(te)}let R={},N={children:R},U=r.makeFetcher(),V={project:s,fetcher:U,cache:n,checksums:s.storedChecksum Line truncated
This command simply runs Node. It also makes sure to call it in a way that's compatible with the current project (for example, on PnP projects the environment will be setup in such a way that PnP will be correctly injected into the environment).
The Node process will use the exact same version of Node as the one used to run Yarn itself, which might be a good way to ensure that your commands always use a consistent Node version.
`,examples:[["Run a Node script","$0 node ./my-script.js"]]})}async execute(){return this.cli.run(["exec","node",...this.args])}};We();sr();var i1=class extends mt{constructor(){super(...arguments);this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","check"]]}static{this.usage=At.Usage({category:"Plugin-related commands",description:"find all third-party plugins that differ from their own spec",details:`
Check only the plugins from https.
If this command detects any plugin differences in the CI environment, it will throw an error.
`,examples:[["find all third-party plugins that differ from their own spec","$0 plugin check"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=await $e.findRcFiles(this.context.cwd);return(await Wt.start({configuration:r,json:this.json,stdout:this.context.stdout},async n=>{for(let l of s)if(l.data?.plugins)for(let f of l.data.plugins){if(!f.checksum||!f.spec.match(/^https?:/))continue;let h=await Sn.get(f.spec,{configuration:r}),A=si.makeHash(h);if(f.checksum===A)continue;let m=pe.pretty(r,f.path,pe.Type.PATH),w=pe.pretty(r,f.spec,pe.Type.URL),v=`${m} is different from the file provided by ${w}`;n.reportJson({...f,newChecksum:A}),n.reportError(0,v)}})).exitCode()}};We();We();Mt();sr();var w2e=Ae("os");We();Mt();sr();var m2e=Ae("os");We();au();sr();var Emt="https://raw.githubusercontent.com/yarnpkg/berry/master/plugins.yml";async function tE(t,e){let r=await Sn.get(Emt,{configuration:t}),s=Fs(r.toString());return Object.fromEntries(Object.entries(s).filter(([a,n])=>!e||zr.satisfiesWithPrereleases(e,n.range??"<4.0.0-rc.1")))}var s1=class extends mt{constructor(){super(...arguments);this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","list"]]}static{this.usage=At.Usage({category:"Plugin-related commands",description:"list the available official plugins",details:"\n This command prints the plugins available directly from the Yarn repository. Only those plugins can be referenced by name in `yarn plugin import`.\n ",examples:[["List the official plugins","$0 plugin list"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins);return(await Wt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{let n=await tE(r,Fn);for(let[l,{experimental:f,...h}]of Object.entries(n)){let A=l;f&&(A+=" [experimental]"),a.reportJson({name:l,experimental:f,...h}),a.reportInfo(null,A)}})).exitCode()}};var Imt=/^[0-9]+$/,wmt=process.platform==="win32";function y2e(t){return Imt.test(t)?`pull/${t}/head`:t}var Cmt=({repository:t,branch:e},r)=>[["git","init",me.fromPortablePath(r)],["git","remote","add","origin",t],["git","fetch","origin","--depth=1",y2e(e)],["git","reset","--hard","FETCH_HEAD"]],Bmt=({branch:t})=>[["git","fetch","origin","--depth=1",y2e(t),"--force"],["git","reset","--hard","FETCH_HEAD"],["git","clean","-dfx","-e","packages/yarnpkg-cli/bundles"]],vmt=({plugins:t,noMinify:e},r,s)=>[["yarn","build:cli",...new Array().concat(...t.map(a=>["--plugin",Y.resolve(s,a)])),...e?["--no-minify"]:[],"|"],[wmt?"move":"mv","packages/yarnpkg-cli/bundles/yarn.js",me.fromPortablePath(r),"|"]],o1=class extends mt{constructor(){super(...arguments);this.installPath=ye.String("--path",{description:"The path where the repository should be cloned to"});this.repository=ye.String("--repository","https://github.com/yarnpkg/berry.git",{description:"The repository that should be cloned"});this.branch=ye.String("--branch","master",{description:"The branch of the repository that should be cloned"});this.plugins=ye.Array("--plugin",[],{description:"An array of additional plugins that should be included in the bundle"});this.dryRun=ye.Boolean("-n,--dry-run",!1,{description:"If set, the bundle will be built but not added to the project"});this.noMinify=ye.Boolean("--no-minify",!1,{description:"Build a bundle for development (debugging) - non-minified and non-mangled"});this.force=ye.Boolean("-f,--force",!1,{description:"Always clone the repository instead of trying to fetch the latest commits"});this.skipPlugins=ye.Boolean("--skip-plugins",!1,{description:"Skip updating the contrib plugins"})}static{this.paths=[["set","version","from","sources"]]}static{this.usage=At.Usage({description:"build Yarn from master",details:`
This command will clone the Yarn repository into a temporary folder, then build it. The resulting bundle will then be copied into the local project.
By default, it also updates all contrib plugins to the same commit the bundle is built from. This behavior can be disabled by using the \`--skip-plugins\` flag.
`,examples:[["Build Yarn from master","$0 set version from sources"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s}=await Yt.find(r,this.context.cwd),a=typeof this.installPath<"u"?Y.resolve(this.context.cwd,me.toPortablePath(this.installPath)):Y.resolve(me.toPortablePath((0,m2e.tmpdir)()),"yarnpkg-sources",si.makeHash(this.repository).slice(0,6));return(await Wt.start({configuration:r,stdout:this.context.stdout},async l=>{await HW(this,{configuration:r,report:l,target:a}),l.reportSeparator(),l.reportInfo(0,"Building a fresh bundle"),l.reportSeparator();let f=await un.execvp("git",["rev-parse","--short","HEAD"],{cwd:a,strict:!0}),h=Y.join(a,`packages/yarnpkg-cli/bundles/yarn-${f.stdout.trim()}.js`);fe.existsSync(h)||(await CD(vmt(this,h,a),{configuration:r,context:this.context,target:a}),l.reportSeparator());let A=await fe.readFilePromise(h);if(!this.dryRun){let{bundleVersion:m}=await MW(r,null,async()=>A,{report:l});this.skipPlugins||await Smt(this,m,{project:s,report:l,target:a})}})).exitCode()}};async function CD(t,{configuration:e,context:r,target:s}){for(let[a,...n]of t){let l=n[n.length-1]==="|";if(l&&n.pop(),l)await un.pipevp(a,n,{cwd:s,stdin:r.stdin,stdout:r.stdout,stderr:r.stderr,strict:!0});else{r.stdout.write(`${pe.pretty(e,` $ ${[a,...n].join(" ")}`,"grey")}
`);try{await un.execvp(a,n,{cwd:s,strict:!0})}catch(f){throw r.stdout.write(f.stdout||f.stack),f}}}}async function HW(t,{configuration:e,report:r,target:s}){let a=!1;if(!t.force&&fe.existsSync(Y.join(s,".git"))){r.reportInfo(0,"Fetching the latest commits"),r.reportSeparator();try{await CD(Bmt(t),{configuration:e,context:t.context,target:s}),a=!0}catch{r.reportSeparator(),r.reportWarning(0,"Repository update failed; we'll try to regenerate it")}}a||(r.reportInfo(0,"Cloning the remote repository"),r.reportSeparator(),await fe.removePromise(s),await fe.mkdirPromise(s,{recursive:!0}),await CD(Cmt(t,s),{configuration:e,context:t.context,target:s}))}async function Smt(t,e,{project:r,report:s,target:a}){let n=await tE(r.configuration,e),l=new Set(Object.keys(n));for(let f of r.configuration.plugins.keys())l.has(f)&&await jW(f,t,{project:r,report:s,target:a})}We();We();Mt();sr();var E2e=st(Di()),I2e=Ae("vm");var a1=class extends mt{constructor(){super(...arguments);this.name=ye.String();this.checksum=ye.Boolean("--checksum",!0,{description:"Whether to care if this plugin is modified"})}static{this.paths=[["plugin","import"]]}static{this.usage=At.Usage({category:"Plugin-related commands",description:"download a plugin",details:`
This command downloads the specified plugin from its remote location and updates the configuration to reference it in further CLI invocations.
Three types of plugin references are accepted:
- If the plugin is stored within the Yarn repository, it can be referenced by name.
- Third-party plugins can be referenced directly through their public urls.
- Local plugins can be referenced by their path on the disk.
If the \`--no-checksum\` option is set, Yarn will no longer care if the plugin is modified.
Plugins cannot be downloaded from the npm registry, and aren't allowed to have dependencies (they need to be bundled into a single file, possibly thanks to the \`@yarnpkg/builder\` package).
`,examples:[['Download and activate the "@yarnpkg/plugin-exec" plugin',"$0 plugin import @yarnpkg/plugin-exec"],['Download and activate the "@yarnpkg/plugin-exec" plugin (shorthand)',"$0 plugin import exec"],["Download and activate a community plugin","$0 plugin import https://example.org/path/to/plugin.js"],["Activate a local plugin","$0 plugin import ./path/to/plugin.js"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins);return(await Wt.start({configuration:r,stdout:this.context.stdout},async a=>{let{project:n}=await Yt.find(r,this.context.cwd),l,f;if(this.name.match(/^\.{0,2}[\\/]/)||me.isAbsolute(this.name)){let h=Y.resolve(this.context.cwd,me.toPortablePath(this.name));a.reportInfo(0,`Reading ${pe.pretty(r,h,pe.Type.PATH)}`),l=Y.relative(n.cwd,h),f=await fe.readFilePromise(h)}else{let h;if(this.name.match(/^https?:/)){try{new URL(this.name)}catch{throw new Zt(52,`Plugin specifier "${this.name}" is neither a plugin name nor a valid url`)}l=this.name,h=this.name}else{let A=G.parseLocator(this.name.replace(/^((@yarnpkg\/)?plugin-)?/,"@yarnpkg/plugin-"));if(A.reference!=="unknown"&&!E2e.default.valid(A.reference))throw new Zt(0,"Official plugins only accept strict version references. Use an explicit URL if you wish to download them from another location.");let m=G.stringifyIdent(A),w=await tE(r,Fn);if(!Object.hasOwn(w,m)){let v=`Couldn't find a plugin named ${G.prettyIdent(r,A)} on the remote registry.
`;throw r.plugins.has(m)?v+=`A plugin named ${G.prettyIdent(r,A)} is already installed; possibly attempting to import a built-in plugin.`:v+=`Note that only the plugins referenced on our website (${pe.pretty(r,"https://github.com/yarnpkg/berry/blob/master/plugins.yml",pe.Type.URL)}) can be referenced by their name; any other plugin will have to be referenced through its public url (for example ${pe.pretty(r,"https://github.com/yarnpkg/berry/raw/master/packages/plugin-typescript/bin/%40yarnpkg/plugin-typescript.js",pe.Type.URL)}).`,new Zt(51,v)}l=m,h=w[m].url,A.reference!=="unknown"?h=h.replace(/\/master\//,`/${m}/${A.reference}/`):Fn!==null&&(h=h.replace(/\/master\//,`/@yarnpkg/cli/${Fn}/`))}a.reportInfo(0,`Downloading ${pe.pretty(r,h,"green")}`),f=await Sn.get(h,{configuration:r})}await GW(l,f,{checksum:this.checksum,project:n,report:a})})).exitCode()}};async function GW(t,e,{checksum:r=!0,project:s,report:a}){let{configuration:n}=s,l={},f={exports:l};(0,I2e.runInNewContext)(e.toString(),{module:f,exports:l});let A=`.yarn/plugins/${f.exports.name}.cjs`,m=Y.resolve(s.cwd,A);a.reportInfo(0,`Saving the new plugin in ${pe.pretty(n,A,"magenta")}`),await fe.mkdirPromise(Y.dirname(m),{recursive:!0}),await fe.writeFilePromise(m,e);let w={path:A,spec:t};r&&(w.checksum=si.makeHash(e)),await $e.addPlugin(s.cwd,[w])}var bmt=({pluginName:t,noMinify:e},r)=>[["yarn",`build:${t}`,...e?["--no-minify"]:[],"|"]],c1=class extends mt{constructor(){super(...arguments);this.installPath=ye.String("--path",{description:"The path where the repository should be cloned to"});this.repository=ye.String("--repository","https://github.com/yarnpkg/berry.git",{description:"The repository that should be cloned"});this.branch=ye.String("--branch","master",{description:"The branch of the repository that should be cloned"});this.noMinify=ye.Boolean("--no-minify",!1,{description:"Build a plugin for development (debugging) - non-minified and non-mangled"});this.force=ye.Boolean("-f,--force",!1,{description:"Always clone the repository instead of trying to fetch the latest commits"});this.name=ye.String()}static{this.paths=[["plugin","import","from","sources"]]}static{this.usage=At.Usage({category:"Plugin-related commands",description:"build a plugin from sources",details:`
This command clones the Yarn repository into a temporary folder, builds the specified contrib plugin and updates the configuration to reference it in further CLI invocations.
The plugins can be referenced by their short name if sourced from the official Yarn repository.
`,examples:[['Build and activate the "@yarnpkg/plugin-exec" plugin',"$0 plugin import from sources @yarnpkg/plugin-exec"],['Build and activate the "@yarnpkg/plugin-exec" plugin (shorthand)',"$0 plugin import from sources exec"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=typeof this.installPath<"u"?Y.resolve(this.context.cwd,me.toPortablePath(this.installPath)):Y.resolve(me.toPortablePath((0,w2e.tmpdir)()),"yarnpkg-sources",si.makeHash(this.repository).slice(0,6));return(await Wt.start({configuration:r,stdout:this.context.stdout},async n=>{let{project:l}=await Yt.find(r,this.context.cwd),f=G.parseIdent(this.name.replace(/^((@yarnpkg\/)?plugin-)?/,"@yarnpkg/plugin-")),h=G.stringifyIdent(f),A=await tE(r,Fn);if(!Object.hasOwn(A,h))throw new Zt(51,`Couldn't find a plugin named "${h}" on the remote registry. Note that only the plugins referenced on our website (https://github.com/yarnpkg/berry/blob/master/plugins.yml) can be built and imported from sources.`);let m=h;await HW(this,{configuration:r,report:n,target:s}),await jW(m,this,{project:l,report:n,target:s})})).exitCode()}};async function jW(t,{context:e,noMinify:r},{project:s,report:a,target:n}){let l=t.replace(/@yarnpkg\//,""),{configuration:f}=s;a.reportSeparator(),a.reportInfo(0,`Building a fresh ${l}`),a.reportSeparator(),await CD(bmt({pluginName:l,noMinify:r},n),{configuration:f,context:e,target:n}),a.reportSeparator();let h=Y.resolve(n,`packages/${l}/bundles/${t}.js`),A=await fe.readFilePromise(h);await GW(t,A,{project:s,report:a})}We();Mt();sr();var l1=class extends mt{constructor(){super(...arguments);this.name=ye.String()}static{this.paths=[["plugin","remove"]]}static{this.usage=At.Usage({category:"Plugin-related commands",description:"remove a plugin",details:`
This command deletes the specified plugin from the .yarn/plugins folder and removes it from the configuration.
**Note:** The plugins have to be referenced by their name property, which can be obtained using the \`yarn plugin runtime\` command. Shorthands are not allowed.
`,examples:[["Remove a plugin imported from the Yarn repository","$0 plugin remove @yarnpkg/plugin-typescript"],["Remove a plugin imported from a local file","$0 plugin remove my-local-plugin"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s}=await Yt.find(r,this.context.cwd);return(await Wt.start({configuration:r,stdout:this.context.stdout},async n=>{let l=this.name,f=G.parseIdent(l);if(!r.plugins.has(l))throw new ht(`${G.prettyIdent(r,f)} isn't referenced by the current configuration`);let h=`.yarn/plugins/${l}.cjs`,A=Y.resolve(s.cwd,h);fe.existsSync(A)&&(n.reportInfo(0,`Removing ${pe.pretty(r,h,pe.Type.PATH)}...`),await fe.removePromise(A)),n.reportInfo(0,"Updating the configuration..."),await $e.updateConfiguration(s.cwd,{plugins:m=>{if(!Array.isArray(m))return m;let w=m.filter(v=>v.path!==h);return w.length===0?$e.deleteProperty:w.length===m.length?m:w}})})).exitCode()}};We();sr();var u1=class extends mt{constructor(){super(...arguments);this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["plugin","runtime"]]}static{this.usage=At.Usage({category:"Plugin-related commands",description:"list the active plugins",details:`
This command prints the currently active plugins. Will be displayed both builtin plugins and external plugins.
`,examples:[["List the currently active plugins","$0 plugin runtime"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins);return(await Wt.start({configuration:r,json:this.json,stdout:this.context.stdout},async a=>{for(let n of r.plugins.keys()){let l=this.context.plugins.plugins.has(n),f=n;l&&(f+=" [builtin]"),a.reportJson({name:n,builtin:l}),a.reportInfo(null,`${f}`)}})).exitCode()}};We();We();sr();var f1=class extends mt{constructor(){super(...arguments);this.idents=ye.Rest()}static{this.paths=[["rebuild"]]}static{this.usage=At.Usage({description:"rebuild the project's native packages",details:`
This command will automatically cause Yarn to forget about previous compilations of the given packages and to run them again.
Note that while Yarn forgets the compilation, the previous artifacts aren't erased from the filesystem and may affect the next builds (in good or bad). To avoid this, you may remove the .yarn/unplugged folder, or any other relevant location where packages might have been stored (Yarn may offer a way to do that automatically in the future).
By default all packages will be rebuilt, but you can filter the list by specifying the names of the packages you want to clear from memory.
`,examples:[["Rebuild all packages","$0 rebuild"],["Rebuild fsevents only","$0 rebuild fsevents"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd),n=await gn.find(r);if(!a)throw new Dr(s.cwd,this.context.cwd);let l=new Set;for(let f of this.idents)l.add(G.parseIdent(f).identHash);if(await s.restoreInstallState({restoreResolutions:!1}),await s.resolveEverything({cache:n,report:new rs}),l.size>0)for(let f of s.storedPackages.values())l.has(f.identHash)&&(s.storedBuildState.delete(f.locatorHash),s.skippedBuilds.delete(f.locatorHash));else s.storedBuildState.clear(),s.skippedBuilds.clear();return await s.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};We();We();We();sr();var qW=st(ma());ga();var h1=class extends mt{constructor(){super(...arguments);this.all=ye.Boolean("-A,--all",!1,{description:"Apply the operation to all workspaces from the current project"});this.mode=ye.String("--mode",{description:"Change what artifacts installs generate",validator:$s(uc)});this.patterns=ye.Rest()}static{this.paths=[["remove"]]}static{this.usage=At.Usage({description:"remove dependencies from the project",details:`
This command will remove the packages matching the specified patterns from the current workspace.
If the \`--mode=<mode>\` option is set, Yarn will change which artifacts are generated. The modes currently supported are:
- \`skip-build\` will not run the build scripts at all. Note that this is different from setting \`enableScripts\` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.
- \`update-lockfile\` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.
This command accepts glob patterns as arguments (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.
`,examples:[["Remove a dependency from the current project","$0 remove lodash"],["Remove a dependency from all workspaces at once","$0 remove lodash --all"],["Remove all dependencies starting with `eslint-`","$0 remove 'eslint-*'"],["Remove all dependencies with the `@babel` scope","$0 remove '@babel/*'"],["Remove all dependencies matching `react-dom` or `react-helmet`","$0 remove 'react-{dom,helmet}'"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd),n=await gn.find(r);if(!a)throw new Dr(s.cwd,this.context.cwd);await s.restoreInstallState({restoreResolutions:!1});let l=this.all?s.workspaces:[a],f=["dependencies","devDependencies","peerDependencies"],h=[],A=!1,m=[];for(let I of this.patterns){let R=!1,N=G.parseIdent(I);for(let U of l){let V=[...U.manifest.peerDependenciesMeta.keys()];for(let ee of(0,qW.default)(V,I))U.manifest.peerDependenciesMeta.delete(ee),A=!0,R=!0;for(let ee of f){let te=U.manifest.getForScope(ee),ie=[...te.values()].map(ae=>G.stringifyIdent(ae));for(let ae of(0,qW.default)(ie,G.stringifyIdent(N))){let{identHash:ge}=G.parseIdent(ae),de=te.get(ge);if(typeof de>"u")throw new Error("Assertion failed: Expected the descriptor to be registered");U.manifest[ee].delete(ge),m.push([U,ee,de]),A=!0,R=!0}}}R||h.push(I)}let w=h.length>1?"Patterns":"Pattern",v=h.length>1?"don't":"doesn't",D=this.all?"any":"this";if(h.length>0)throw new ht(`${w} ${pe.prettyList(r,h,pe.Type.CODE)} ${v} match any packages referenced by ${D} workspace`);return A?(await r.triggerMultipleHooks(I=>I.afterWorkspaceDependencyRemoval,m),await s.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})):0}};We();We();sr();var C2e=Ae("util"),A1=class extends mt{constructor(){super(...arguments);this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["run"]]}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd);if(!a)throw new Dr(s.cwd,this.context.cwd);return(await Wt.start({configuration:r,stdout:this.context.stdout,json:this.json},async l=>{let f=a.manifest.scripts,h=Ye.sortMap(f.keys(),w=>w),A={breakLength:1/0,colors:r.get("enableColors"),maxArrayLength:2},m=h.reduce((w,v)=>Math.max(w,v.length),0);for(let[w,v]of f.entries())l.reportInfo(null,`${w.padEnd(m," ")} ${(0,C2e.inspect)(v,A)}`),l.reportJson({name:w,script:v})})).exitCode()}};We();We();sr();var p1=class extends mt{constructor(){super(...arguments);this.inspect=ye.String("--inspect",!1,{tolerateBoolean:!0,description:"Forwarded to the underlying Node process when executing a binary"});this.inspectBrk=ye.String("--inspect-brk",!1,{tolerateBoolean:!0,description:"Forwarded to the underlying Node process when executing a binary"});this.topLevel=ye.Boolean("-T,--top-level",!1,{description:"Check the root workspace for scripts and/or binaries instead of the current one"});this.binariesOnly=ye.Boolean("-B,--binaries-only",!1,{description:"Ignore any user defined scripts and only check for binaries"});this.require=ye.String("--require",{description:"Forwarded to the underlying Node process when executing a binary"});this.silent=ye.Boolean("--silent",{hidden:!0});this.scriptName=ye.String();this.args=ye.Proxy()}static{this.paths=[["run"]]}static{this.usage=At.Usage({description:"run a script defined in the package.json",details:`
This command will run a tool. The exact tool that will be executed will depend on the current state of your workspace:
- If the \`scripts\` field from your local package.json contains a matching script name, its definition will get executed.
- Otherwise, if one of the local workspace's dependencies exposes a binary with a matching name, this binary will get executed.
- Otherwise, if the specified name contains a colon character and if one of the workspaces in the project contains exactly one script with a matching name, then this script will get executed.
Whatever happens, the cwd of the spawned process will be the workspace that declares the script (which makes it possible to call commands cross-workspaces using the third syntax).
`,examples:[["Run the tests from the local workspace","$0 run test"],['Same thing, but without the "run" keyword',"$0 test"],["Inspect Webpack while running","$0 run --inspect-brk webpack"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a,locator:n}=await Yt.find(r,this.context.cwd);await s.restoreInstallState();let l=this.topLevel?s.topLevelWorkspace.anchoredLocator:n;if(!this.binariesOnly&&await qn.hasPackageScript(l,this.scriptName,{project:s}))return await qn.executePackageScript(l,this.scriptName,this.args,{project:s,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});let f=await qn.getPackageAccessibleBinaries(l,{project:s});if(f.get(this.scriptName)){let A=[];return this.inspect&&(typeof this.inspect=="string"?A.push(`--inspect=${this.inspect}`):A.push("--inspect")),this.inspectBrk&&(typeof this.inspectBrk=="string"?A.push(`--inspect-brk=${this.inspectBrk}`):A.push("--inspect-brk")),this.require&&A.push(`--require=${this.require}`),await qn.executePackageAccessibleBinary(l,this.scriptName,this.args,{cwd:this.context.cwd,project:s,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr,nodeArgs:A,packageAccessibleBinaries:f})}if(!this.topLevel&&!this.binariesOnly&&a&&this.scriptName.includes(":")){let m=(await Promise.all(s.workspaces.map(async w=>w.manifest.scripts.has(this.scriptName)?w:null))).filter(w=>w!==null);if(m.length===1)return await qn.executeWorkspaceScript(m[0],this.scriptName,this.args,{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})}if(this.topLevel)throw this.scriptName==="node-gyp"?new ht(`Couldn't find a script name "${this.scriptName}" in the top-level (used by ${G.prettyLocator(r,n)}). This typically happens because some package depends on "node-gyp" to build itself, but didn't list it in their dependencies. To fix that, please run "yarn add node-gyp" into your top-level workspace. You also can open an issue on the repository of the specified package to suggest them to use an optional peer dependency.`):new ht(`Couldn't find a script name "${this.scriptName}" in the top-level (used by ${G.prettyLocator(r,n)}).`);{if(this.scriptName==="global")throw new ht("The 'yarn global' commands have been removed in 2.x - consider using 'yarn dlx' or a third-party plugin instead");let A=[this.scriptName].concat(this.args);for(let[m,w]of RC)for(let v of w)if(A.length>=v.length&&JSON.stringify(A.slice(0,v.length))===JSON.stringify(v))throw new ht(`Couldn't find a script named "${this.scriptName}", but a matching command can be found in the ${m} plugin. You can install it with "yarn plugin import ${m}".`);throw new ht(`Couldn't find a script named "${this.scriptName}".`)}}};We();We();sr();var d1=class extends mt{constructor(){super(...arguments);this.descriptor=ye.String();this.resolution=ye.String()}static{this.paths=[["set","resolution"]]}static{this.usage=At.Usage({description:"enforce a package resolution",details:'\n This command updates the resolution table so that `descriptor` is resolved by `resolution`.\n\n Note that by default this command only affect the current resolution table - meaning that this "manual override" will disappear if you remove the lockfile, or if the package disappear from the table. If you wish to make the enforced resolution persist whatever happens, edit the `resolutions` field in your top-level manifest.\n\n Note that no attempt is made at validating that `resolution` is a valid resolution entry for `descriptor`.\n ',examples:[["Force all instances of lodash@npm:^1.2.3 to resolve to 1.5.0","$0 set resolution lodash@npm:^1.2.3 npm:1.5.0"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd),n=await gn.find(r);if(await s.restoreInstallState({restoreResolutions:!1}),!a)throw new Dr(s.cwd,this.context.cwd);let l=G.parseDescriptor(this.descriptor,!0),f=G.makeDescriptor(l,this.resolution);return s.storedDescriptors.set(l.descriptorHash,l),s.storedDescriptors.set(f.descriptorHash,f),s.resolutionAliases.set(l.descriptorHash,f.descriptorHash),await s.installWithNewReport({stdout:this.context.stdout},{cache:n})}};We();Mt();sr();var B2e=st(ma()),g1=class extends mt{constructor(){super(...arguments);this.all=ye.Boolean("-A,--all",!1,{description:"Unlink all workspaces belonging to the target project from the current one"});this.leadingArguments=ye.Rest()}static{this.paths=[["unlink"]]}static{this.usage=At.Usage({description:"disconnect the local project from another one",details:`
This command will remove any resolutions in the project-level manifest that would have been added via a yarn link with similar arguments.
`,examples:[["Unregister a remote workspace in the current project","$0 unlink ~/ts-loader"],["Unregister all workspaces from a remote project in the current project","$0 unlink ~/jest --all"],["Unregister all previously linked workspaces","$0 unlink --all"],["Unregister all workspaces matching a glob","$0 unlink '@babel/*' 'pkg-{a,b}'"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd),n=await gn.find(r);if(!a)throw new Dr(s.cwd,this.context.cwd);let l=s.topLevelWorkspace,f=new Set;if(this.leadingArguments.length===0&&this.all)for(let{pattern:h,reference:A}of l.manifest.resolutions)A.startsWith("portal:")&&f.add(h.descriptor.fullName);if(this.leadingArguments.length>0)for(let h of this.leadingArguments){let A=Y.resolve(this.context.cwd,me.toPortablePath(h));if(Ye.isPathLike(h)){let m=await $e.find(A,this.context.plugins,{useRc:!1,strict:!1}),{project:w,workspace:v}=await Yt.find(m,A);if(!v)throw new Dr(w.cwd,A);if(this.all){for(let D of w.workspaces)D.manifest.name&&f.add(G.stringifyIdent(D.anchoredLocator));if(f.size===0)throw new ht("No workspace found to be unlinked in the target project")}else{if(!v.manifest.name)throw new ht("The target workspace doesn't have a name and thus cannot be unlinked");f.add(G.stringifyIdent(v.anchoredLocator))}}else{let m=[...l.manifest.resolutions.map(({pattern:w})=>w.descriptor.fullName)];for(let w of(0,B2e.default)(m,h))f.add(w)}}return l.manifest.resolutions=l.manifest.resolutions.filter(({pattern:h})=>!f.has(h.descriptor.fullName)),await s.installWithNewReport({stdout:this.context.stdout,quiet:this.context.quiet},{cache:n})}};We();We();We();sr();var v2e=st(gD()),VW=st(ma());ga();var m1=class extends mt{constructor(){super(...arguments);this.interactive=ye.Boolean("-i,--interactive",{description:"Offer various choices, depending on the detected upgrade paths"});this.fixed=ye.Boolean("-F,--fixed",!1,{description:"Store dependency tags as-is instead of resolving them"});this.exact=ye.Boolean("-E,--exact",!1,{description:"Don't use any semver modifier on the resolved range"});this.tilde=ye.Boolean("-T,--tilde",!1,{description:"Use the `~` semver modifier on the resolved range"});this.caret=ye.Boolean("-C,--caret",!1,{description:"Use the `^` semver modifier on the resolved range"});this.recursive=ye.Boolean("-R,--recursive",!1,{description:"Resolve again ALL resolutions for those packages"});this.noTimeGate=ye.Boolean("--no-time-gate",!1,{description:"Disable the minimum release age check for this command"});this.mode=ye.String("--mode",{description:"Change what artifacts installs generate",validator:$s(uc)});this.patterns=ye.Rest()}static{this.paths=[["up"]]}static{this.usage=At.Usage({description:"upgrade dependencies across the project",details:"\n This command upgrades the packages matching the list of specified patterns to their latest available version across the whole project (regardless of whether they're part of `dependencies` or `devDependencies` - `peerDependencies` won't be affected). This is a project-wide command: all workspaces will be upgraded in the process.\n\n If `-R,--recursive` is set the command will change behavior and no other switch will be allowed. When operating under this mode `yarn up` will force all ranges matching the selected packages to be resolved again (often to the highest available versions) before being stored in the lockfile. It however won't touch your manifests anymore, so depending on your needs you might want to run both `yarn up` and `yarn up -R` to cover all bases.\n\n If `-i,--interactive` is set (or if the `preferInteractive` settings is toggled on) the command will offer various choices, depending on the detected upgrade paths. Some upgrades require this flag in order to resolve ambiguities.\n\n The, `-C,--caret`, `-E,--exact` and `-T,--tilde` options have the same meaning as in the `add` command (they change the modifier used when the range is missing or a tag, and are ignored when the range is explicitly set).\n\n If the `--mode=<mode>` option is set, Yarn will change which artifacts are generated. The modes currently supported are:\n\n - `skip-build` will not run the build scripts at all. Note that this is different from setting `enableScripts` to false because the latter will disable build scripts, and thus affect the content of the artifacts generated on disk, whereas the former will just disable the build step - but not the scripts themselves, which just won't run.\n\n - `update-lockfile` will skip the link step altogether, and only fetch packages that are missing from the lockfile (or that have no associated checksums). This mode is typically used by tools like Renovate or Dependabot to keep a lockfile up-to-date without incurring the full install cost.\n\n Generally you can see `yarn up` as a counterpart to what was `yarn upgrade --latest` in Yarn 1 (ie it ignores the ranges previously li Line truncated
${ae}`):N.reportError(27,`${G.prettyDescriptor(r,U)} can't be resolved to a satisfying range (note: network resolution has been disabled)
${ae}`)}else te.length>1&&!f&&N.reportError(27,`${G.prettyDescriptor(r,U)} has multiple possible upgrade strategies; use -i to disambiguate manually`)}});if(D.hasErrors())return D.exitCode();let I=!1,R=[];for(let[N,U,,{suggestions:V}]of v){let ee,te=V.filter(de=>de.descriptor!==null),ie=te[0].descriptor,ae=te.every(de=>G.areDescriptorsEqual(de.descriptor,ie));te.length===1||ae?ee=ie:(I=!0,{answer:ee}=await(0,v2e.prompt)({type:"select",name:"answer",message:`Which range do you want to use in ${G.prettyWorkspace(r,N)} \u276F ${U}?`,choices:V.map(({descriptor:de,name:xe,reason:we})=>de?{name:xe,hint:we,descriptor:de}:{name:xe,hint:we,disabled:!0}),onCancel:()=>process.exit(130),result(de){return this.find(de,"descriptor")},stdin:this.context.stdin,stdout:this.context.stdout}));let ge=N.manifest[U].get(ee.identHash);if(typeof ge>"u")throw new Error("Assertion failed: This descriptor should have a matching entry");if(ge.descriptorHash!==ee.descriptorHash)N.manifest[U].set(ee.identHash,ee),R.push([N,U,ge,ee]);else{let de=r.makeResolver(),xe={project:s,resolver:de},we=r.normalizeDependency(ge),d=de.bindDescriptor(we,N.anchoredLocator,xe);s.forgetResolution(d)}}return await r.triggerMultipleHooks(N=>N.afterWorkspaceDependencyReplacement,R),I&&this.context.stdout.write(`
`),await s.installWithNewReport({stdout:this.context.stdout},{cache:n,mode:this.mode})}};We();We();sr();var y1=class extends mt{constructor(){super(...arguments);this.recursive=ye.Boolean("-R,--recursive",!1,{description:"List, for each workspace, what are all the paths that lead to the dependency"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.peers=ye.Boolean("--peers",!1,{description:"Also print the peer dependencies that match the specified name"});this.package=ye.String()}static{this.paths=[["why"]]}static{this.usage=At.Usage({description:"display the reason why a package is needed",details:`
This command prints the exact reasons why a package appears in the dependency tree. Specify a version or range to determine why the dependency tree contains a specific version of a package. This is particularly useful when trying to find out why your project depends on lower versions.
If \`-R,--recursive\` is set, the listing will go in depth and will list, for each workspaces, what are all the paths that lead to the dependency. Note that the display is somewhat optimized in that it will not print the package listing twice for a single package, so if you see a leaf named "Foo" when looking for "Bar", it means that "Foo" already got printed higher in the tree.
`,examples:[["Explain why lodash is used in your project","$0 why lodash"],["Explain why version 3.3.1 of lodash is in your project","$0 why [email protected]"],["Explain why version 3.X of lodash is in your project","$0 why lodash@^3"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd);if(!a)throw new Dr(s.cwd,this.context.cwd);await s.restoreInstallState();let n=G.parseDescriptor(this.package,!1);if(n.range!=="unknown"&&zr.validRange(n.range)===null)throw new ht(`Expected a valid semver range, got ${n.range}`);let l=this.recursive?Pmt(s,n,{configuration:r,peers:this.peers}):Dmt(s,n,{configuration:r,peers:this.peers});bs.emitTree(l,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1})}};function Dmt(t,e,{configuration:r,peers:s}){let a=Ye.sortMap(t.storedPackages.values(),f=>G.stringifyLocator(f)),n={},l={children:n};for(let f of a){let h={};for(let m of f.dependencies.values()){if(!s&&WW(f,m))continue;let w=t.storedResolutions.get(m.descriptorHash);if(!w)throw new Error("Assertion failed: The resolution should have been registered");let v=t.storedPackages.get(w);if(!v)throw new Error("Assertion failed: The package should have been registered");if(!G.areIdentsEqual(v,e)||!G.isPackageInRange(v,e.range))continue;{let I=G.stringifyLocator(f);n[I]={value:[f,pe.Type.LOCATOR],children:h}}let D=G.stringifyLocator(v);h[D]={value:[{descriptor:m,locator:v},pe.Type.DEPENDENT]}}}return l}function Pmt(t,e,{configuration:r,peers:s}){let a=Ye.sortMap(t.workspaces,v=>G.stringifyLocator(v.anchoredLocator)),n=new Set,l=new Set,f=v=>{if(n.has(v.locatorHash))return l.has(v.locatorHash);if(n.add(v.locatorHash),G.areIdentsEqual(v,e)&&G.isPackageInRange(v,e.range))return l.add(v.locatorHash),!0;let D=!1;for(let I of v.dependencies.values()){if(!s&&WW(v,I))continue;let R=t.storedResolutions.get(I.descriptorHash);if(!R)throw new Error("Assertion failed: The resolution should have been registered");let N=t.storedPackages.get(R);if(!N)throw new Error("Assertion failed: The package should have been registered");f(N)&&(D=!0)}return D&&l.add(v.locatorHash),D};for(let v of a)f(v.anchoredPackage);let h=new Set,A={},m={children:A},w=(v,D,I)=>{if(!l.has(v.locatorHash))return;let R=I!==null?pe.tuple(pe.Type.DEPENDENT,{locator:v,descriptor:I}):pe.tuple(pe.Type.LOCATOR,v),N={},U={value:R,children:N},V=G.stringifyLocator(v);if(D[V]=U,!(I!==null&&t.tryWorkspaceByLocator(v))&&!h.has(v.locatorHash)){h.add(v.locatorHash);for(let ee of v.dependencies.values()){if(!s&&WW(v,ee))continue;let te=t.storedResolutions.get(ee.descriptorHash);if(!te)throw new Error("Assertion failed: The resolution should have been registered");let ie=t.storedPackages.get(te);if(!ie)throw new Error("Assertion failed: The package should have been registered");w(ie,N,ee)}}};for(let v of a)w(v.anchoredPackage,A,null);return m}function WW(t,e){return G.isVirtualLocator(t)&&t.peerDependencies.has(e.identHash)}We();var rY={};lr(rY,{GitFetcher:()=>vD,GitResolver:()=>SD,default:()=>zmt,gitUtils:()=>fc});We();Mt();var fc={};lr(fc,{TreeishProtocols:()=>BD,clone:()=>tY,fetchBase:()=>V2e,fetchChangedFiles:()=>W2e,fetchChangedWorkspaces:()=>Ymt,fetchRoot:()=>q2e,isGitUrl:()=>w1,lsRemote:()=>G2e,normalizeLocator:()=>Wmt,normalizeRepoUrl:()=>E1,resolveUrl:()=>eY,splitRepoUrl:()=>$p,validateRepoUrl:()=>$W});We();Mt();sr();xl();var H2e=st(_2e()),I1=st(Ae("querystring")),ZW=st(Di());function JW(t,e,r){let s=t.indexOf(r);return t.lastIndexOf(e,s>-1?s:1/0)}function M2e(t){try{return new URL(t)}catch{return}}function qmt(t){let e=JW(t,"@","#"),r=JW(t,":","#");return r>e&&(t=`${t.slice(0,r)}/${t.slice(r+1)}`),JW(t,":","#")===-1&&t.indexOf("//")===-1&&(t=`ssh://${t}`),t}function U2e(t){return M2e(t)||M2e(qmt(t))}function E1(t,{git:e=!1}={}){if(t=t.replace(/^git\+https:/,"https:"),t=t.replace(/^(?:github:|https:\/\/github\.com\/|git:\/\/github\.com\/)?(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)(?:\.git)?(#.*)?$/,"https://github.com/$1/$2.git$3"),t=t.replace(/^https:\/\/github\.com\/(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\/tarball\/(.+)?$/,"https://github.com/$1/$2.git#$3"),e){let r=U2e(t);r&&(t=r.href),t=t.replace(/^git\+([^:]+):/,"$1:")}return t}function j2e(){return{...process.env,GIT_SSH_COMMAND:process.env.GIT_SSH_COMMAND||`${process.env.GIT_SSH||"ssh"} -o BatchMode=yes`}}var Vmt=[/^ssh:/,/^git(?:\+[^:]+)?:/,/^(?:git\+)?https?:[^#]+\/[^#]+(?:\.git)(?:#.*)?$/,/^git@[^#]+\/[^#]+\.git(?:#.*)?$/,/^(?:github:|https:\/\/github\.com\/)?(?!\.{1,2}\/)([a-zA-Z._0-9-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z._0-9-]+?)(?:\.git)?(?:#.*)?$/,/^https:\/\/github\.com\/(?!\.{1,2}\/)([a-zA-Z0-9._-]+)\/(?!\.{1,2}(?:#|$))([a-zA-Z0-9._-]+?)\/tarball\/(.+)?$/],BD=(a=>(a.Commit="commit",a.Head="head",a.Tag="tag",a.Semver="semver",a))(BD||{});function w1(t){return t?Vmt.some(e=>!!t.match(e)):!1}function $p(t){t=E1(t);let e=t.indexOf("#");if(e===-1)return{repo:t,treeish:{pr Line truncated
This command will run a given sub-command on a single workspace.
`,examples:[["Add a package to a single workspace","yarn workspace components add -D react"],["Run build script on a single workspace","yarn workspace components run build"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd);if(!a)throw new Dr(s.cwd,this.context.cwd);let n=s.workspaces,l=new Map(n.map(h=>[G.stringifyIdent(h.anchoredLocator),h])),f=l.get(this.workspaceName);if(f===void 0){let h=Array.from(l.keys()).sort();throw new ht(`Workspace '${this.workspaceName}' not found. Did you mean any of the following:
- ${h.join(`
- `)}?`)}return this.cli.run([this.commandName,...this.args],{cwd:f.cwd})}};var Jmt={configuration:{enableImmutableInstalls:{description:"If true (the default on CI), prevents the install command from modifying the lockfile",type:"BOOLEAN",default:Y2e.isCI},defaultSemverRangePrefix:{description:"The default save prefix: '^', '~' or ''",type:"STRING",values:["^","~",""],default:"^"},preferReuse:{description:"If true, `yarn add` will attempt to reuse the most common dependency range in other workspaces.",type:"BOOLEAN",default:!1}},commands:[UC,HC,jC,GC,d1,o1,XC,C1,WC,YC,KC,zC,_C,MC,qC,VC,JC,ZC,$C,e1,t1,r1,g1,n1,i1,c1,a1,l1,s1,u1,f1,h1,A1,p1,m1,y1,B1]},Zmt=Jmt;var aY={};lr(aY,{default:()=>tyt});We();We();var iY="catalog:";var sY=t=>t.startsWith(iY),Xmt=t=>t.range.slice(iY.length)||null,K2e=t=>t===null?"default catalog":`catalog "${t}"`,$mt=t=>t.scope?`@${t.scope}/${t.name}`:t.name,oY=(t,e,r,s)=>{let a=Xmt(e),n;if(a===null)n=t.configuration.get("catalog");else try{let m=t.configuration.get("catalogs");m&&(n=m.get(a))}catch{n=void 0}if(!n||n.size===0)throw new Zt(82,`${G.prettyDescriptor(t.configuration,e)}: ${K2e(a)} not found or empty`);let l=$mt(e),f=n.get(l);if(!f)throw new Zt(82,`${G.prettyDescriptor(t.configuration,e)}: entry not found in ${K2e(a)}`);let h=t.configuration.normalizeDependency(G.makeDescriptor(e,f));return r.supportsDescriptor(h,s)?r.bindDescriptor(h,t.topLevelWorkspace.anchoredLocator,s):h};var eyt={configuration:{catalog:{description:"The default catalog of packages",type:"MAP",valueDefinition:{description:"The catalog of packages",type:"STRING"}},catalogs:{description:"Named catalogs of packages",type:"MAP",valueDefinition:{description:"A named catalog",type:"MAP",valueDefinition:{description:"Package version in the catalog",type:"STRING"}}}},hooks:{beforeWorkspacePacking:(t,e)=>{let r=t.project,s=r.configuration.makeResolver(),a={project:r,resolver:s,report:new rs};for(let n of nr.allDependencies){let l=e[n];if(l)for(let[f,h]of Object.entries(l)){if(typeof h!="string"||!sY(h))continue;let A=G.parseIdent(f),m=G.makeDescriptor(A,h),w=oY(r,m,s,a),{protocol:v,source:D,params:I,selector:R}=G.parseRange(G.convertToManifestRange(w.range));v===t.project.configuration.get("defaultProtocol")&&(v=null),l[f]=G.makeRange({protocol:v,source:D,params:I,selector:R})}}},reduceDependency:async(t,e,r,s,{resolver:a,resolveOptions:n})=>sY(t.range)?oY(e,t,a,n):t}},tyt=eyt;var hY={};lr(hY,{default:()=>nyt});We();var Ut={optional:!0},cY=[["@tailwindcss/aspect-ratio@<0.2.1",{peerDependencies:{tailwindcss:"^2.0.2"}}],["@tailwindcss/line-clamp@<0.2.1",{peerDependencies:{tailwindcss:"^2.0.2"}}],["@fullhuman/[email protected] || 3.1.3-alpha.0",{peerDependencies:{postcss:"^8.0.0"}}],["@samverschueren/stream-to-observable@<0.3.1",{peerDependenciesMeta:{rxjs:Ut,zenObservable:Ut}}],["any-observable@<0.5.1",{peerDependenciesMeta:{rxjs:Ut,zenObservable:Ut}}],["@pm2/agent@<1.0.4",{dependencies:{debug:"*"}}],["debug@<4.2.0",{peerDependenciesMeta:{"supports-color":Ut}}],["got@<11",{dependencies:{"@types/responselike":"^1.0.0","@types/keyv":"^3.1.1"}}],["cacheable-lookup@<4.1.2",{dependencies:{"@types/keyv":"^3.1.1"}}],["http-link-dataloader@*",{peerDependencies:{graphql:"^0.13.1 || ^14.0.0"}}],["typescript-language-server@*",{dependencies:{"vscode-jsonrpc":"^5.0.1","vscode-languageserver-protocol":"^3.15.0"}}],["postcss-syntax@*",{peerDependenciesMeta:{"postcss-html":Ut,"postcss-jsx":Ut,"postcss-less":Ut,"postcss-markdown":Ut,"postcss-scss":Ut}}],["jss-plugin-rule-value-function@<=10.1.1",{dependencies:{"tiny-warning":"^1.0.2"}}],["ink-select-input@<4.1.0",{peerDependencies:{react:"^16.8.2"}}],["license-webpack-plugin@<2.3.18",{peerDependenciesMeta:{webpack:Ut}}],["snowpack@>=3.3.0",{dependencies:{"node-gyp":"^7.1.0"}}],["promise-inflight@*",{peerDependenciesMeta:{bluebird:Ut}}],["reactcss@*",{peerDependencies:{react:"*"}}],["react-color@<=2.19.0",{peerDependencies:{react:"*"}}],["gatsby-plugin-i18n@*",{dependencies:{ramda:"^0.24.1"}}],["useragent@^2.0.0",{dependencies:{request:"^2.88.0",yamlparser:"0.0.x",semver:"5.5.x"}}],["@apollographql/apollo-tools@<=0.5.2",{peerDependencies:{graphql:"^14.2.1 || ^15.0.0"}}],["material-table@^2.0.0",{dependencies:{"@babel/runtime":"^7.11.2"}}],["@babel/parser@*",{dependencies:{"@babel/types":"^7.8.3"}}],["fork-ts-checker-webpack-plugin@<=6.3.4",{peerDependencies:{eslint:">= 6",typescript:">= 2.7",webpack:">= 4","vue-template-compiler":"*"},peerDependenciesMeta:{eslint:Ut,"vue-template-compiler":Ut}}],["rc-animate@<=3.1.1",{peerDependencies:{react:">=16.9.0","react-dom":">=16.9.0"}}],["react-bootstrap-table2-paginator@*",{dependencies:{classnames:"^2.2.6"}}],["react-draggable@<=4.4.3",{peerDependencies:{react:">= 16.3.0","react-dom":">= 16.3.0"}}],["apollo-upload-client@<14",{peerDependencies:{graphql:"14 - 15"}}],["react-instantsearch-core@<=6.7.0",{peerDependencies:{algoliasearch:">= 3.1 < 5"}}],["react-instantsearch-dom@<=6.7.0",{dependencies:{"react-fast-compare":"^3.0.0"}}],Line truncated
This command will output all matches to the given prolog query.
`,examples:[["List all dependencies throughout the workspace","yarn constraints query 'workspace_has_dependency(_, DependencyName, _, _).'"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(RD(),kD)),s=await $e.find(this.context.cwd,this.context.plugins),{project:a}=await Yt.find(s,this.context.cwd),n=await r.find(a),l=this.query;return l.endsWith(".")||(l=`${l}.`),(await Wt.start({configuration:s,json:this.json,stdout:this.context.stdout},async h=>{for await(let A of n.query(l)){let m=Array.from(Object.entries(A)),w=m.length,v=m.reduce((D,[I])=>Math.max(D,I.length),0);for(let D=0;D<w;D++){let[I,R]=m[D];h.reportInfo(null,`${Iyt(D,w)}${I.padEnd(v," ")} = ${Eyt(R)}`)}h.reportJson(A)}})).exitCode()}};function Eyt(t){return typeof t!="string"?`${t}`:t.match(/^[a-zA-Z][a-zA-Z0-9_]+$/)?t:`'${t}'`}function Iyt(t,e){let r=t===0,s=t===e-1;return r&&s?"":r?"\u250C ":s?"\u2514 ":"\u2502 "}We();sr();var k1=class extends mt{constructor(){super(...arguments);this.verbose=ye.Boolean("-v,--verbose",!1,{description:"Also print the fact database automatically compiled from the workspace manifests"})}static{this.paths=[["constraints","source"]]}static{this.usage=At.Usage({category:"Constraints-related commands",description:"print the source code for the constraints",details:"\n This command will print the Prolog source code used by the constraints engine. Adding the `-v,--verbose` flag will print the *full* source code, including the fact database automatically compiled from the workspace manifests.\n ",examples:[["Prints the source code","yarn constraints source"],["Print the source code and the fact database","yarn constraints source -v"]]})}async execute(){let{Constraints:r}=await Promise.resolve().then(()=>(RD(),kD)),s=await $e.find(this.context.cwd,this.context.plugins),{project:a}=await Yt.find(s,this.context.cwd),n=await r.find(a);this.context.stdout.write(this.verbose?n.fullSource:n.source)}};We();We();sr();DD();var R1=class extends mt{constructor(){super(...arguments);this.fix=ye.Boolean("--fix",!1,{description:"Attempt to automatically fix unambiguous issues, following a multi-pass process"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["constraints"]]}static{this.usage=At.Usage({category:"Constraints-related commands",description:"check that the project constraints are met",details:`
This command will run constraints on your project and emit errors for each one that is found but isn't met. If any error is emitted the process will exit with a non-zero exit code.
If the \`--fix\` flag is used, Yarn will attempt to automatically fix the issues the best it can, following a multi-pass process (with a maximum of 10 iterations). Some ambiguous patterns cannot be autofixed, in which case you'll have to manually specify the right resolution.
For more information as to how to write constraints, please consult our dedicated page on our website: https://yarnpkg.com/features/constraints.
`,examples:[["Check that all constraints are satisfied","yarn constraints"],["Autofix all unmet constraints","yarn constraints --fix"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s}=await Yt.find(r,this.context.cwd);await s.restoreInstallState();let a=await s.loadUserConfig(),n;if(a?.constraints)n=new S1(s);else{let{Constraints:A}=await Promise.resolve().then(()=>(RD(),kD));n=await A.find(s)}let l,f=!1,h=!1;for(let A=this.fix?10:1;A>0;--A){let m=await n.process();if(!m)break;let{changedWorkspaces:w,remainingErrors:v}=zO(s,m,{fix:this.fix}),D=[];for(let[I,R]of w){let N=I.manifest.indent;I.manifest=new nr,I.manifest.indent=N,I.manifest.load(R),D.push(I.persistManifest())}if(await Promise.all(D),!(w.size>0&&A>1)){l=$2e(v,{configuration:r}),f=!1,h=!0;for(let[,I]of v)for(let R of I)R.fixable?f=!0:h=!1}}if(l.children.length===0)return 0;if(f){let A=h?`Those errors can all be fixed by running ${pe.pretty(r,"yarn constraints --fix",pe.Type.CODE)}`:`Errors prefixed by '\u2699' can be fixed by running ${pe.pretty(r,"yarn constraints --fix",pe.Type.CODE)}`;await Wt.start({configuration:r,stdout:this.context.stdout,includeNames:!1,includeFooter:!1},async m=>{m.reportInfo(0,A),m.reportSeparator()})}return l.children=Ye.sortMap(l.children,A=>A.value[1]),bs.emitTree(l,{configuration:r,stdout:this.context.stdout,json:this.json,separators:1}),1}};DD();var wyt={configuration:{enableConstraintsChecks:{description:"If true, constraints will run during installs",type:"BOOLEAN",default:!1},constraintsPath:{description:"The path of the constraints file.",type:"ABSOLUTE_PATH",default:"./constraints.pro"}},commands:[x1,k1,R1],hooks:{async validateProjectAfterInstall(t,{reportError:e}){if(!t.configuration.get("enableConstraintsChecks"))return;let r=await t.loadUserConfig(),s;if(r?.constraints)s=new S1(t);else{let{Constraints:l}=await Promise.resolve().then(()=>(RD(),kD));s=await l.find(t)}let a=await s.process();if(!a)return;let{remainingErrors:n}=zO(t,a);if(n.size!==0)if(t.configuration.isCI)for(let[l,f]of n)for(let h of f)e(84,`${pe.pretty(t.configuration,l.anchoredLocator,pe.Type.IDENT)}: ${h.text}`);else e(84,`Constraint check failed; run ${pe.pretty(t.configuration,"yarn constraints",pe.Type.CODE)} for more details`)}}},Cyt=wyt;var kY={};lr(kY,{CreateCommand:()=>T1,DlxCommand:()=>Q1,default:()=>vyt});We();sr();var T1=class extends mt{constructor(){super(...arguments);this.pkg=ye.String("-p,--package",{description:"The package to run the provided command from"});this.quiet=ye.Boolean("-q,--quiet",!1,{description:"Only report critical errors instead of printing the full install logs"});this.command=ye.String();this.args=ye.Proxy()}static{this.paths=[["create"]]}async execute(){let r=[];this.pkg&&r.push("--package",this.pkg),this.quiet&&r.push("--quiet");let s=this.command.replace(/^(@[^@/]+)(@|$)/,"$1/create$2"),a=G.parseDescriptor(s),n=a.name.match(/^create(-|$)/)?a:a.scope?G.makeIdent(a.scope,`create-${a.name}`):G.makeIdent(null,`create-${a.name}`),l=G.stringifyIdent(n);return a.range!=="unknown"&&(l+=`@${a.range}`),this.cli.run(["dlx",...r,l,...this.args])}};We();We();Mt();sr();var Q1=class extends mt{constructor(){super(...arguments);this.packages=ye.Array("-p,--package",{description:"The package(s) to install before running the command"});this.quiet=ye.Boolean("-q,--quiet",!1,{description:"Only report critical errors instead of printing the full install logs"});this.command=ye.String();this.args=ye.Proxy()}static{this.paths=[["dlx"]]}static{this.usage=At.Usage({description:"run a package in a temporary environment",details:"\n This command will install a package within a temporary environment, and run its binary script if it contains any. The binary will run within the current cwd.\n\n By default Yarn will download the package named `command`, but this can be changed through the use of the `-p,--package` flag which will instruct Yarn to still run the same command but from a different package.\n\n Using `yarn dlx` as a replacement of `yarn add` isn't recommended, as it makes your project non-deterministic (Yarn doesn't keep track of the packages installed through `dlx` - neither their name, nor their version).\n ",examples:[["Use create-vite to scaffold a new Vite project","yarn dlx create-vite"],["Install multiple packages for a single command",`yarn dlx -p typescript -p ts-node ts-node --transpile-only -e "console.log('hello!')"`]]})}async execute(){return $e.telemetry=null,await fe.mktempPromise(async r=>{let s=Y.join(r,`dlx-${process.pid}`);await fe.mkdirPromise(s),await fe.writeFilePromise(Y.join(s,"package.json"),`{}
`),await fe.writeFilePromise(Y.join(s,"yarn.lock"),"");let a=Y.join(s,".yarnrc.yml"),n=await $e.findProjectCwd(this.context.cwd),f={enableGlobalCache:!(await $e.find(this.context.cwd,null,{strict:!1})).get("enableGlobalCache"),enableTelemetry:!1,logFilters:[{code:Mh(68),level:pe.LogLevel.Discard}]},h=n!==null?Y.join(n,".yarnrc.yml"):null;h!==null&&fe.existsSync(h)?(await fe.copyFilePromise(h,a),await $e.updateConfiguration(s,N=>{let U=Ye.toMerged(N,f);return Array.isArray(N.plugins)&&(U.plugins=N.plugins.map(V=>{let ee=typeof V=="string"?V:V.path,te=me.isAbsolute(ee)?ee:me.resolve(me.fromPortablePath(n),ee);return typeof V=="string"?te:{path:te,spec:V.spec}})),U})):await fe.writeJsonPromise(a,f);let A=this.packages??[this.command],m=G.parseDescriptor(this.command).name,w=await this.cli.run(["add","--fixed","--",...A],{cwd:s,quiet:this.quiet});if(w!==0)return w;this.quiet||this.context.stdout.write(`
`);let v=await $e.find(s,this.context.plugins),{project:D,workspace:I}=await Yt.find(v,s);if(I===null)throw new Dr(D.cwd,s);await D.restoreInstallState();let R=await qn.getWorkspaceAccessibleBinaries(I);return R.has(m)===!1&&R.size===1&&typeof this.packages>"u"&&(m=Array.from(R)[0][0]),await qn.executeWorkspaceAccessibleBinary(I,m,this.args,{packageAccessibleBinaries:R,cwd:this.context.cwd,stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr})})}};var Byt={commands:[T1,Q1]},vyt=Byt;var QY={};lr(QY,{ExecFetcher:()=>QD,ExecResolver:()=>FD,default:()=>Dyt,execUtils:()=>$O});We();We();We();Mt();var rA="exec:";var $O={};lr($O,{loadGeneratorFile:()=>TD,makeLocator:()=>TY,makeSpec:()=>SBe,parseSpec:()=>RY});We();Mt();function RY(t){let{params:e,selector:r}=G.parseRange(t),s=me.toPortablePath(r);return{parentLocator:e&&typeof e.locator=="string"?G.parseLocator(e.locator):null,path:s}}function SBe({parentLocator:t,path:e,generatorHash:r,protocol:s}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<"u"?{hash:r}:{};return G.makeRange({protocol:s,source:e,selector:e,params:{...n,...a}})}function TY(t,{parentLocator:e,path:r,generatorHash:s,protocol:a}){return G.makeLocator(t,SBe({parentLocator:e,path:r,generatorHash:s,protocol:a}))}async function TD(t,e,r){let{parentLocator:s,path:a}=G.parseFileStyleRange(t,{protocol:e}),n=Y.isAbsolute(a)?{packageFs:new Jn(Rt.root),prefixPath:Rt.dot,localPath:Rt.root}:await r.fetcher.fetch(s,r),l=n.localPath?{packageFs:new Jn(Rt.root),prefixPath:Y.relative(Rt.root,n.localPath)}:n;n!==l&&n.releaseFs&&n.releaseFs();let f=l.packageFs,h=Y.join(l.prefixPath,a);return await f.readFilePromise(h,"utf8")}var QD=class{supports(e,r){return!!e.reference.startsWith(rA)}getLocalPath(e,r){let{parentLocator:s,path:a}=G.parseFileStyleRange(e.reference,{protocol:rA});if(Y.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(s,r);return n===null?null:Y.resolve(n,a)}async fetch(e,r){let s=r.checksums.get(e.locatorHash)||null,[a,n,l]=await r.cache.fetchPackageFromCache(e,s,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e),loader:()=>this.fetchFromDisk(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:l}}async fetchFromDisk(e,r){let s=r.project.getDependencyMeta(e,null);if(!r.project.configuration.get("enableScripts")&&!s.built)throw new Zt(4,`${G.prettyLocator(r.project.configuration,e)} can't be built with the exec: protocol because all scripts have been disabled.`);let a=await TD(e.reference,rA,r);return fe.mktempPromise(async n=>{let l=Y.join(n,"generator.js");return await fe.writeFilePromise(l,a),fe.mktempPromise(async f=>{if(await this.generatePackage(f,e,l,r),!fe.existsSync(Y.join(f,"build")))throw new Error("The script should have generated a build directory");return await Hs.makeArchiveFromDirectory(Y.join(f,"build"),{prefixPath:G.getIdentVendorPath(e),compressionLevel:r.project.configuration.get("compressionLevel")})})})}async generatePackage(e,r,s,a){return await fe.mktempPromise(async n=>{let l=await qn.makeScriptEnv({project:a.project,binFolder:n}),f=Y.join(e,"runtime.js");return await fe.mktempPromise(async h=>{let A=Y.join(h,"buildfile.log"),m=Y.join(e,"generator"),w=Y.join(e,"build");await fe.mkdirPromise(m),await fe.mkdirPromise(w);let v={tempDir:me.fromPortablePath(m),buildDir:me.fromPortablePath(w),locator:G.stringifyLocator(r)};await fe.writeFilePromise(f,`
// Expose 'Module' as a global variable
Object.defineProperty(global, 'Module', {
get: () => require('module'),
configurable: true,
enumerable: false,
});
// Expose non-hidden built-in modules as global variables
for (const name of Module.builtinModules.filter((name) => name !== 'module' && !name.startsWith('_'))) {
Object.defineProperty(global, name, {
get: () => require(name),
configurable: true,
enumerable: false,
});
}
// Expose the 'execEnv' global variable
Object.defineProperty(global, 'execEnv', {
value: {
...${JSON.stringify(v)},
},
enumerable: true,
});
`);let D=l.NODE_OPTIONS||"",I=/\s*--require\s+\S*\.pnp\.c?js\s*/g;D=D.replace(I," ").trim(),l.NODE_OPTIONS=D;let{stdout:R,stderr:N}=a.project.configuration.getSubprocessStreams(A,{header:`# This file contains the result of Yarn generating a package (${G.stringifyLocator(r)})
`,prefix:G.prettyLocator(a.project.configuration,r),report:a.report}),{code:U}=await un.pipevp(process.execPath,["--require",me.fromPortablePath(f),me.fromPortablePath(s),G.stringifyIdent(r)],{cwd:e,env:l,stdin:null,stdout:R,stderr:N});if(U!==0)throw fe.detachTemp(h),new Error(`Package generation failed (exit code ${U}, logs can be found here: ${pe.pretty(a.project.configuration,A,pe.Type.PATH)})`)})})}};We();We();We();var Syt=2,FD=class{supportsDescriptor(e,r){return!!e.range.startsWith(rA)}supportsLocator(e,r){return!!e.reference.startsWith(rA)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,s){if(s.project.tryWorkspaceByLocator(r)===null)throw new Zt(57,`${G.prettyLocator(s.project.configuration,r)} lists ${G.prettyDescriptor(s.project.configuration,e)} as dependency, but only workspaces can depend on exec: packages.`);return G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){return{}}async getCandidates(e,r,s){if(!s.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{path:a,parentLocator:n}=RY(e.range);if(n===null)throw new Error("Assertion failed: The descriptor should have been bound");let l=await TD(G.makeRange({protocol:rA,source:a,selector:a,params:{locator:G.stringifyLocator(n)}}),rA,s.fetchOptions),f=si.makeHash(`${Syt}`,l).slice(0,6);return[TY(e,{parentLocator:n,path:a,generatorHash:f,protocol:rA})]}async getSatisfying(e,r,s,a){let[n]=await this.getCandidates(e,r,a);return{locators:s.filter(l=>l.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){if(!r.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let s=await r.fetchOptions.fetcher.fetch(e,r.fetchOptions),a=await Ye.releaseAfterUseAsync(async()=>await nr.find(s.prefixPath,{baseFs:s.packageFs}),s.releaseFs);return{...e,version:a.version||"0.0.0",languageName:a.languageName||r.project.configuration.get("defaultLanguageName"),linkType:"HARD",conditions:a.getConditions(),dependencies:r.project.configuration.normalizeDependencyMap(a.dependencies),peerDependencies:a.peerDependencies,dependenciesMeta:a.dependenciesMeta,peerDependenciesMeta:a.peerDependenciesMeta,bin:a.bin}}};var byt={fetchers:[QD],resolvers:[FD]},Dyt=byt;var NY={};lr(NY,{FileFetcher:()=>_D,FileResolver:()=>MD,TarballFileFetcher:()=>UD,TarballFileResolver:()=>HD,default:()=>kyt,fileUtils:()=>sE});We();Mt();var F1=/^(?:[a-zA-Z]:[\\/]|\.{0,2}\/)/,ND=/^[^?]*\.(?:tar\.gz|tgz)(?:::.*)?$/,Ds="file:";var sE={};lr(sE,{fetchArchiveFromLocator:()=>LD,makeArchiveFromLocator:()=>eL,makeBufferFromLocator:()=>FY,makeLocator:()=>N1,makeSpec:()=>bBe,parseSpec:()=>OD});We();Mt();function OD(t){let{params:e,selector:r}=G.parseRange(t),s=me.toPortablePath(r);return{parentLocator:e&&typeof e.locator=="string"?G.parseLocator(e.locator):null,path:s}}function bBe({parentLocator:t,path:e,hash:r,protocol:s}){let a=t!==null?{locator:G.stringifyLocator(t)}:{},n=typeof r<"u"?{hash:r}:{};return G.makeRange({protocol:s,source:e,selector:e,params:{...n,...a}})}function N1(t,{parentLocator:e,path:r,hash:s,protocol:a}){return G.makeLocator(t,bBe({parentLocator:e,path:r,hash:s,protocol:a}))}async function LD(t,e){let{parentLocator:r,path:s}=G.parseFileStyleRange(t.reference,{protocol:Ds}),a=Y.isAbsolute(s)?{packageFs:new Jn(Rt.root),prefixPath:Rt.dot,localPath:Rt.root}:await e.fetcher.fetch(r,e),n=a.localPath?{packageFs:new Jn(Rt.root),prefixPath:Y.relative(Rt.root,a.localPath)}:a;a!==n&&a.releaseFs&&a.releaseFs();let l=n.packageFs,f=Y.join(n.prefixPath,s);return await Ye.releaseAfterUseAsync(async()=>await l.readFilePromise(f),n.releaseFs)}async function eL(t,{protocol:e,fetchOptions:r,inMemory:s=!1}){let{parentLocator:a,path:n}=G.parseFileStyleRange(t.reference,{protocol:e}),l=Y.isAbsolute(n)?{packageFs:new Jn(Rt.root),prefixPath:Rt.dot,localPath:Rt.root}:await r.fetcher.fetch(a,r),f=l.localPath?{packageFs:new Jn(Rt.root),prefixPath:Y.relative(Rt.root,l.localPath)}:l;l!==f&&l.releaseFs&&l.releaseFs();let h=f.packageFs,A=Y.join(f.prefixPath,n);return await Ye.releaseAfterUseAsync(async()=>await Hs.makeArchiveFromDirectory(A,{baseFs:h,prefixPath:G.getIdentVendorPath(t),compressionLevel:r.project.configuration.get("compressionLevel"),inMemory:s}),f.releaseFs)}async function FY(t,{protocol:e,fetchOptions:r}){return(await eL(t,{protocol:e,fetchOptions:r,inMemory:!0})).getBufferAndClose()}var _D=class{supports(e,r){return!!e.reference.startsWith(Ds)}getLocalPath(e,r){let{parentLocator:s,path:a}=G.parseFileStyleRange(e.reference,{protocol:Ds});if(Y.isAbsolute(a))return a;let n=r.fetcher.getLocalPath(s,r);return n===null?null:Y.resolve(n,a)}async fetch(e,r){let s=r.checksums.get(e.locatorHash)||null,[a,n,l]=await r.cache.fetchPackageFromCache(e,s,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.fetchFro Line truncated
`,{automaticNewlines:!0});let A=[h],m=Y.join(this.context.cwd,"README.md");if(fe.existsSync(m)||(await fe.writeFilePromise(m,`# ${G.stringifyIdent(n.name)}
`),A.push(m)),!s||s.cwd===this.context.cwd){let w=Y.join(this.context.cwd,Or.lockfile);fe.existsSync(w)||(await fe.writeFilePromise(w,""),A.push(w));let D=[".yarn/*","!.yarn/patches","!.yarn/plugins","!.yarn/releases","!.yarn/sdks","!.yarn/versions","","# Whether you use PnP or not, the node_modules folder is often used to store","# build artifacts that should be gitignored","node_modules","","# Swap the comments on the following lines if you wish to use zero-installs","# In that case, don't forget to run `yarn config set enableGlobalCache false`!","# Documentation here: https://yarnpkg.com/features/caching#zero-installs","","#!.yarn/cache",".pnp.*"].map(ie=>`${ie}
`).join(""),I=Y.join(this.context.cwd,".gitignore");fe.existsSync(I)||(await fe.writeFilePromise(I,D),A.push(I));let N=["/.yarn/** linguist-vendored","/.yarn/releases/* binary","/.yarn/plugins/**/* binary","/.pnp.* binary linguist-generated"].map(ie=>`${ie}
`).join(""),U=Y.join(this.context.cwd,".gitattributes");fe.existsSync(U)||(await fe.writeFilePromise(U,N),A.push(U));let V={"*":{charset:"utf-8",endOfLine:"lf",indentSize:2,indentStyle:"space",insertFinalNewline:!0}};Ye.mergeIntoTarget(V,r.get("initEditorConfig"));let ee=`root = true
`;for(let[ie,ae]of Object.entries(V)){ee+=`
[${ie}]
`;for(let[ge,de]of Object.entries(ae)){let xe=ge.replace(/[A-Z]/g,we=>`_${we.toLowerCase()}`);ee+=`${xe} = ${de}
`}}let te=Y.join(this.context.cwd,".editorconfig");fe.existsSync(te)||(await fe.writeFilePromise(te,ee),A.push(te)),await this.cli.run(["install"],{quiet:!0}),await this.initialize(),fe.existsSync(Y.join(this.context.cwd,".git"))||(await un.execvp("git",["init"],{cwd:this.context.cwd}),await un.execvp("git",["add","--",...A],{cwd:this.context.cwd}),await un.execvp("git",["commit","--allow-empty","-m","First commit"],{cwd:this.context.cwd}))}}};var O1=class extends yg{constructor(){super(...arguments);this.initializer=ye.String();this.argv=ye.Proxy()}static{this.paths=[["init"]]}async initialize(){this.context.stdout.write(`
`),await this.cli.run(["dlx",this.initializer,...this.argv],{quiet:!0})}};var Nyt={configuration:{initScope:{description:"Scope used when creating packages via the init command",type:"STRING",default:null},initFields:{description:"Additional fields to set when creating packages via the init command",type:"MAP",valueDefinition:{description:"",type:"ANY"}},initEditorConfig:{description:"Extra rules to define in the generator editorconfig",type:"MAP",valueDefinition:{description:"",type:"ANY"}}},commands:[yg,O1]},Oyt=Nyt;var Lz={};lr(Lz,{SearchCommand:()=>e2,UpgradeInteractiveCommand:()=>t2,default:()=>W2t});We();var RBe=st(Ae("os"));function L1({stdout:t}){if(RBe.default.endianness()==="BE")throw new Error("Interactive commands cannot be used on big-endian systems because ink depends on yoga-layout-prebuilt which only supports little-endian architectures");if(!t.isTTY)throw new Error("Interactive commands can only be used inside a TTY environment")}sr();var Gve=st(iK()),sK={appId:"OFCNCOG2CU",apiKey:"6fe4476ee5a1832882e326b506d14126",indexName:"npm-search"},QIt=(0,Gve.default)(sK.appId,sK.apiKey).initIndex(sK.indexName),oK=async(t,e=0)=>await QIt.search(t,{analyticsTags:["yarn-plugin-interactive-tools"],attributesToRetrieve:["name","version","owner","repository","humanDownloadsLast30Days"],page:e,hitsPerPage:10});var GP=["regular","dev","peer"],e2=class extends mt{static{this.paths=[["search"]]}static{this.usage=At.Usage({category:"Interactive commands",description:"open the search interface",details:`
This command opens a fullscreen terminal interface where you can search for and install packages from the npm registry.
`,examples:[["Open the search window","yarn search"]]})}async execute(){L1(this.context);let{Gem:e}=await Promise.resolve().then(()=>(OL(),bz)),{ScrollableItems:r}=await Promise.resolve().then(()=>(UL(),ML)),{useKeypress:s}=await Promise.resolve().then(()=>($1(),Dz)),{useMinistore:a}=await Promise.resolve().then(()=>(Tz(),Rz)),{renderForm:n}=await Promise.resolve().then(()=>(VL(),qL)),{default:l}=await Promise.resolve().then(()=>st(PPe())),{Box:f,Text:h}=await Promise.resolve().then(()=>st(Du())),{default:A,useEffect:m,useState:w}=await Promise.resolve().then(()=>st(Ln())),v=await $e.find(this.context.cwd,this.context.plugins),D=()=>A.createElement(f,{flexDirection:"row"},A.createElement(f,{flexDirection:"column",width:48},A.createElement(f,null,A.createElement(h,null,"Press ",A.createElement(h,{bold:!0,color:"cyanBright"},"<up>"),"/",A.createElement(h,{bold:!0,color:"cyanBright"},"<down>")," to move between packages.")),A.createElement(f,null,A.createElement(h,null,"Press ",A.createElement(h,{bold:!0,color:"cyanBright"},"<space>")," to select a package.")),A.createElement(f,null,A.createElement(h,null,"Press ",A.createElement(h,{bold:!0,color:"cyanBright"},"<space>")," again to change the target."))),A.createElement(f,{flexDirection:"column"},A.createElement(f,{marginLeft:1},A.createElement(h,null,"Press ",A.createElement(h,{bold:!0,color:"cyanBright"},"<enter>")," to install the selected packages.")),A.createElement(f,{marginLeft:1},A.createElement(h,null,"Press ",A.createElement(h,{bold:!0,color:"cyanBright"},"<ctrl+c>")," to abort.")))),I=()=>A.createElement(A.Fragment,null,A.createElement(f,{width:15},A.createElement(h,{bold:!0,underline:!0,color:"gray"},"Owner")),A.createElement(f,{width:11},A.createElement(h,{bold:!0,underline:!0,color:"gray"},"Version")),A.createElement(f,{width:10},A.createElement(h,{bold:!0,underline:!0,color:"gray"},"Downloads"))),R=()=>A.createElement(f,{width:17},A.createElement(h,{bold:!0,underline:!0,color:"gray"},"Target")),N=({hit:de,active:xe})=>{let[we,d]=a(de.name,null);s({active:xe},(Ee,he)=>{if(he.name!=="space")return;if(!we){d(GP[0]);return}let $=GP.indexOf(we)+1;$===GP.length?d(null):d(GP[$])},[we,d]);let be=G.parseIdent(de.name),Ce=G.prettyIdent(v,be);return A.createElement(f,null,A.createElement(f,{width:45},A.createElement(h,{bold:!0,wrap:"wrap"},Ce)),A.createElement(f,{width:14,marginLeft:1},A.createElement(h,{bold:!0,wrap:"truncate"},de.owner.name)),A.createElement(f,{width:10,marginLeft:1},A.createElement(h,{italic:!0,wrap:"truncate"},de.version)),A.createElement(f,{width:16,marginLeft:1},A.createElement(h,null,de.humanDownloadsLast30Days)))},U=({name:de,active:xe})=>{let[we]=a(de,null),d=G.parseIdent(de);return A.createElement(f,null,A.createElement(f,{width:47},A.createElement(h,{bold:!0}," - ",G.prettyIdent(v,d))),GP.map(be=>A.createElement(f,{key:be,width:14,marginLeft:1},A.createElement(h,null," ",A.createElement(e,{active:we===be})," ",A.createElement(h,{bold:!0},be)))))},V=()=>A.createElement(f,{marginTop:1},A.createElement(h,null,"Powered by Algolia.")),te=await n(({useSubmit:de})=>{let xe=a();de(xe);let we=Array.from(xe.keys()).filter(j=>xe.get(j)!==null),[d,be]=w(""),[Ce,Ee]=w(0),[he,$]=w([]),De=j=>{j.match(/\t| /)||be(j)},Te=async()=>{Ee(0);let j=await oK(d);j.query===d&&$(j.hits)},ot=async()=>{let j=await oK(d,Ce+1);j.query===d&&j.page-1===Ce&&(Ee(j.page),$([...he,...j.hits]))};return m(()=>{d?Te():$([])},[d]),A.createElement(f,{flexDirection:"column"},A.createElement(D,null),A.createElement(f,{flexDirection:"row",marginTop:1},A.createElement(h,{bold:!0},"Search: "),A.createElement(f,{width:41},A.createElement(l,{value:d,onChange:De,placeholder:"i.e. babel, webpack, react...",showCursor:!1})),A.createElement(I,null)),he.length?A.createElement(r,{radius:2,loop:!1,children:he.map(j=>A.createElement(N,{key:j.name,hit:j,active:!1})),willReachEnd:ot}):A.createElement(h,{color:"gray"},"Start typing..."),A.createElement(f,{flexDirection:"row",marginTop:1},A.createElement(f,{width:49},A.createElement(h,{bold:!0},"Selected:")),A.createElement(R,null)),we.length?we.map(j=>A.createElement(U,{key:j,name:j,active:!1})):A.createElement(h,{color:"gray"},"No selected packages..."),A.createElement(V,null))},{},{stdin:this.context.stdin,stdout:this.context.stdout,stderr:this.context.stderr});if(typeof te>"u")return 1;let ie=Array.from(te.keys()).filter(de=>te.get(de)==="regular"),ae=Array.from(te.keys()).filter(de=>te.get(de)==="dev"),ge=Array.from(te.keys()).filter(de=>te.get(de)==="peer");return ie.length&&await this.cli.run(["add",...ie]),ae.length&&await this.cli.run(["add","--dev",...ae]),ge&&await this.cli.run(["add","--peer",...ge]),0}};We();sr();FV();var NPe=st(Di());ga();var FPe=/^((?:[\^~]|>=?)?)([0-9]+)(\.[0-9]+)(\.[0-9]+)((?:-\S+)?)$/;function OPe(t,e){return t.length>0?[t.slice(0,e)].concat(OPe(t.slice(e),e)):[]}var t2=class extends mt{constructor(){super(...arguments);this.mode=ye.String("--mode",{description:"Change what artifacts installs genera Line truncated
${m}, next tree:
${JP(f)}`);let v=UPe(f);if(v)throw new Error(`${v}, after hoisting finished:
${JP(f)}`)}return n.debugLevel>=2&&console.log(JP(f)),oBt(f)},$2t=t=>{let e=t[t.length-1],r=new Map,s=new Set,a=n=>{if(!s.has(n)){s.add(n);for(let l of n.hoistedDependencies.values())r.set(l.name,l);for(let l of n.dependencies.values())n.peerNames.has(l.name)||a(l)}};return a(e),r},eBt=t=>{let e=t[t.length-1],r=new Map,s=new Set,a=new Set,n=(l,f)=>{if(s.has(l))return;s.add(l);for(let A of l.hoistedDependencies.values())if(!f.has(A.name)){let m;for(let w of t)m=w.dependencies.get(A.name),m&&r.set(m.name,m)}let h=new Set;for(let A of l.dependencies.values())h.add(A.name);for(let A of l.dependencies.values())l.peerNames.has(A.name)||n(A,h)};return n(e,a),r},_Pe=(t,e)=>{if(e.decoupled)return e;let{name:r,references:s,ident:a,locator:n,dependencies:l,originalDependencies:f,hoistedDependencies:h,peerNames:A,reasons:m,isHoistBorder:w,hoistPriority:v,dependencyKind:D,hoistedFrom:I,hoistedTo:R}=e,N={name:r,references:new Set(s),ident:a,locator:n,dependencies:new Map(l),originalDependencies:new Map(f),hoistedDependencies:new Map(h),peerNames:new Set(A),reasons:new Map(m),decoupled:!0,isHoistBorder:w,hoistPriority:v,dependencyKind:D,hoistedFrom:new Map(I),hoistedTo:new Map(R)},U=N.dependencies.get(r);return U&&U.ident==N.ident&&N.dependencies.set(r,N),t.dependencies.set(N.name,N),N},tBt=(t,e)=>{let r=new Map([[t.name,[t.ident]]]);for(let a of t.dependencies.values())t.peerNames.has(a.name)||r.set(a.name,[a.ident]);let s=Array.from(e.keys());s.sort((a,n)=>{let l=e.get(a),f=e.get(n);if(f.hoistPriority!==l.hoistPriority)return f.hoistPriority-l.hoistPriority;{let h=l.dependents.size+l.peerDependents.size;return f.dependents.size+f.peerDependents.size-h}});for(let a of s){let n=a.substring(0,a.indexOf("@",1)),l=a.substring(n.length+1);if(!t.peerNames.has(n)){let f=r.get(n);f||(f=[],r.set(n,f)),f.indexOf(l)<0&&f.push(l)}}return r},Hz=t=>{let e=new Set,r=(s,a=new Set)=>{if(!a.has(s)){a.add(s);for(let n of s.peerNames)if(!t.peerNames.has(n)){let l=t.dependencies.get(n);l&&!e.has(l)&&r(l,a)}e.add(s)}};for(let s of t.dependencies.values())t.peerNames.has(s.name)||r(s);return e},Gz=(t,e,r,s,a,n=new Set)=>{let l=e[e.length-1];if(n.has(l))return{anotherRoundNeeded:!1,isGraphChanged:!1};n.add(l);let f=aBt(l),h=tBt(l,f),A=t==l?new Map:a.fastLookupPossible?$2t(e):eBt(e),m,w=!1,v=!1,D=new Map(Array.from(h.entries()).map(([R,N])=>[R,N[0]])),I=new Map;do{let R=iBt(t,e,r,A,D,h,s,I,a);R.isGraphChanged&&(v=!0),R.anotherRoundNeeded&&(w=!0),m=!1;for(let[N,U]of h)U.length>1&&!l.dependencies.has(N)&&(D.delete(N),U.shift(),D.set(N,U[0]),m=!0)}while(m);for(let R of l.dependencies.values())if(!l.peerNames.has(R.name)&&!r.has(R.locator)){r.add(R.locator);let N=Gz(t,[...e,R],r,I,a);N.isGraphChanged&&(v=!0),N.anotherRoundNeeded&&(w=!0),r.delete(R.locator)}return{anotherRoundNeeded:w,isGraphChanged:v}},rBt=t=>{for(let[e,r]of t.dependencies)if(!t.peerNames.has(e)&&r.ident!==t.ident)return!0;return!1},nBt=(t,e,r,s,a,n,l,f,{outputReason:h,fastLookupPossible:A})=>{let m,w=null,v=new Set;h&&(m=`${Array.from(e).map(N=>Yo(N)).join("\u2192")}`);let D=r[r.length-1],R=!(s.ident===D.ident);if(h&&!R&&(w="- self-reference"),R&&(R=s.dependencyKind!==1,h&&!R&&(w="- workspace")),R&&s.dependencyKind===2&&(R=!rBt(s),h&&!R&&(w="- external soft link with unhoisted dependencies")),R&&(R=!t.peerNames.has(s.name),h&&!R&&(w=`- cannot shadow peer: ${Yo(t.originalDependencies.get(s.name).locator)} at ${m}`)),R){let N=!1,U=a.get(s.name);if(N=!U||U.ident===s.ident,h&&!N&&(w=`- filled by: ${Yo(U.locator)} at ${m}`),N)for(let V=r.length-1;V>=1;V--){let te=r[V].dependencies.get(s.name);if(te&&te.ident!==s.ident){N=!1;let ie=f.get(D);ie||(ie=new Set,f.set(D,ie)),ie.add(s.name),h&&(w=`- filled by ${Yo(te.locator)} at ${r.slice(0,V).map(ae=>Yo(ae.locator)).join("\u2192")}`);break}}R=N}if(R&&(R=n.get(s.name)===s.ident,h&&!R&&(w=`- filled by: ${Yo(l.get(s.name)[0])} at ${m}`)),R){let N=!0,U=new Set(s.peerNames);for(let V=r.length-1;V>=1;V--){let ee=r[V];for(let te of U){if(ee.peerNames.has(te)&&ee.originalDependencies.has(te))continue;let ie=ee.dependencies.get(te);ie&&t.dependencies.get(te)!==ie&&(V===r.length-1?v.add(ie):(v=null,N=!1,h&&(w=`- peer dependency ${Yo(ie.locator)} from parent ${Yo(ee.locator)} was not hoisted to ${m}`))),U.delete(te)}if(!N)break}R=N}if(R&&!A)for(let N of s.hoistedDependencies.values()){let U=a.get(N.name)||t.dependencies.get(N.name);if(!U||N.ident!==U.ident){R=!1,h&&(w=`- previously hoisted dependency mismatch, needed: ${Yo(N.locator)}, available: ${Yo(U?.locator)}`);break}}return v!==null&&v.size>0?{isHoistable:2,dependsOn:v,reason:w}:{isHoistable:R?0:1,reason:w}},KL=t=>`${t.name}@${t.locator}`,iBt=(t,e,r,s,a,n,l,f,h)=>{let A=e[e.length-1],m=new Set,w=!1,v=!1,D=(U,V,ee,te,ie)=>{if(m.has(te))return;let ae=[...V,KL(te)],ge=[...ee,KL(te)],de=new Map,xe=new Map;for(let Ee of Hz(te)){let he=nBt(A,r,[A,...U,te],Ee,s,a,n,f,{outputReason:h.debugLevel>=2,fastLookupPossible:h.fastLookupPossible});if(xe.set(Ee,he),he.isHoistable===2)for(let $ of he.dependsOn){let Line truncated
${JP(t)}`)}let Ce=Hz(te);for(let Ee of Ce)if(we.has(Ee)){let he=xe.get(Ee);if((a.get(Ee.name)===Ee.ident||!te.reasons.has(Ee.name))&&he.isHoistable!==0&&te.reasons.set(Ee.name,he.reason),!Ee.isHoistBorder&&ge.indexOf(KL(Ee))<0){m.add(te);let De=_Pe(te,Ee);D([...U,te],ae,ge,De,R),m.delete(te)}}},I,R=new Set(Hz(A)),N=Array.from(e).map(U=>KL(U));do{I=R,R=new Set;for(let U of I){if(U.locator===A.locator||U.isHoistBorder)continue;let V=_Pe(A,U);D([],Array.from(r),N,V,R)}}while(R.size>0);return{anotherRoundNeeded:w,isGraphChanged:v}},UPe=t=>{let e=[],r=new Set,s=new Set,a=(n,l,f)=>{if(r.has(n)||(r.add(n),s.has(n)))return;let h=new Map(l);for(let A of n.dependencies.values())n.peerNames.has(A.name)||h.set(A.name,A);for(let A of n.originalDependencies.values()){let m=h.get(A.name),w=()=>`${Array.from(s).concat([n]).map(v=>Yo(v.locator)).join("\u2192")}`;if(n.peerNames.has(A.name)){let v=l.get(A.name);(v!==m||!v||v.ident!==A.ident)&&e.push(`${w()} - broken peer promise: expected ${A.ident} but found ${v&&v.ident}`)}else{let v=f.hoistedFrom.get(n.name),D=n.hoistedTo.get(A.name),I=`${v?` hoisted from ${v.join(", ")}`:""}`,R=`${D?` hoisted to ${D}`:""}`,N=`${w()}${I}`;m?m.ident!==A.ident&&e.push(`${N} - broken require promise for ${A.name}${R}: expected ${A.ident}, but found: ${m.ident}`):e.push(`${N} - broken require promise: no required dependency ${A.name}${R} found`)}}s.add(n);for(let A of n.dependencies.values())n.peerNames.has(A.name)||a(A,h,n);s.delete(n)};return a(t,t.dependencies,t),e.join(`
`)},sBt=(t,e)=>{let{identName:r,name:s,reference:a,peerNames:n}=t,l={name:s,references:new Set([a]),locator:jz(r,a),ident:LPe(r,a),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(n),reasons:new Map,decoupled:!0,isHoistBorder:!0,hoistPriority:0,dependencyKind:1,hoistedFrom:new Map,hoistedTo:new Map},f=new Map([[t,l]]),h=(A,m)=>{let w=f.get(A),v=!!w;if(!w){let{name:D,identName:I,reference:R,peerNames:N,hoistPriority:U,dependencyKind:V}=A;w={name:D,references:new Set([R]),locator:jz(I,R),ident:LPe(I,R),dependencies:new Map,originalDependencies:new Map,hoistedDependencies:new Map,peerNames:new Set(N),reasons:new Map,decoupled:!0,isHoistBorder:!1,hoistPriority:U||0,dependencyKind:V||0,hoistedFrom:new Map,hoistedTo:new Map},f.set(A,w)}if(!w.isHoistBorder&&e.hoistingLimits.get(m.locator)?.has(A.name)&&(w.isHoistBorder=!0),m.dependencies.set(A.name,w),m.originalDependencies.set(A.name,w),v){let D=new Set,I=R=>{if(!D.has(R)){D.add(R),R.decoupled=!1;for(let N of R.dependencies.values())R.peerNames.has(N.name)||I(N)}};I(w)}else for(let D of A.dependencies)h(D,w)};for(let A of t.dependencies)h(A,l);return l},qz=t=>t.substring(0,t.indexOf("@",1)),oBt=t=>{let e={name:t.name,identName:qz(t.locator),references:new Set(t.references),dependencies:new Set},r=new Set([t]),s=(a,n,l)=>{let f=r.has(a),h;if(n===a)h=l;else{let{name:A,references:m,locator:w}=a;h={name:A,identName:qz(w),references:m,dependencies:new Set}}if(l.dependencies.add(h),!f){r.add(a);for(let A of a.dependencies.values())a.peerNames.has(A.name)||s(A,a,h);r.delete(a)}};for(let a of t.dependencies.values())s(a,t,e);return e},aBt=t=>{let e=new Map,r=new Set([t]),s=l=>`${l.name}@${l.ident}`,a=l=>{let f=s(l),h=e.get(f);return h||(h={dependents:new Set,peerDependents:new Set,hoistPriority:0},e.set(f,h)),h},n=(l,f)=>{let h=!!r.has(f);if(a(f).dependents.add(l.ident),!h){r.add(f);for(let m of f.dependencies.values()){let w=a(m);w.hoistPriority=Math.max(w.hoistPriority,m.hoistPriority),f.peerNames.has(m.name)?w.peerDependents.add(f.ident):n(f,m)}}};for(let l of t.dependencies.values())t.peerNames.has(l.name)||n(t,l);return e},Yo=t=>{if(!t)return"none";let e=t.indexOf("@",1),r=t.substring(0,e);r.endsWith("$wsroot$")&&(r=`wh:${r.replace("$wsroot$","")}`);let s=t.substring(e+1);if(s==="workspace:.")return".";if(s){let a=(s.indexOf("#")>0?s.split("#")[1]:s).replace("npm:","");return s.startsWith("virtual")&&(r=`v:${r}`),a.startsWith("workspace")&&(r=`w:${r}`,a=""),`${r}${a?`@${a}`:""}`}else return`${r}`};var JP=t=>{let e=0,r=(a,n,l="")=>{if(e>5e4||n.has(a))return"";e++;let f=Array.from(a.dependencies.values()).sort((A,m)=>A.name===m.name?0:A.name>m.name?1:-1),h="";n.add(a);for(let A=0;A<f.length;A++){let m=f[A];if(!a.peerNames.has(m.name)&&m!==a){let w=a.reasons.get(m.name),v=qz(m.locator);h+=`${l}${A<f.length-1?"\u251C\u2500":"\u2514\u2500"}${(n.has(m)?">":"")+(v!==m.name?`a:${m.name}:`:"")+Yo(m.locator)+(w?` ${w}`:"")}
`,h+=r(m,n,`${l}${A<f.length-1?"\u2502 ":" "}`)}}return n.delete(a),h};return r(t,new Set)+(e>5e4?`
Tree is too large, part of the tree has been dunped
`:"")};var ZP=(s=>(s.WORKSPACES="workspaces",s.DEPENDENCIES="dependencies",s.NONE="none",s))(ZP||{}),HPe="node_modules",vg="$wsroot$";var XP=(t,e)=>{let{packageTree:r,hoistingLimits:s,errors:a,preserveSymlinksRequired:n}=lBt(t,e),l=null;if(a.length===0){let f=MPe(r,{hoistingLimits:s});l=fBt(t,f,e)}return{tree:l,errors:a,preserveSymlinksRequired:n}},oA=t=>`${t.name}@${t.reference}`,Wz=t=>{let e=new Map;for(let[r,s]of t.entries())if(!s.dirList){let a=e.get(s.locator);a||(a={target:s.target,linkType:s.linkType,locations:[],aliases:s.aliases},e.set(s.locator,a)),a.locations.push(r)}for(let r of e.values())r.locations=r.locations.sort((s,a)=>{let n=s.split(Y.delimiter).length,l=a.split(Y.delimiter).length;return a===s?0:n!==l?l-n:a>s?1:-1});return e},jPe=(t,e)=>{let r=G.isVirtualLocator(t)?G.devirtualizeLocator(t):t,s=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e;return G.areLocatorsEqual(r,s)},Vz=(t,e,r,s)=>{if(t.linkType!=="SOFT")return!1;let a=me.toPortablePath(r.resolveVirtual&&e.reference&&e.reference.startsWith("virtual:")?r.resolveVirtual(t.packageLocation):t.packageLocation);return Y.contains(s,a)===null},cBt=t=>{let e=t.getPackageInformation(t.topLevel);if(e===null)throw new Error("Assertion failed: Expected the top-level package to have been registered");if(t.findPackageLocator(e.packageLocation)===null)throw new Error("Assertion failed: Expected the top-level package to have a physical locator");let s=me.toPortablePath(e.packageLocation.slice(0,-1)),a=new Map,n={children:new Map},l=t.getDependencyTreeRoots(),f=new Map,h=new Set,A=(v,D)=>{let I=oA(v);if(h.has(I))return;h.add(I);let R=t.getPackageInformation(v);if(R){let N=D?oA(D):"";if(oA(v)!==N&&R.linkType==="SOFT"&&!v.reference.startsWith("link:")&&!Vz(R,v,t,s)){let U=GPe(R,v,t);(!f.get(U)||v.reference.startsWith("workspace:"))&&f.set(U,v)}for(let[U,V]of R.packageDependencies)V!==null&&(R.packagePeers.has(U)||A(t.getLocator(U,V),v))}};for(let v of l)A(v,null);let m=s.split(Y.sep);for(let v of f.values()){let D=t.getPackageInformation(v),R=me.toPortablePath(D.packageLocation.slice(0,-1)).split(Y.sep).slice(m.length),N=n;for(let U of R){let V=N.children.get(U);V||(V={children:new Map},N.children.set(U,V)),N=V}N.workspaceLocator=v}let w=(v,D)=>{if(v.workspaceLocator){let I=oA(D),R=a.get(I);R||(R=new Set,a.set(I,R)),R.add(v.workspaceLocator)}for(let I of v.children.values())w(I,v.workspaceLocator||D)};for(let v of n.children.values())w(v,n.workspaceLocator);return a},lBt=(t,e)=>{let r=[],s=!1,a=new Map,n=cBt(t),l=t.getPackageInformation(t.topLevel);if(l===null)throw new Error("Assertion failed: Expected the top-level package to have been registered");let f=t.findPackageLocator(l.packageLocation);if(f===null)throw new Error("Assertion failed: Expected the top-level package to have a physical locator");let h=me.toPortablePath(l.packageLocation.slice(0,-1)),A={name:f.name,identName:f.name,reference:f.reference,peerNames:l.packagePeers,dependencies:new Set,dependencyKind:1},m=new Map,w=(D,I)=>`${oA(I)}:${D}`,v=(D,I,R,N,U,V,ee,te)=>{let ie=w(D,R),ae=m.get(ie),ge=!!ae;!ge&&R.name===f.name&&R.reference===f.reference&&(ae=A,m.set(ie,A));let de=Vz(I,R,t,h);if(!ae){let Ee=0;de?Ee=2:I.linkType==="SOFT"&&R.name.endsWith(vg)&&(Ee=1),ae={name:D,identName:R.name,reference:R.reference,dependencies:new Set,peerNames:Ee===1?new Set:I.packagePeers,dependencyKind:Ee},m.set(ie,ae)}let xe;if(de?xe=2:U.linkType==="SOFT"?xe=1:xe=0,ae.hoistPriority=Math.max(ae.hoistPriority||0,xe),te&&!de){let Ee=oA({name:N.identName,reference:N.reference}),he=a.get(Ee)||new Set;a.set(Ee,he),he.add(ae.name)}let we=new Map(I.packageDependencies);if(e.project){let Ee=e.project.workspacesByCwd.get(me.toPortablePath(I.packageLocation.slice(0,-1)));if(Ee){let he=new Set([...Array.from(Ee.manifest.peerDependencies.values(),$=>G.stringifyIdent($)),...Array.from(Ee.manifest.peerDependenciesMeta.keys())]);for(let $ of he)we.has($)||(we.set($,V.get($)||null),ae.peerNames.add($))}}let d=oA({name:R.name.replace(vg,""),reference:R.reference}),be=n.get(d);if(be)for(let Ee of be)we.set(`${Ee.name}${vg}`,Ee.reference);(I!==U||I.linkType!=="SOFT"||!de&&(!e.selfReferencesByCwd||e.selfReferencesByCwd.get(ee)))&&N.dependencies.add(ae);let Ce=R!==f&&I.linkType==="SOFT"&&!R.name.endsWith(vg)&&!de;if(!ge&&!Ce){let Ee=new Map;for(let[he,$]of we)if($!==null){let De=t.getLocator(he,$),Te=t.getLocator(he.replace(vg,""),$),ot=t.getPackageInformation(Te);if(ot===null)throw new Error("Assertion failed: Expected the package to have been registered");let j=Vz(ot,De,t,h);if(e.validateExternalSoftLinks&&e.project&&j){ot.packageDependencies.size>0&&(s=!0);for(let[He,Qe]of ot.packageDependencies)if(Qe!==null){let ft=G.parseLocator(Array.isArray(Qe)?`${Qe[0]}@${Qe[1]}`:`${He}@${Qe}`);if(oA(ft)!==oA(De)){let Me=we.get(He);if(Me){let x=G.parseLocator(Array.isArray(Me)?`${Me[0]}@${Me[1]}`:`${He}@${Me}`);jPe(x,ft)||r.push({messageName:71,text:`Cannot link ${G.prettyIdent(e.project.configuration,G.parseIdent(De.name))} into ${G.pretLine truncated
`;for(let n=0,l=t.length;n<l;++n)a+=s+zL(String(n),t[n],e,s).replace(/^ +/,""),n+1<l&&(a+=","),a+=`
`;return a+=r,a+="]",a}function CBt(t,e,r){let s=Object.keys(t),a="";a+="{";for(let n=0,l=s.length,f=0;n<l;++n){let h=s[n],A=t[h];typeof A>"u"||(f!==0&&(a+=", "),a+=JSON.stringify(h),a+=": ",a+=zL(h,A,e,r).replace(/^ +/g,""),f+=1)}return a+="}",a}function BBt(t,e,r){let s=Object.keys(t),a=`${r} `,n="";n+=r,n+=`{
`;let l=0;for(let f=0,h=s.length;f<h;++f){let A=s[f],m=t[A];typeof m>"u"||(l!==0&&(n+=",",n+=`
`),n+=a,n+=JSON.stringify(A),n+=": ",n+=zL(A,m,e,a).replace(/^ +/g,""),l+=1)}return l!==0&&(n+=`
`),n+=r,n+="}",n}function zL(t,e,r,s){let{next:a}=WPe[r],n=a[t]||a["*"];return YPe(e,n,s)}function YPe(t,e,r){let{collapsed:s}=WPe[e];return Array.isArray(t)?s?IBt(t,e,r):wBt(t,e,r):typeof t=="object"&&t!==null?s?CBt(t,e,r):BBt(t,e,r):JSON.stringify(t)}function KPe(t){return YPe(t,"TOP_LEVEL","")}function $P(t,e){let r=Array.from(t);Array.isArray(e)||(e=[e]);let s=[];for(let n of e)s.push(r.map(l=>n(l)));let a=r.map((n,l)=>l);return a.sort((n,l)=>{for(let f of s){let h=f[n]<f[l]?-1:f[n]>f[l]?1:0;if(h!==0)return h}return 0}),a.map(n=>r[n])}function vBt(t){let e=new Map,r=$P(t.fallbackExclusionList||[],[({name:s,reference:a})=>s,({name:s,reference:a})=>a]);for(let{name:s,reference:a}of r){let n=e.get(s);typeof n>"u"&&e.set(s,n=new Set),n.add(a)}return Array.from(e).map(([s,a])=>[s,Array.from(a)])}function SBt(t){return $P(t.fallbackPool||[],([e])=>e)}function bBt(t){let e=[],r=t.dependencyTreeRoots.find(s=>t.packageRegistry.get(s.name)?.get(s.reference)?.packageLocation==="./");for(let[s,a]of $P(t.packageRegistry,([n])=>n===null?"0":`1${n}`)){if(s===null)continue;let n=[];e.push([s,n]);for(let[l,{packageLocation:f,packageDependencies:h,packagePeers:A,linkType:m,discardFromLookup:w}]of $P(a,([v])=>v===null?"0":`1${v}`)){if(l===null)continue;let v=[];s!==null&&l!==null&&!h.has(s)&&v.push([s,l]);for(let[U,V]of h)v.push([U,V]);let D=$P(v,([U])=>U),I=A&&A.size>0?Array.from(A):void 0,N={packageLocation:f,packageDependencies:D,packagePeers:I,linkType:m,discardFromLookup:w||void 0};n.push([l,N]),r&&s===r.name&&l===r.reference&&e.unshift([null,[[null,N]]])}}return e}function ex(t){return{__info:["This file is automatically generated. Do not touch it, or risk","your modifications being lost."],dependencyTreeRoots:t.dependencyTreeRoots,enableTopLevelFallback:t.enableTopLevelFallback||!1,ignorePatternData:t.ignorePattern||null,pnpZipBackend:t.pnpZipBackend,fallbackExclusionList:vBt(t),fallbackPool:SBt(t),packageRegistryData:bBt(t)}}var ZPe=st(JPe());function XPe(t,e){return[t?`${t}
`:"",`/* eslint-disable */
`,`// @ts-nocheck
`,`"use strict";
`,`
`,e,`
`,(0,ZPe.default)()].join("")}function DBt(t){return JSON.stringify(t,null,2)}function PBt(t){return`'${t.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/\n/g,`\\
`)}'`}function xBt(t){return[`const RAW_RUNTIME_STATE =
`,`${PBt(KPe(t))};
`,`function $$SETUP_STATE(hydrateRuntimeState, basePath) {
`,` return hydrateRuntimeState(JSON.parse(RAW_RUNTIME_STATE), {basePath: basePath || __dirname});
`,`}
`].join("")}function kBt(){return[`function $$SETUP_STATE(hydrateRuntimeState, basePath) {
`,` const fs = require('fs');
`,` const path = require('path');
`,` const pnpDataFilepath = path.resolve(__dirname, ${JSON.stringify(Or.pnpData)});
`,` return hydrateRuntimeState(JSON.parse(fs.readFileSync(pnpDataFilepath, 'utf8')), {basePath: basePath || __dirname});
`,`}
`].join("")}function $Pe(t){let e=ex(t),r=xBt(e);return XPe(t.shebang,r)}function exe(t){let e=ex(t),r=kBt(),s=XPe(t.shebang,r);return{dataFile:DBt(e),loaderFile:s}}Mt();function Jz(t,{basePath:e}){let r=me.toPortablePath(e),s=Y.resolve(r),a=t.ignorePatternData!==null?new RegExp(t.ignorePatternData):null,n=new Map,l=new Map(t.packageRegistryData.map(([w,v])=>[w,new Map(v.map(([D,I])=>{if(w===null!=(D===null))throw new Error("Assertion failed: The name and reference should be null, or neither should");let R=I.discardFromLookup??!1,N={name:w,reference:D},U=n.get(I.packageLocation);U?(U.discardFromLookup=U.discardFromLookup&&R,R||(U.locator=N)):n.set(I.packageLocation,{locator:N,discardFromLookup:R});let V=null;return[D,{packageDependencies:new Map(I.packageDependencies),packagePeers:new Set(I.packagePeers),linkType:I.linkType,discardFromLookup:R,get packageLocation(){return V||(V=Y.join(s,I.packageLocation))}}]}))])),f=new Map(t.fallbackExclusionList.map(([w,v])=>[w,new Set(v)])),h=new Map(t.fallbackPool),A=t.dependencyTreeRoots,m=t.enableTopLevelFallback;return{basePath:r,dependencyTreeRoots:A,enableTopLevelFallback:m,fallbackExclusionList:f,pnpZipBackend:t.pnpZipBackend,fallbackPool:h,ignorePattern:a,packageLocatorsByLocations:n,packageRegistry:l}}Mt();Mt();var ad=Ae("module"),yE=Ae("url"),aJ=Ae("util");var Da=Ae("url");var ixe=st(Ae("assert"));var Zz=Array.isArray,tx=JSON.stringify,rx=Object.getOwnPropertyNames,mE=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),Xz=(t,e)=>RegExp.prototype.exec.call(t,e),$z=(t,...e)=>RegExp.prototype[Symbol.replace].apply(t,e),Sg=(t,...e)=>String.prototype.endsWith.apply(t,e),eJ=(t,...e)=>String.prototype.includes.apply(t,e),tJ=(t,...e)=>String.prototype.lastIndexOf.apply(t,e),nx=(t,...e)=>String.prototype.indexOf.apply(t,e),txe=(t,...e)=>String.prototype.replace.apply(t,e),bg=(t,...e)=>String.prototype.slice.apply(t,e),aA=(t,...e)=>String.prototype.startsWith.apply(t,e),rxe=Map,nxe=JSON.parse;function ix(t,e,r){return class extends r{constructor(...s){super(e(...s)),this.code=t,this.name=`${r.name} [${t}]`}}}var sxe=ix("ERR_PACKAGE_IMPORT_NOT_DEFINED",(t,e,r)=>`Package import specifier "${t}" is not defined${e?` in package ${e}package.json`:""} imported from ${r}`,TypeError),rJ=ix("ERR_INVALID_MODULE_SPECIFIER",(t,e,r=void 0)=>`Invalid module "${t}" ${e}${r?` imported from ${r}`:""}`,TypeError),oxe=ix("ERR_INVALID_PACKAGE_TARGET",(t,e,r,s=!1,a=void 0)=>{let n=typeof r=="string"&&!s&&r.length&&!aA(r,"./");return e==="."?((0,ixe.default)(s===!1),`Invalid "exports" main target ${tx(r)} defined in the package config ${t}package.json${a?` imported from ${a}`:""}${n?'; targets must start with "./"':""}`):`Invalid "${s?"imports":"exports"}" target ${tx(r)} defined for '${e}' in the package config ${t}package.json${a?` imported from ${a}`:""}${n?'; targets must start with "./"':""}`},Error),sx=ix("ERR_INVALID_PACKAGE_CONFIG",(t,e,r)=>`Invalid package config ${t}${e?` while importing ${e}`:""}${r?`. ${r}`:""}`,Error),axe=ix("ERR_PACKAGE_PATH_NOT_EXPORTED",(t,e,r=void 0)=>e==="."?`No "exports" main defined in ${t}package.json${r?` imported from ${r}`:""}`:`Package subpath '${e}' is not defined by "exports" in ${t}package.json${r?` imported from ${r}`:""}`,Error);var ZL=Ae("url");function cxe(t,e){let r=Object.create(null);for(let s=0;s<e.length;s++){let a=e[s];mE(t,a)&&(r[a]=t[a])}return r}var JL=new rxe;function RBt(t,e,r,s){let a=JL.get(t);if(a!==void 0)return a;let n=s(t);if(n===void 0){let D={pjsonPath:t,exists:!1,main:void 0,name:void 0,type:"none",exports:void 0,imports:void 0};return JL.set(t,D),D}let l;try{l=nxe(n)}catch(D){throw new sx(t,(r?`"${e}" from `:"")+(0,ZL.fileURLToPath)(r||e),D.message)}let{imports:f,main:h,name:A,type:m}=cxe(l,["imports","main","name","type"]),w=mE(l,"exports")?l.exports:void 0;(typeof f!="object"||f===null)&&(f=void 0),typeof h!="string"&&(h=void 0),typeof A!="string"&&(A=void 0),m!=="module"&&m!=="commonjs"&&(m="none");let v={pjsonPath:t,exists:!0,main:h,name:A,type:m,exports:w,imports:f};return JL.set(t,v),v}function lxe(t,e){let r=new URL("./package.json",t);for(;;){let n=r.pathname;if(Sg(n,"node_modules/package.json"))break;let l=RBt((0,ZL.fileURLToPath)(r),t,void 0,e);if(l.exists)return l;let f=r;if(r=new URL("../package.json",r),r.pathname===f.pathname)break}let s=(0,ZL.fileURLToPath)(r),a={pjsonPath:s,exists:!1,main:void 0,name:void 0,type:"none",exports:void 0,imports:void 0};return JL.set(s,a),a}function TBt(t,e,r){throw new sxe(t,e&&(0,Da.fileURLToPath)(new URL(".",e)),(0,Da.fileURLToPath)(r))}function QBt(t,e,r,s){let a=`request is not a valid subpath for the "${r?"imports":"exports"}" resolution of ${(0,Da.fileURLToPath)(e)}`;throw new rJ(t,a,s&&(0,Da.fileURLToPath)(s))}function ox(t,e,r,s,a){throw typeof e=="object"&&e!==null?e=tx(e,null,""):e=`${e}`,new oxe((0,Da.fileURLToPath)(new URL(".",r)),t,e,s,a&&(0,Da.fileURLToPath)(a))}var uxe=/(^|\\|\/)((\.|%2e)(\.|%2e)?|(n|%6e|%4e)(o|%6f|%4f)(d|%64|%44)(e|%65|%45)(_|%5f)(m|%6d|%4d)(o|%6f Line truncated
`),r;l=t[++n]}else if(l===" "&&!s){a=!0;continue}else if(l==='"'){s=!s;continue}a?(r.push(l),a=!1):r[r.length-1]+=l}return s&&e.push(`invalid value for NODE_OPTIONS (unterminated string)
`),r}Mt();var[vo,Xc,jBt]=process.versions.node.split(".").map(t=>parseInt(t,10)),wxe=vo>19||vo===19&&Xc>=2||vo===18&&Xc>=13,Dgr=vo===20&&Xc<6||vo===19&&Xc>=3,Pgr=vo>19||vo===19&&Xc>=6,xgr=vo>=21||vo===20&&Xc>=10||vo===18&&Xc>=19,kgr=vo>=21||vo===20&&Xc>=10||vo===18&&Xc>=20,Rgr=vo>=22,Tgr=vo===26&&Xc<1||vo===25&&Xc>=7||vo===24&&Xc===15||vo===22&&(Xc>22||Xc===22&&jBt>=3);function oJ(t){if(process.env.WATCH_REPORT_DEPENDENCIES&&process.send){let e=t.map(r=>me.fromPortablePath(Mo.resolveVirtual(r)));if(wxe)process.send({"watch:require":e});else for(let r of e)process.send({"watch:require":r})}}function cJ(t,e){let r=Number(process.env.PNP_ALWAYS_WARN_ON_FALLBACK)>0,s=Number(process.env.PNP_DEBUG_LEVEL),a=/^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:node:)?(?:@[^/]+\/)?[^/]+)\/*(.*|)$/,n=/^(\/|\.{1,2}(\/|$))/,l=/\/$/,f=/^\.{0,2}\//,h={name:null,reference:null},A=[],m=new Set;if(t.enableTopLevelFallback===!0&&A.push(h),e.compatibilityMode!==!1)for(let Ne of["react-scripts","gatsby"]){let Fe=t.packageRegistry.get(Ne);if(Fe)for(let Pe of Fe.keys()){if(Pe===null)throw new Error("Assertion failed: This reference shouldn't be null");A.push({name:Ne,reference:Pe})}}let{ignorePattern:w,packageRegistry:v,packageLocatorsByLocations:D}=t;function I(Ne,Fe){return{fn:Ne,args:Fe,error:null,result:null}}function R(Ne){let Fe=process.stderr?.hasColors?.()??process.stdout.isTTY,Pe=(ft,Me)=>`\x1B[${ft}m${Me}\x1B[0m`,He=Ne.error;console.error(He?Pe("31;1",`\u2716 ${Ne.error?.message.replace(/\n.*/s,"")}`):Pe("33;1","\u203C Resolution")),Ne.args.length>0&&console.error();for(let ft of Ne.args)console.error(` ${Pe("37;1","In \u2190")} ${(0,aJ.inspect)(ft,{colors:Fe,compact:!0})}`);Ne.result&&(console.error(),console.error(` ${Pe("37;1","Out \u2192")} ${(0,aJ.inspect)(Ne.result,{colors:Fe,compact:!0})}`));let Qe=new Error().stack.match(/(?<=^ +)at.*/gm)?.slice(2)??[];if(Qe.length>0){console.error();for(let ft of Qe)console.error(` ${Pe("38;5;244",ft)}`)}console.error()}function N(Ne,Fe){if(e.allowDebug===!1)return Fe;if(Number.isFinite(s)){if(s>=2)return(...Pe)=>{let He=I(Ne,Pe);try{return He.result=Fe(...Pe)}catch(Qe){throw He.error=Qe}finally{R(He)}};if(s>=1)return(...Pe)=>{try{return Fe(...Pe)}catch(He){let Qe=I(Ne,Pe);throw Qe.error=He,R(Qe),He}}}return Fe}function U(Ne){let Fe=d(Ne);if(!Fe)throw Gs("INTERNAL","Couldn't find a matching entry in the dependency tree for the specified parent (this is probably an internal error)");return Fe}function V(Ne){if(Ne.name===null)return!0;for(let Fe of t.dependencyTreeRoots)if(Fe.name===Ne.name&&Fe.reference===Ne.reference)return!0;return!1}let ee=new Set(["node","require",...Ixe("--conditions")]);function te(Ne,Fe=ee,Pe){let He=Ee(Y.join(Ne,"internal.js"),{resolveIgnored:!0,includeDiscardFromLookup:!0});if(He===null)throw Gs("INTERNAL",`The locator that owns the "${Ne}" path can't be found inside the dependency tree (this is probably an internal error)`);let{packageLocation:Qe}=U(He),ft=Y.join(Qe,Or.manifest);if(!e.fakeFs.existsSync(ft))return null;let Me=JSON.parse(e.fakeFs.readFileSync(ft,"utf8"));if(Me.exports==null)return null;let x=Y.contains(Qe,Ne);if(x===null)throw Gs("INTERNAL","unqualifiedPath doesn't contain the packageLocation (this is probably an internal error)");x!=="."&&!f.test(x)&&(x=`./${x}`);try{let C=pxe({packageJSONUrl:(0,yE.pathToFileURL)(me.fromPortablePath(ft)),packageSubpath:x,exports:Me.exports,base:Pe?(0,yE.pathToFileURL)(me.fromPortablePath(Pe)):null,conditions:Fe});return me.toPortablePath((0,yE.fileURLToPath)(C))}catch(C){throw Gs("EXPORTS_RESOLUTION_FAILED",C.message,{unqualifiedPath:Xf(Ne),locator:He,pkgJson:Me,subpath:Xf(x),conditions:Fe},C.code)}}function ie(Ne,Fe,{extensions:Pe}){let He;try{Fe.push(Ne),He=e.fakeFs.statSync(Ne)}catch{}if(He&&!He.isDirectory())return e.fakeFs.realpathSync(Ne);if(He&&He.isDirectory()){let Qe;try{Qe=JSON.parse(e.fakeFs.readFileSync(Y.join(Ne,Or.manifest),"utf8"))}catch{}let ft;if(Qe&&Qe.main&&(ft=Y.resolve(Ne,Qe.main)),ft&&ft!==Ne){let Me=ie(ft,Fe,{extensions:Pe});if(Me!==null)return Me}}for(let Qe=0,ft=Pe.length;Qe<ft;Qe++){let Me=`${Ne}${Pe[Qe]}`;if(Fe.push(Me),e.fakeFs.existsSync(Me))return Me}if(He&&He.isDirectory())for(let Qe=0,ft=Pe.length;Qe<ft;Qe++){let Me=Y.format({dir:Ne,name:"index",ext:Pe[Qe]});if(Fe.push(Me),e.fakeFs.existsSync(Me))return Me}return null}function ae(Ne){let Fe=new ad.Module(Ne,null);return Fe.filename=Ne,Fe.paths=ad.Module._nodeModulePaths(Ne),Fe}function ge(Ne,Fe){return Fe.endsWith("/")&&(Fe=Y.join(Fe,"internal.js")),ad.Module._resolveFilename(me.fromPortablePath(Ne),ae(me.fromPortablePath(Fe)),!1,{plugnplay:!1})}function de(Ne){if(w===null)return!1;let Fe=Y.contains(t.basePath,Ne);return Fe===null?!1:!!w.test(Fe.replace(/\/$/,""))}let xe={std:3,resolveVirtual:1,getAllLocators:1},we=h;function d({name:Ne,reference:Fe}){let Pe=v.get(Ne);if(!Pe)return null;let He=Pe.get(Fe);return He||null}function be({name:Ne,reference:Fe}){let Pe=[];for(let[He,Qe]of v)if(He!==null)for(let[ft,Me]of Qe)ft===nulLine truncated
Require request: "${He}"
Required by: ${Qe}
`,{request:He,issuer:Qe});return me.toPortablePath(x)}let ft,Me=Ne.match(a);if(Me){if(!Fe)throw Gs("API_ERROR","The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute",{request:He,issuer:Qe});let[,x,C]=Me,P=Ee(Fe);if(!P){let Le=ge(Ne,Fe);if(Le===!1)throw Gs("BUILTIN_NODE_RESOLUTION_FAILED",`The builtin node resolution algorithm was unable to resolve the requested module (it didn't go through the pnp resolver because the issuer doesn't seem to be part of the Yarn-managed dependency tree).
Require path: "${He}"
Required by: ${Qe}
`,{request:He,issuer:Qe});return me.toPortablePath(Le)}let F=U(P).packageDependencies.get(x),Z=null;if(F==null&&P.name!==null){let Le=t.fallbackExclusionList.get(P.name);if(!Le||!Le.has(P.reference)){for(let St=0,er=A.length;St<er;++St){let Ht=U(A[St]).packageDependencies.get(x);if(Ht!=null){r?Z=Ht:F=Ht;break}}if(t.enableTopLevelFallback&&F==null&&Z===null){let St=t.fallbackPool.get(x);St!=null&&(Z=St)}}}let X=null;if(F===null)if(V(P))X=Gs("MISSING_PEER_DEPENDENCY",`Your application tried to access ${x} (a peer dependency); this isn't allowed as there is no ancestor to satisfy the requirement. Use a devDependency if needed.
Required package: ${x}${x!==He?` (via "${He}")`:""}
Required by: ${Qe}
`,{request:He,issuer:Qe,dependencyName:x});else{let Le=Ce(x,P);Le.every(pt=>V(pt))?X=Gs("MISSING_PEER_DEPENDENCY",`${P.name} tried to access ${x} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound.
Required package: ${x}${x!==He?` (via "${He}")`:""}
Required by: ${P.name}@${P.reference} (via ${Qe})
${Le.map(pt=>`Ancestor breaking the chain: ${pt.name}@${pt.reference}
`).join("")}
`,{request:He,issuer:Qe,issuerLocator:Object.assign({},P),dependencyName:x,brokenAncestors:Le}):X=Gs("MISSING_PEER_DEPENDENCY",`${P.name} tried to access ${x} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound.
Required package: ${x}${x!==He?` (via "${He}")`:""}
Required by: ${P.name}@${P.reference} (via ${Qe})
${Le.map(pt=>`Ancestor breaking the chain: ${pt.name}@${pt.reference}
`).join("")}
`,{request:He,issuer:Qe,issuerLocator:Object.assign({},P),dependencyName:x,brokenAncestors:Le})}else F===void 0&&(!Pe&&(0,ad.isBuiltin)(Ne)?V(P)?X=Gs("UNDECLARED_DEPENDENCY",`Your application tried to access ${x}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${x} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound.
Required package: ${x}${x!==He?` (via "${He}")`:""}
Required by: ${Qe}
`,{request:He,issuer:Qe,dependencyName:x}):X=Gs("UNDECLARED_DEPENDENCY",`${P.name} tried to access ${x}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since ${x} isn't otherwise declared in ${P.name}'s dependencies, this makes the require call ambiguous and unsound.
Required package: ${x}${x!==He?` (via "${He}")`:""}
Required by: ${Qe}
`,{request:He,issuer:Qe,issuerLocator:Object.assign({},P),dependencyName:x}):V(P)?X=Gs("UNDECLARED_DEPENDENCY",`Your application tried to access ${x}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.
Required package: ${x}${x!==He?` (via "${He}")`:""}
Required by: ${Qe}
`,{request:He,issuer:Qe,dependencyName:x}):X=Gs("UNDECLARED_DEPENDENCY",`${P.name} tried to access ${x}, but it isn't declared in its dependencies; this makes the require call ambiguous and unsound.
Required package: ${x}${x!==He?` (via "${He}")`:""}
Required by: ${P.name}@${P.reference} (via ${Qe})
`,{request:He,issuer:Qe,issuerLocator:Object.assign({},P),dependencyName:x}));if(F==null){if(Z===null||X===null)throw X||new Error("Assertion failed: Expected an error to have been set");F=Z;let Le=X.message.replace(/\n.*/g,"");X.message=Le,!m.has(Le)&&s!==0&&(m.add(Le),process.emitWarning(X))}let re=Array.isArray(F)?{name:F[0],reference:F[1]}:{name:x,reference:F},ce=U(re);if(!ce.packageLocation)throw Gs("MISSING_DEPENDENCY",`A dependency seems valid but didn't get installed for some reason. This might be caused by a partial install, such as dev vs prod.
Required package: ${re.name}@${re.reference}${re.name!==He?` (via "${He}")`:""}
Required by: ${P.name}@${P.reference} (via ${Qe})
`,{request:He,issuer:Qe,dependencyLocator:Object.assign({},re)});let ke=ce.packageLocation;C?ft=Y.join(ke,C):ft=ke}else if(Y.isAbsolute(Ne))ft=Y.normalize(Ne);else{if(!Fe)throw Gs("API_ERROR","The resolveToUnqualified function must be called with a valid issuer when the path isn't a builtin nor absolute",{request:He,issuer:Qe});let x=Y.resolve(Fe);Fe.match(l)?ft=Y.normalize(Y.join(x,Ne)):ft=Y.normalize(Y.join(Y.dirname(x),Ne))}return Y.normalize(ft)}function De(Ne,Fe,Pe=ee,He){if(n.test(Ne))return Fe;let Qe=te(Fe,Pe,He);return Qe?Y.normalize(Qe):Fe}function Te(Ne,{extensions:Fe=Object.keys(ad.Module._extensions)}={}){let Pe=[],He=ie(Ne,Pe,{extensions:Fe});if(He)return oJ([He]),Y.normalize(He);{oJ(Pe);let Qe=Xf(Ne),ft=Ee(Ne);if(ft){let{packageLocation:Me}=U(ft),x=!0;try{e.fakeFs.accessSync(Me)}catch(C){if(C?.code==="ENOENT")x=!1;else{let P=(C?.message??C??"empty exception thrown").replace(/^[A-Z]/,E=>E.toLowerCase());throw Gs("QUALIFIED_PATH_RESOLUTION_FAILED",`Required package exists but could not be accessed (${P}).
Missing package: ${ft.name}@${ft.reference}
Expected package location: ${Xf(Me)}
`,{unqualifiedPath:Qe,extensions:Fe})}}if(!x){let C=Me.includes("/unplugged/")?"Required unplugged package missing from disk. This may happen when switching branches without running installs (unplugged packages must be fully materialized on disk to work).":"Required package missing from disk. If you keep your packages inside your repository then restarting the Node process may be enough. Otherwise, try to run an install first.";throw Gs("QUALIFIED_PATH_RESOLUTION_FAILED",`${C}
Missing package: ${ft.name}@${ft.reference}
Expected package location: ${Xf(Me)}
`,{unqualifiedPath:Qe,extensions:Fe})}}throw Gs("QUALIFIED_PATH_RESOLUTION_FAILED",`Qualified path resolution failed: we looked for the following paths, but none could be accessed.
Source path: ${Qe}
${Pe.map(Me=>`Not found: ${Xf(Me)}
`).join("")}`,{unqualifiedPath:Qe,extensions:Fe})}}function ot(Ne,Fe,Pe){if(!Fe)throw new Error("Assertion failed: An issuer is required to resolve private import mappings");let He=dxe({name:Ne,base:(0,yE.pathToFileURL)(me.fromPortablePath(Fe)),conditions:Pe.conditions??ee,readFileSyncFn:he});if(He instanceof URL)return Te(me.toPortablePath((0,yE.fileURLToPath)(He)),{extensions:Pe.extensions});if(He.startsWith("#"))throw new Error("Mapping from one private import to another isn't allowed");return j(He,Fe,Pe)}function j(Ne,Fe,Pe={}){try{if(Ne.startsWith("#"))return ot(Ne,Fe,Pe);let{considerBuiltins:He,extensions:Qe,conditions:ft}=Pe,Me=$(Ne,Fe,{considerBuiltins:He});if(Ne==="pnpapi")return Me;if(Me===null)return null;let x=()=>Fe!==null?de(Fe):!1,C=(!He||!(0,ad.isBuiltin)(Ne))&&!x()?De(Ne,Me,ft,Fe):Me;return Te(C,{extensions:Qe})}catch(He){throw Object.hasOwn(He,"pnpCode")&&Object.assign(He.data,{request:Xf(Ne),issuer:Fe&&Xf(Fe)}),He}}function rt(Ne){let Fe=Y.normalize(Ne),Pe=Mo.resolveVirtual(Fe);return Pe!==Fe?Pe:null}return{VERSIONS:xe,topLevel:we,getLocator:(Ne,Fe)=>Array.isArray(Fe)?{name:Fe[0],reference:Fe[1]}:{name:Ne,reference:Fe},getDependencyTreeRoots:()=>[...t.dependencyTreeRoots],getAllLocators(){let Ne=[];for(let[Fe,Pe]of v)for(let He of Pe.keys())Fe!==null&&He!==null&&Ne.push({name:Fe,reference:He});return Ne},getPackageInformation:Ne=>{let Fe=d(Ne);if(Fe===null)return null;let Pe=me.fromPortablePath(Fe.packageLocation);return{...Fe,packageLocation:Pe}},findPackageLocator:Ne=>Ee(me.toPortablePath(Ne)),resolveToUnqualified:N("resolveToUnqualified",(Ne,Fe,Pe)=>{let He=Fe!==null?me.toPortablePath(Fe):null,Qe=$(me.toPortablePath(Ne),He,Pe);return Qe===null?null:me.fromPortablePath(Qe)}),resolveUnqualified:N("resolveUnqualified",(Ne,Fe)=>me.fromPortablePath(Te(me.toPortablePath(Ne),Fe))),resolveRequest:N("resolveRequest",(Ne,Fe,Pe)=>{let He=Fe!==null?me.toPortablePath(Fe):null,Qe=j(me.toPortablePath(Ne),He,Pe);return Qe===null?null:me.fromPortablePath(Qe)}),resolveVirtual:N("resolveVirtual",Ne=>{let Fe=rt(me.toPortablePath(Ne));return Fe!==null?me.fromPortablePath(Fe):null})}}Mt();var Cxe=(t,e,r)=>{let s=ex(t),a=Jz(s,{basePath:e}),n=me.join(e,Or.pnpCjs);return cJ(a,{fakeFs:r,pnpapiResolution:n})};var uJ=st(vxe());sr();var cA={};lr(cA,{checkManifestCompatibility:()=>Sxe,extractBuildRequest:()=>XL,getExtractHint:()=>fJ,hasBindingGyp:()=>hJ});We();Mt();function Sxe(t){return G.isPackageCompatible(t,us.getArchitectureSet())}function XL(t,e,r,{configuration:s}){let a=[];for(let n of["preinstall","install","postinstall"])e.manifest.scripts.has(n)&&a.push({type:0,script:n});return!e.manifest.scripts.has("install")&&e.misc.hasBindingGyp&&a.push({type:1,script:"node-gyp rebuild"}),a.length===0?null:t.linkType!=="HARD"?{skipped:!0,explain:n=>n.reportWarningOnce(6,`${G.prettyLocator(s,t)} lists build scripts, but is referenced through a soft link. Soft links don't support build scripts, so they'll be ignored.`)}:r&&r.built===!1?{skipped:!0,explain:n=>n.reportInfoOnce(5,`${G.prettyLocator(s,t)} lists build scripts, but its build has been explicitly disabled through configuration.`)}:!s.get("enableScripts")&&!r.built?{skipped:!0,explain:n=>n.reportWarningOnce(4,`${G.prettyLocator(s,t)} lists build scripts, but all build scripts have been disabled.`)}:Sxe(t)?{skipped:!1,directives:a}:{skipped:!0,explain:n=>n.reportWarningOnce(76,`${G.prettyLocator(s,t)} The ${us.getArchitectureName()} architecture is incompatible with this package, build skipped.`)}}var qBt=new Set([".exe",".bin",".h",".hh",".hpp",".c",".cc",".cpp",".java",".jar",".node"]);function fJ(t){return t.packageFs.getExtractHint({relevantExtensions:qBt})}function hJ(t){let e=Y.join(t.prefixPath,"binding.gyp");return t.packageFs.existsSync(e)}var lx={};lr(lx,{getUnpluggedPath:()=>cx});We();Mt();function cx(t,{configuration:e}){return Y.resolve(e.get("pnpUnpluggedFolder"),G.slugifyLocator(t))}var VBt=new Set([G.makeIdent(null,"open").identHash,G.makeIdent(null,"opn").identHash]),Dg=class{constructor(){this.mode="strict";this.pnpCache=new Map}getCustomDataKey(){return JSON.stringify({name:"PnpLinker",version:2})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the PnP linker to be enabled");let s=Pg(r.project).cjs;if(!fe.existsSync(s))throw new ht(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let a=Ye.getFactoryWithDefault(this.pnpCache,s,()=>Ye.dynamicRequire(s,{cachingStrategy:Ye.CachingStrategy.FsTime})),n={name:G.stringifyIdent(e),reference:e.reference},l=a.getPackageInformation(n);if(!l)throw new ht(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed PnP map - running an install might help`);return me.toPortablePath(l.packageLocation)}async findPackageLocator(e,r){if(!this.isEnabled(r))return nullLine truncated
`,n+=`# cause your node_modules installation to become invalidated.
`,n+=`
`,n+=`__metadata:
`,n+=` version: ${_xe}
`,n+=` nmMode: ${s.value}
`;let l=Array.from(e.keys()).sort(),f=G.stringifyLocator(t.topLevelWorkspace.anchoredLocator);for(let m of l){let w=e.get(m);n+=`
`,n+=`${JSON.stringify(m)}:
`,n+=` locations:
`;for(let v of w.locations){let D=Y.contains(t.cwd,v);if(D===null)throw new Error(`Assertion failed: Expected the path to be within the project (${v})`);n+=` - ${JSON.stringify(D)}
`}if(w.aliases.length>0){n+=` aliases:
`;for(let v of w.aliases)n+=` - ${JSON.stringify(v)}
`}if(m===f&&r.size>0){n+=` bin:
`;for(let[v,D]of r){let I=Y.contains(t.cwd,v);if(I===null)throw new Error(`Assertion failed: Expected the path to be within the project (${v})`);n+=` ${JSON.stringify(I)}:
`;for(let[R,N]of D){let U=Y.relative(Y.join(v,Vi),N);n+=` ${JSON.stringify(R)}: ${JSON.stringify(U)}
`}}}}let h=t.cwd,A=Y.join(h,Vi,BJ);try{a&&await fe.removePromise(A),await fe.changeFilePromise(A,n,{automaticNewlines:!0})}finally{dvt(t)}}async function yvt(t){let e=t.cwd,r=Y.join(e,Vi,BJ);try{let s=await fe.statPromise(r);return`${s.mtimeMs}:${s.size}`}catch{return null}}async function Mxe(t,{unrollAliases:e=!1}={}){let r=t.cwd,s=Y.join(r,Vi,BJ),a;try{a=await fe.statPromise(s)}catch{}if(!a)return null;let n=Fs(await fe.readFilePromise(s,"utf8"));if(n.__metadata.version>_xe)return null;let l=n.__metadata.nmMode||"classic",f=new Map,h=new Map;delete n.__metadata;for(let[A,m]of Object.entries(n)){let w=m.locations.map(D=>Y.join(r,D)),v=m.bin;if(v)for(let[D,I]of Object.entries(v)){let R=Y.join(r,me.toPortablePath(D)),N=Ye.getMapWithDefault(h,R);for(let[U,V]of Object.entries(I))N.set(U,me.toPortablePath([R,Vi,V].join(Y.sep)))}if(f.set(A,{target:Rt.dot,linkType:"HARD",locations:w,aliases:m.aliases||[]}),e&&m.aliases)for(let D of m.aliases){let{scope:I,name:R}=G.parseLocator(A),N=G.makeLocator(G.makeIdent(I,R),D),U=G.stringifyLocator(N);f.set(U,{target:Rt.dot,linkType:"HARD",locations:w,aliases:[]})}}return{locatorMap:f,binSymlinks:h,locationTree:Uxe(f,{skipPrefix:t.cwd}),nmMode:l,mtimeMs:a.mtimeMs}}var a2=async(t,e)=>{if(t.split(Y.sep).indexOf(Vi)<0)throw new Error(`Assertion failed: trying to remove dir that doesn't contain node_modules: ${t}`);try{let r;if(!e.innerLoop&&(r=await fe.lstatPromise(t),!r.isDirectory()&&!r.isSymbolicLink()||r.isSymbolicLink()&&!e.isWorkspaceDir)){await fe.unlinkPromise(t);return}let s=await fe.readdirPromise(t,{withFileTypes:!0});for(let n of s){let l=Y.join(t,n.name);n.isDirectory()?(n.name!==Vi||e&&e.innerLoop)&&await a2(l,{innerLoop:!0,contentsOnly:!1}):await fe.unlinkPromise(l)}let a=!e.innerLoop&&e.isWorkspaceDir&&r?.isSymbolicLink();!e.contentsOnly&&!a&&await fe.rmdirPromise(t)}catch(r){if(r.code!=="ENOENT"&&r.code!=="ENOTEMPTY")throw r}},Fxe=4,r_=(t,{skipPrefix:e})=>{let r=Y.contains(e,t);if(r===null)throw new Error(`Assertion failed: Writing attempt prevented to ${t} which is outside project root: ${e}`);let s=r.split(Y.sep).filter(h=>h!==""),a=s.indexOf(Vi),n=s.slice(0,a).join(Y.sep),l=Y.join(e,n),f=s.slice(a);return{locationRoot:l,segments:f}},Uxe=(t,{skipPrefix:e})=>{let r=new Map;if(t===null)return r;let s=()=>({children:new Map,linkType:"HARD"});for(let[a,n]of t.entries()){if(n.linkType==="SOFT"&&Y.contains(e,n.target)!==null){let f=Ye.getFactoryWithDefault(r,n.target,s);f.locator=a,f.linkType=n.linkType}for(let l of n.locations){let{locationRoot:f,segments:h}=r_(l,{skipPrefix:e}),A=Ye.getFactoryWithDefault(r,f,s);for(let m=0;m<h.length;++m){let w=h[m];if(w!=="."){let v=Ye.getFactoryWithDefault(A.children,w,s);A.children.set(w,v),A=v}m===h.length-1&&(A.locator=a,A.linkType=n.linkType)}}}return r},SJ=async(t,e,r)=>{if(process.platform==="win32"&&r==="junctions"){let s;try{s=await fe.lstatPromise(t)}catch{}if(!s||s.isDirectory()){await fe.symlinkPromise(t,e,"junction");return}}await fe.symlinkPromise(Y.relative(Y.dirname(e),t),e)};async function Hxe(t,e,r){let s=Y.join(t,`${CJ.default.randomBytes(16).toString("hex")}.tmp`);try{await fe.writeFilePromise(s,r);try{await fe.linkPromise(s,e)}catch{}}finally{await fe.unlinkPromise(s)}}async function Evt({srcPath:t,dstPath:e,entry:r,globalHardlinksStore:s,baseFs:a,nmMode:n}){if(r.kind==="file"){if(n.value==="hardlinks-global"&&s&&r.digest){let f=Y.join(s,r.digest.substring(0,2),`${r.digest.substring(2)}.dat`),h;try{let A=await fe.statPromise(f);if(A&&(!r.mtimeMs||A.mtimeMs>r.mtimeMs||A.mtimeMs<r.mtimeMs-pvt))if(await si.checksumFile(f,{baseFs:fe,algorithm:"sha1"})!==r.digest){let w=Y.join(s,`${CJ.default.randomBytes(16).toString("hex")}.tmp`);await fe.renamePromise(f,w);let v=await a.readFilePromise(t);await fe.writeFilePromise(w,v);try{await fe.linkPromise(w,f),r.mtimeMs=new Date().getTime(),await fe.unlinkPromise(w)}catch{}}else r.mtimeMs||(r.mtimeMs=Math.ceil(A.mtimeMs));await fe.linkPromise(f,e),h=!0}catch{h=!1}if(!h){let A=await a.readFilePromise(t);await Hxe(s,f,A),r.mtimeMs=new Date().getTime();try{await fe.linkPromise(f,e)}catch(m){m&&m.code&&m.code=="EXDEV"&&(n.value="hardlinks-local",await a.copyFilePromise(t,e))}}}else await a.copyFilePromise(t,e);let l=r.mode&511;l!==420&&await fe.chmodPromise(e,l)}}var Ivt=async(t,e,{baseFs:r,globalHardlinksStore:s,nmMode:a,windowsLinkType:n,packageChecksum:l})=>{await fe.mkdirPromise(t,{recursive:!0});let f=async(m=Rt.dot)=>{let w=Y.join(e,m),v=await r.readdirPromise(w,{withFileTypes:!0}),D=new Map;for(let I of v){let R=Y.join(m,I.name),N,U=Y.join(w,I.name);if(I.isFile()){if(N={kind:"file",mode:(await r.lstatPromise(U)).mode},a.value==="hardlinks-global"){let V=await si.checksumFile(U,{baseFs:r,algorithm:"sha1"});N.digest=V}}else if(I.isDirectory())N={kind:"directory"};else if(I.isSymbolicLink())N={kind:"symlink",symlinkTo:await r.readlinkPromise(U)};else throw new Error(`Unsupported file type (file: ${U}, mode: 0o${await r.statSync(U).mode.toString(8).padStart(6,"0")})`);if(D. Line truncated
`)),process.env.YARN_IS_TEST_ENV)return process.env.YARN_INJECT_NPM_2FA_TOKEN||"";if(!process.stdin.isTTY)throw new Zt(33,"The registry requires additional authentication, but Yarn is not running in an interactive terminal");let{otp:s}=await(0,kJ.prompt)({type:"password",name:"otp",message:"One-time password:",required:!0,onCancel:()=>process.exit(130)});return process.stdout.write(`
`),s}function s_(t){if(t.originalError?.name!=="HTTPError")return!1;try{return(t.originalError?.response.headers["www-authenticate"].split(/,\s*/).map(r=>r.toLowerCase())).includes("otp")}catch{return!1}}function u2(t){return{"npm-otp":t}}async function Yvt(t,{configuration:e,ident:r}){let s=null;if(process.env.GITLAB_CI)s=process.env.NPM_ID_TOKEN||null;else if(process.env.CIRCLECI)s=process.env.NPM_ID_TOKEN||null;else if(process.env.GITHUB_ACTIONS){if(!(process.env.ACTIONS_ID_TOKEN_REQUEST_URL&&process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN))return null;let a=`npm:${new URL(t).host.replace("registry.yarnpkg.com","registry.npmjs.org").replace("yarn.npmjs.org","registry.npmjs.org")}`,n=new URL(process.env.ACTIONS_ID_TOKEN_REQUEST_URL);n.searchParams.append("audience",a),s=(await Sn.get(n.href,{configuration:e,jsonResponse:!0,headers:{Authorization:`Bearer ${process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN}`}})).value}if(!s)return null;try{return(await Sn.post(`${t}/-/npm/v1/oidc/token/exchange/package${Ax(r)}`,null,{configuration:e,jsonResponse:!0,headers:{Authorization:`Bearer ${s}`}})).token||null}catch{}return null}var dx=class{supports(e,r){if(!e.reference.startsWith(Ci))return!1;let{selector:s,params:a}=G.parseRange(e.reference);return!(!Zxe.default.valid(s)||a===null||typeof a.__archiveUrl!="string")}getLocalPath(e,r){return null}async fetch(e,r){let s=r.checksums.get(e.locatorHash)||null,[a,n,l]=await r.cache.fetchPackageFromCache(e,s,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote server`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:l}}async fetchFromNetwork(e,r){let{params:s}=G.parseRange(e.reference);if(s===null||typeof s.__archiveUrl!="string")throw new Error("Assertion failed: The archiveUrl querystring parameter should have been available");let a=await wE(s.__archiveUrl,{customErrorMessage:IE,configuration:r.project.configuration,ident:e});return await Hs.convertToZip(a,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}};We();var gx=class{supportsDescriptor(e,r){return!(!e.range.startsWith(Ci)||!G.tryParseDescriptor(e.range.slice(Ci.length),!0))}supportsLocator(e,r){return!1}shouldPersistResolution(e,r){throw new Error("Unreachable")}bindDescriptor(e,r,s){return e}getResolutionDependencies(e,r){let s=r.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Ci.length),!0));return r.resolver.getResolutionDependencies(s,r)}async getCandidates(e,r,s){let a=s.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Ci.length),!0));return await s.resolver.getCandidates(a,r,s)}async getSatisfying(e,r,s,a){let n=a.project.configuration.normalizeDependency(G.parseDescriptor(e.range.slice(Ci.length),!0));return a.resolver.getSatisfying(n,r,s,a)}resolve(e,r){throw new Error("Unreachable")}};We();We();var Xxe=st(Di());var cd=class t{supports(e,r){if(!e.reference.startsWith(Ci))return!1;let s=new URL(e.reference);return!(!Xxe.default.valid(s.pathname)||s.searchParams.has("__archiveUrl"))}getLocalPath(e,r){return null}async fetch(e,r){let s=r.checksums.get(e.locatorHash)||null,[a,n,l]=await r.cache.fetchPackageFromCache(e,s,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the remote registry`),loader:()=>this.fetchFromNetwork(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),checksum:l}}async fetchFromNetwork(e,r){let s;try{s=await wE(t.getLocatorUrl(e),{customErrorMessage:IE,configuration:r.project.configuration,ident:e})}catch{s=await wE(t.getLocatorUrl(e).replace(/%2f/g,"/"),{customErrorMessage:IE,configuration:r.project.configuration,ident:e})}return await Hs.convertToZip(s,{configuration:r.project.configuration,prefixPath:G.getIdentVendorPath(e),stripComponents:1})}static isConventionalTarballUrl(e,r,{configuration:s}){let a=c2(e.scope,{configuration:s}),n=t.getLocatorUrl(e);return r=r.replace(/^https?:(\/\/(?:[^/]+\.)?npmjs.org(?:$|\/))/,"https:$1"),a=a.replace(/^https:\/\/registry\.npmjs\.org($|\/)/,"https://registry.yarnpkg.com$1"),r=r.replace(/^https:\/\/registry\.npmjs\.org($|\/)/,"https://registry.yarnpkg.com$1"),r===a+n||r===a+n.replace(/%2f/g,"/")}static getLocatorUrl(e){let r=zr.clean(e.reference.slice(Ci.length));if(r===null)throw new Zt(10,"The npm semver resolver got selected, but the version isn't semver");let s=encodeURIComponent(e.name),a=encodeURIComponent(r);return`${Ax(e)}/-/${s}-${a}.tgz`}};We();We();We();var a_=st(Di());var o_=G.makeIdent(null,"node-gyp"),Kvt=/\b(node-gyp|prebuild-install)\b/;function $xe(t,e){let r=a=>Ye.mapAndFilter(e,n=>{try{let l=new zr.SemVer(n);if(a.test(l))return l}catch{}return Ye.mapAndFilter.skip}),sLine truncated
https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html`);r={_type:n5t,subject:t,predicateType:s5t,predicate:{buildType:`${l5t}/${u5t}`,builder:{id:`${Ot.CI_PROJECT_URL}/-/runners/${Ot.CI_RUNNER_ID}`},invocation:{configSource:{uri:`git+${Ot.CI_PROJECT_URL}`,digest:{sha1:Ot.CI_COMMIT_SHA},entryPoint:Ot.CI_JOB_NAME},parameters:{CI:Ot.CI,CI_API_GRAPHQL_URL:Ot.CI_API_GRAPHQL_URL,CI_API_V4_URL:Ot.CI_API_V4_URL,CI_BUILD_BEFORE_SHA:Ot.CI_BUILD_BEFORE_SHA,CI_BUILD_ID:Ot.CI_BUILD_ID,CI_BUILD_NAME:Ot.CI_BUILD_NAME,CI_BUILD_REF:Ot.CI_BUILD_REF,CI_BUILD_REF_NAME:Ot.CI_BUILD_REF_NAME,CI_BUILD_REF_SLUG:Ot.CI_BUILD_REF_SLUG,CI_BUILD_STAGE:Ot.CI_BUILD_STAGE,CI_COMMIT_BEFORE_SHA:Ot.CI_COMMIT_BEFORE_SHA,CI_COMMIT_BRANCH:Ot.CI_COMMIT_BRANCH,CI_COMMIT_REF_NAME:Ot.CI_COMMIT_REF_NAME,CI_COMMIT_REF_PROTECTED:Ot.CI_COMMIT_REF_PROTECTED,CI_COMMIT_REF_SLUG:Ot.CI_COMMIT_REF_SLUG,CI_COMMIT_SHA:Ot.CI_COMMIT_SHA,CI_COMMIT_SHORT_SHA:Ot.CI_COMMIT_SHORT_SHA,CI_COMMIT_TIMESTAMP:Ot.CI_COMMIT_TIMESTAMP,CI_COMMIT_TITLE:Ot.CI_COMMIT_TITLE,CI_CONFIG_PATH:Ot.CI_CONFIG_PATH,CI_DEFAULT_BRANCH:Ot.CI_DEFAULT_BRANCH,CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX:Ot.CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX,CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX:Ot.CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX,CI_DEPENDENCY_PROXY_SERVER:Ot.CI_DEPENDENCY_PROXY_SERVER,CI_DEPENDENCY_PROXY_USER:Ot.CI_DEPENDENCY_PROXY_USER,CI_JOB_ID:Ot.CI_JOB_ID,CI_JOB_NAME:Ot.CI_JOB_NAME,CI_JOB_NAME_SLUG:Ot.CI_JOB_NAME_SLUG,CI_JOB_STAGE:Ot.CI_JOB_STAGE,CI_JOB_STARTED_AT:Ot.CI_JOB_STARTED_AT,CI_JOB_URL:Ot.CI_JOB_URL,CI_NODE_TOTAL:Ot.CI_NODE_TOTAL,CI_PAGES_DOMAIN:Ot.CI_PAGES_DOMAIN,CI_PAGES_URL:Ot.CI_PAGES_URL,CI_PIPELINE_CREATED_AT:Ot.CI_PIPELINE_CREATED_AT,CI_PIPELINE_ID:Ot.CI_PIPELINE_ID,CI_PIPELINE_IID:Ot.CI_PIPELINE_IID,CI_PIPELINE_SOURCE:Ot.CI_PIPELINE_SOURCE,CI_PIPELINE_URL:Ot.CI_PIPELINE_URL,CI_PROJECT_CLASSIFICATION_LABEL:Ot.CI_PROJECT_CLASSIFICATION_LABEL,CI_PROJECT_DESCRIPTION:Ot.CI_PROJECT_DESCRIPTION,CI_PROJECT_ID:Ot.CI_PROJECT_ID,CI_PROJECT_NAME:Ot.CI_PROJECT_NAME,CI_PROJECT_NAMESPACE:Ot.CI_PROJECT_NAMESPACE,CI_PROJECT_NAMESPACE_ID:Ot.CI_PROJECT_NAMESPACE_ID,CI_PROJECT_PATH:Ot.CI_PROJECT_PATH,CI_PROJECT_PATH_SLUG:Ot.CI_PROJECT_PATH_SLUG,CI_PROJECT_REPOSITORY_LANGUAGES:Ot.CI_PROJECT_REPOSITORY_LANGUAGES,CI_PROJECT_ROOT_NAMESPACE:Ot.CI_PROJECT_ROOT_NAMESPACE,CI_PROJECT_TITLE:Ot.CI_PROJECT_TITLE,CI_PROJECT_URL:Ot.CI_PROJECT_URL,CI_PROJECT_VISIBILITY:Ot.CI_PROJECT_VISIBILITY,CI_REGISTRY:Ot.CI_REGISTRY,CI_REGISTRY_IMAGE:Ot.CI_REGISTRY_IMAGE,CI_REGISTRY_USER:Ot.CI_REGISTRY_USER,CI_RUNNER_DESCRIPTION:Ot.CI_RUNNER_DESCRIPTION,CI_RUNNER_ID:Ot.CI_RUNNER_ID,CI_RUNNER_TAGS:Ot.CI_RUNNER_TAGS,CI_SERVER_HOST:Ot.CI_SERVER_HOST,CI_SERVER_NAME:Ot.CI_SERVER_NAME,CI_SERVER_PORT:Ot.CI_SERVER_PORT,CI_SERVER_PROTOCOL:Ot.CI_SERVER_PROTOCOL,CI_SERVER_REVISION:Ot.CI_SERVER_REVISION,CI_SERVER_SHELL_SSH_HOST:Ot.CI_SERVER_SHELL_SSH_HOST,CI_SERVER_SHELL_SSH_PORT:Ot.CI_SERVER_SHELL_SSH_PORT,CI_SERVER_URL:Ot.CI_SERVER_URL,CI_SERVER_VERSION:Ot.CI_SERVER_VERSION,CI_SERVER_VERSION_MAJOR:Ot.CI_SERVER_VERSION_MAJOR,CI_SERVER_VERSION_MINOR:Ot.CI_SERVER_VERSION_MINOR,CI_SERVER_VERSION_PATCH:Ot.CI_SERVER_VERSION_PATCH,CI_TEMPLATE_REGISTRY_HOST:Ot.CI_TEMPLATE_REGISTRY_HOST,GITLAB_CI:Ot.GITLAB_CI,GITLAB_FEATURES:Ot.GITLAB_FEATURES,GITLAB_USER_ID:Ot.GITLAB_USER_ID,GITLAB_USER_LOGIN:Ot.GITLAB_USER_LOGIN,RUNNER_GENERATE_ARTIFACTS_METADATA:Ot.RUNNER_GENERATE_ARTIFACTS_METADATA},environment:{name:Ot.CI_RUNNER_DESCRIPTION,architecture:Ot.CI_RUNNER_EXECUTABLE_ARCH,server:Ot.CI_SERVER_URL,project:Ot.CI_PROJECT_PATH,job:{id:Ot.CI_JOB_ID},pipeline:{id:Ot.CI_PIPELINE_ID,ref:Ot.CI_CONFIG_PATH}}},metadata:{buildInvocationId:`${Ot.CI_JOB_URL}`,completeness:{parameters:!0,environment:!0,materials:!1},reproducible:!1},materials:[{uri:`git+${Ot.CI_PROJECT_URL}`,digest:{sha1:Ot.CI_COMMIT_SHA}}]}}}else throw new Zt(91,"Provenance generation is only supported in GitHub Actions and GitLab CI");return HUe.attest(Buffer.from(JSON.stringify(r)),r5t,e)};async function f5t(t,e,{access:r,tag:s,registry:a,gitHead:n,provenance:l}){let f=t.manifest.name,h=t.manifest.version,A=G.stringifyIdent(f),m=GUe.default.fromData(e,{algorithms:["sha1","sha512"]}),w=r??qUe(t,f),v=await VUe(t),D=await fA.genPackageManifest(t),I=`${A}-${h}.tgz`,R=new URL(`${ku(a)}/${A}/-/${I}`),N={[I]:{content_type:"application/octet-stream",data:e.toString("base64"),length:e.length}};if(l){let U={name:`pkg:npm/${A.replace(/^@/,"%40")}@${h}`,digest:{sha512:m.sha512[0].hexDigest()}},V=await jUe([U]),ee=JSON.stringify(V);N[`${A}-${h}.sigstore`]={content_type:V.mediaType,data:ee,length:ee.length}}return{_id:A,_attachments:N,name:A,access:w,"dist-tags":{[s]:h},versions:{[h]:{...D,_id:`${A}@${h}`,name:A,version:h,gitHead:n,dist:{shasum:m.sha1[0].hexDigest(),integrity:m.sha512[0].toString(),tarball:R.toString()}}},readme:v}}async function h5t(t){try{let{stdout:e}=await un.execvp("git",["rev-parse","--revs-only","HEAD"],{cwd:t});return e.trim()===""?void 0:e.trim()}catch{return} Line truncated
`;try{a=await fe.readFilePromise(e,"utf8")}catch(n){if(n.code==="ENOENT")return a;throw n}return a}var Aie={npmAlwaysAuth:{description:"URL of the selected npm registry (note: npm enterprise isn't supported)",type:"BOOLEAN",default:!1},npmAuthIdent:{description:"Authentication identity for the npm registry (_auth in npm and yarn v1)",type:"SECRET",default:null},npmAuthToken:{description:"Authentication token for the npm registry (_authToken in npm and yarn v1)",type:"SECRET",default:null}},WUe={npmAuditRegistry:{description:"Registry to query for audit reports",type:"STRING",default:null},npmPublishRegistry:{description:"Registry to push packages to",type:"STRING",default:null},npmRegistryServer:{description:"URL of the selected npm registry (note: npm enterprise isn't supported)",type:"STRING",default:"https://registry.yarnpkg.com"}},YUe={npmMinimalAgeGate:{description:"Minimum age of a package version according to the publish date on the npm registry to be considered for installation",type:"DURATION",unit:"m",default:"1d"}},A5t={npmPreapprovedPackages:{description:"Array of package descriptors or package name glob patterns to exclude from the minimum release age check",type:"STRING",isArray:!0,default:[]}},p5t={configuration:{...Aie,...WUe,...YUe,...A5t,npmScopes:{description:"Settings per package scope",type:"MAP",valueDefinition:{description:"",type:"SHAPE",properties:{...Aie,...WUe,...YUe}}},npmRegistries:{description:"Settings per registry",type:"MAP",normalizeKeys:ku,valueDefinition:{description:"",type:"SHAPE",properties:{...Aie}}}},fetchers:[dx,cd],resolvers:[gx,mx,yx]},d5t=p5t;var vie={};lr(vie,{NpmAuditCommand:()=>VB,NpmInfoCommand:()=>WB,NpmLoginCommand:()=>YB,NpmLogoutCommand:()=>zB,NpmPublishCommand:()=>JB,NpmStageApproveCommand:()=>ZB,NpmStageListCommand:()=>XB,NpmStageRejectCommand:()=>$B,NpmTagAddCommand:()=>tv,NpmTagListCommand:()=>ev,NpmTagRemoveCommand:()=>rv,NpmWhoamiCommand:()=>nv,default:()=>P5t,npmAuditTypes:()=>AR,npmAuditUtils:()=>D8});We();We();sr();var Eie=st(ma());ga();var AR={};lr(AR,{Environment:()=>fR,Severity:()=>hR});var fR=(s=>(s.All="all",s.Production="production",s.Development="development",s))(fR||{}),hR=(n=>(n.Info="info",n.Low="low",n.Moderate="moderate",n.High="high",n.Critical="critical",n))(hR||{});var D8={};lr(D8,{allSeverities:()=>qB,getPackages:()=>yie,getReportTree:()=>gie,getSeverityInclusions:()=>die,getTopLevelDependencies:()=>mie});We();var KUe=st(Di());var qB=["info","low","moderate","high","critical"];function die(t){if(typeof t>"u")return new Set(qB);let e=qB.indexOf(t),r=qB.slice(e);return new Set(r)}function gie(t){let e={},r={children:e};for(let[s,a]of Ye.sortMap(Object.entries(t),n=>n[0]))for(let n of Ye.sortMap(a,l=>`${l.id}`))e[`${s}/${n.id}`]={value:pe.tuple(pe.Type.IDENT,G.parseIdent(s)),children:{ID:typeof n.id<"u"&&{label:"ID",value:pe.tuple(pe.Type.ID,n.id)},Issue:{label:"Issue",value:pe.tuple(pe.Type.NO_HINT,n.title)},URL:typeof n.url<"u"&&{label:"URL",value:pe.tuple(pe.Type.URL,n.url)},Severity:{label:"Severity",value:pe.tuple(pe.Type.NO_HINT,n.severity)},"Vulnerable Versions":{label:"Vulnerable Versions",value:pe.tuple(pe.Type.RANGE,n.vulnerable_versions)},"Tree Versions":{label:"Tree Versions",children:[...n.versions].sort(KUe.default.compare).map(l=>({value:pe.tuple(pe.Type.REFERENCE,l)}))},Dependents:{label:"Dependents",children:Ye.sortMap(n.dependents,l=>G.stringifyLocator(l)).map(l=>({value:pe.tuple(pe.Type.LOCATOR,l)}))}}};return r}function mie(t,e,{all:r,environment:s}){let a=[],n=r?t.workspaces:[e],l=["all","production"].includes(s),f=["all","development"].includes(s);for(let h of n)for(let A of h.anchoredPackage.dependencies.values())(h.manifest.devDependencies.has(A.identHash)?!f:!l)||a.push({workspace:h,dependency:A});return a}function yie(t,e,{recursive:r}){let s=new Map,a=new Set,n=[],l=t.configuration.makeResolver(),f={project:t,resolver:l},h=(A,m)=>{let w=t.storedResolutions.get(m.descriptorHash);if(typeof w>"u")throw new Error("Assertion failed: The resolution should have been registered");if(!a.has(w))a.add(w);else return;let v=t.storedPackages.get(w);if(typeof v>"u")throw new Error("Assertion failed: The package should have been registered");let D=G.ensureDevirtualizedDescriptor(m);if(l.supportsDescriptor(D,f)){let R=l.getResolutionDependencies(D,f);if(Object.keys(R).length>0)for(let N of Object.values(R))h(A,N)}if(G.ensureDevirtualizedLocator(v).reference.startsWith("npm:")&&v.version!==null){let R=G.stringifyIdent(v),N=Ye.getMapWithDefault(s,R);Ye.getArrayWithDefault(N,v.version).push(A)}if(r)for(let R of v.dependencies.values())n.push([v,R])};for(let{workspace:A,dependency:m}of e)n.push([A.anchoredLocator,m]);for(;n.length>0;){let[A,m]=n.shift();h(A,m)}return s}var VB=class extends mt{constructor(){super(...arguments);this.all=ye.Boolean("-A,--all",!1,{description:"Audit dependencies from all workspaces"});this.recursive=ye.Boolean("-R,--recursive",!1,{description:"Audit transitive dependencies as well"});this.environm Line truncated
This command checks for known security reports on the packages you use. The reports are by default extracted from the npm registry, and may or may not be relevant to your actual program (not all vulnerabilities affect all code paths).
For consistency with our other commands the default is to only check the direct dependencies for the active workspace. To extend this search to all workspaces, use \`-A,--all\`. To extend this search to both direct and transitive dependencies, use \`-R,--recursive\`.
Applying the \`--severity\` flag will limit the audit table to vulnerabilities of the corresponding severity and above. Valid values are ${qB.map(r=>`\`${r}\``).join(", ")}.
If the \`--json\` flag is set, Yarn will print the output exactly as received from the registry. Regardless of this flag, the process will exit with a non-zero exit code if a report is found for the selected packages.
If certain packages produce false positives for a particular environment, the \`--exclude\` flag can be used to exclude any number of packages from the audit. This can also be set in the configuration file with the \`npmAuditExcludePackages\` option.
If particular advisories are needed to be ignored, the \`--ignore\` flag can be used with Advisory ID's to ignore any number of advisories in the audit report. This can also be set in the configuration file with the \`npmAuditIgnoreAdvisories\` option.
To understand the dependency tree requiring vulnerable packages, check the raw report with the \`--json\` flag or use \`yarn why package\` to get more information as to who depends on them.
`,examples:[["Checks for known security issues with the installed packages. The output is a list of known issues.","yarn npm audit"],["Audit dependencies in all workspaces","yarn npm audit --all"],["Limit auditing to `dependencies` (excludes `devDependencies`)","yarn npm audit --environment production"],["Show audit report as valid JSON","yarn npm audit --json"],["Audit all direct and transitive dependencies","yarn npm audit --recursive"],["Output moderate (or more severe) vulnerabilities","yarn npm audit --severity moderate"],["Exclude certain packages","yarn npm audit --exclude package1 --exclude package2"],["Ignore specific advisories","yarn npm audit --ignore 1234567 --ignore 7654321"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd);if(!a)throw new Dr(s.cwd,this.context.cwd);await s.restoreInstallState();let n=mie(s,a,{all:this.all,environment:this.environment}),l=yie(s,n,{recursive:this.recursive}),f=Array.from(new Set([...r.get("npmAuditExcludePackages"),...this.excludes])),h=Object.create(null);for(let[N,U]of l)f.some(V=>Eie.default.isMatch(N,V))||(h[N]=[...U.keys()]);let A=_n.getAuditRegistry({configuration:r}),m,w=await tA.start({configuration:r,stdout:this.context.stdout},async()=>{let N=Jr.post("/-/npm/v1/security/advisories/bulk",h,{authType:Jr.AuthType.BEST_EFFORT,configuration:r,jsonResponse:!0,registry:A}),U=this.noDeprecations?[]:await Promise.all(Array.from(Object.entries(h),async([ee,te])=>{let ie=await Jr.getPackageMetadata(G.parseIdent(ee),{project:s});return Ye.mapAndFilter(te,ae=>{let{deprecated:ge}=ie.versions[ae];return ge?[ee,ae,ge]:Ye.mapAndFilter.skip})})),V=await N;for(let[ee,te,ie]of U.flat(1))Object.hasOwn(V,ee)&&V[ee].some(ae=>zr.satisfiesWithPrereleases(te,ae.vulnerable_versions))||(V[ee]??=[],V[ee].push({id:`${ee} (deprecation)`,title:(typeof ie=="string"?ie:"").trim()||"This package has been deprecated.",severity:"moderate",vulnerable_versions:te}));m=V});if(w.hasErrors())return w.exitCode();let v=die(this.severity),D=Array.from(new Set([...r.get("npmAuditIgnoreAdvisories"),...this.ignores])),I=Object.create(null);for(let[N,U]of Object.entries(m)){let V=U.filter(ee=>!Eie.default.isMatch(`${ee.id}`,D)&&v.has(ee.severity));V.length>0&&(I[N]=V.map(ee=>{let te=l.get(N);if(typeof te>"u")throw new Error("Assertion failed: Expected the registry to only return packages that were requested");let ie=[...te.keys()].filter(ge=>zr.satisfiesWithPrereleases(ge,ee.vulnerable_versions)),ae=new Map;for(let ge of ie)for(let de of te.get(ge))ae.set(de.locatorHash,de);return{...ee,versions:ie,dependents:[...ae.values()]}}))}let R=Object.keys(I).length>0;return R?(bs.emitTree(gie(I),{configuration:r,json:this.json,stdout:this.context.stdout,separators:2}),1):(await Wt.start({configuration:r,includeFooter:!1,json:this.json,stdout:this.context.stdout},async N=>{N.reportInfo(1,"No audit suggestions")}),R?1:0)}};We();We();Mt();sr();var Iie=st(Di()),wie=Ae("util"),WB=class extends mt{constructor(){super(...arguments);this.fields=ye.String("-f,--fields",{description:"A comma-separated list of manifest fields that should be displayed"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.packages=ye.Rest()}static{this.paths=[["npm","info"]]}static{this.usage=At.Usage({category:"Npm-related commands",description:"show information about a package",details:"\n This command fetches information about a package from the npm registry and prints it in a tree format.\n\n The package does not have to be installed locally, but needs to have been published (in particular, local changes will be ignored even for workspaces).\n\n Append `@<range>` to the package argument to provide information specific to the latest version that satisfies the range or to the corresponding tagged version. If the range is invalid or if there is no version satisfying the range, the command will print a warning and fall back to the latest version.\n\n If the `-f,--fields` option is set, it's a comma-separated list of fields which will be used to only display part of the package information.\n\n By default, this command won't return the `dist`, `readme`, and `users` fields, since they are often very long. To explicitly request those fields, explicitly list them with the `--fields` flag or request the output in JSON mode.\n ",examples:[["Show all available information about react (except the `dist`, `readme`, and `users` fields)","yarn npm info react"],["Show all available information about react as valid JSON (including the `dist`, `readme`, and `users` fields)","yarn npm info react --json"],["Show all available information about [email protected]","yarn npm info [email protected]"],["Show all available information about react@next","yarn npm info react@next"],["Show the description of react","yarn npm info react --fields description"],["Show all available versions of react","yarn npm in Line truncated
`),this.context.stdout.write(`${(0,wie.inspect)(h,{depth:1/0,colors:!0,compact:!1})}
`);return f.exitCode()}};function Cie(t){if(Array.isArray(t)){let e=[];for(let r of t)r=Cie(r),r&&e.push(r);return e}else if(typeof t=="object"&&t!==null){let e={};for(let r of Object.keys(t)){if(r.startsWith("_"))continue;let s=Cie(t[r]);s&&(e[r]=s)}return e}else return t||null}We();We();sr();var Bie=st(gD()),YB=class extends mt{constructor(){super(...arguments);this.scope=ye.String("-s,--scope",{description:"Login to the registry configured for a given scope"});this.publish=ye.Boolean("--publish",!1,{description:"Login to the publish registry"});this.alwaysAuth=ye.Boolean("--always-auth",{description:"Set the npmAlwaysAuth configuration"});this.webLogin=ye.Boolean("--web-login",{description:"Enable web login"})}static{this.paths=[["npm","login"]]}static{this.usage=At.Usage({category:"Npm-related commands",description:"store new login info to access the npm registry",details:"\n This command will ask you for your username, password, and 2FA One-Time-Password (when it applies). It will then modify your local configuration (in your home folder, never in the project itself) to reference the new tokens thus generated.\n\n Adding the `-s,--scope` flag will cause the authentication to be done against whatever registry is configured for the associated scope (see also `npmScopes`).\n\n Adding the `--publish` flag will cause the authentication to be done against the registry used when publishing the package (see also `publishConfig.registry` and `npmPublishRegistry`).\n ",examples:[["Login to the default registry","yarn npm login"],["Login to the registry linked to the @my-scope registry","yarn npm login --scope my-scope"],["Login to the publish registry for the current package","yarn npm login --publish"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=await P8({configuration:r,cwd:this.context.cwd,publish:this.publish,scope:this.scope});return(await Wt.start({configuration:r,stdout:this.context.stdout,includeFooter:!1},async n=>{let l=await I5t({registry:s,configuration:r,report:n,webLogin:this.webLogin,stdin:this.context.stdin,stdout:this.context.stdout});return await C5t(s,l,{alwaysAuth:this.alwaysAuth,scope:this.scope}),n.reportInfo(0,"Successfully logged in")})).exitCode()}};async function P8({scope:t,publish:e,configuration:r,cwd:s}){return t&&e?_n.getScopeRegistry(t,{configuration:r,type:_n.RegistryType.PUBLISH_REGISTRY}):t?_n.getScopeRegistry(t,{configuration:r}):e?_n.getPublishRegistry((await TC(r,s)).manifest,{configuration:r}):_n.getDefaultRegistry({configuration:r})}async function g5t(t,e){let r;try{r=await Jr.post("/-/v1/login",null,{configuration:e,registry:t,authType:Jr.AuthType.NO_AUTH,jsonResponse:!0,headers:{"npm-auth-type":"web"}})}catch{return null}return r}async function m5t(t,e){let r=await Sn.request(t,null,{configuration:e,jsonResponse:!0});if(r.statusCode===202){let s=r.headers["retry-after"]??"1";return{type:"waiting",sleep:parseInt(s,10)}}return r.statusCode===200?{type:"success",token:r.body.token}:null}async function y5t({registry:t,configuration:e,report:r}){let s=await g5t(t,e);if(!s)return null;if(us.openUrl){r.reportInfo(0,"Starting the web login process..."),r.reportSeparator();let{openNow:a}=await(0,Bie.prompt)({type:"confirm",name:"openNow",message:"Do you want to try to open your browser now?",required:!0,initial:!0,onCancel:()=>process.exit(130)});r.reportSeparator(),(!a||!await us.openUrl(s.loginUrl))&&(r.reportWarning(0,"We failed to automatically open the url; you'll have to open it yourself in your browser of choice:"),r.reportWarning(0,pe.pretty(e,s.loginUrl,pe.Type.URL)),r.reportSeparator())}for(;;){let a=await m5t(s.doneUrl,e);if(a===null)return null;if(a.type==="waiting")await new Promise(n=>setTimeout(n,a.sleep*1e3));else return a.token}}var E5t=["https://registry.yarnpkg.com","https://registry.npmjs.org"];async function I5t(t){if(t.webLogin??E5t.includes(t.registry)){let e=await y5t(t);if(e!==null)return e}return await w5t(t)}async function w5t({registry:t,configuration:e,report:r,stdin:s,stdout:a}){let n=await B5t({configuration:e,registry:t,report:r,stdin:s,stdout:a}),l=`/-/user/org.couchdb.user:${encodeURIComponent(n.name)}`,f={_id:`org.couchdb.user:${n.name}`,name:n.name,password:n.password,type:"user",roles:[],date:new Date().toISOString()},h={attemptedAs:n.name,configuration:e,registry:t,jsonResponse:!0,authType:Jr.AuthType.NO_AUTH};try{return(await Jr.put(l,f,h)).token}catch(D){if(!(D.originalError?.name==="HTTPError"&&D.originalError?.response.statusCode===409))throw D}let A={...h,authType:Jr.AuthType.NO_AUTH,headers:{authorization:`Basic ${Buffer.from(`${n.name}:${n.password}`).toString("base64")}`}},m=await Jr.get(l,A);for(let[D,I]of Object.entries(m))(!f[D]||D==="roles")&&(f[D]=I);let w=`${l}/-rev/${f._rev}`;return(await Jr.put(w,f,A)).token}async function C5t(t,e,{alwaysAuth:r,scope:s}){let a=l=>f=>{let h=Ye.isIndexableObject(f)?f:{},A=h[l],m=Ye.isIndexableObject(A)?A:{};return{...h,[l]:{...m,...r!==void Line truncated
This command will list all staged package versions awaiting approval on the npm registry.
If a package name is provided, only staged versions of that package will be listed.
`,examples:[["List all staged packages","yarn npm stage list"],["List staged versions of a specific package","yarn npm stage list my-pkg"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=_n.getDefaultRegistry({configuration:r,type:_n.RegistryType.PUBLISH_REGISTRY}),a=await b5t(r,s,this.package??void 0);if(await Wt.start({configuration:r,stdout:this.context.stdout,json:this.json,includeFooter:!1,includePrefix:!1},async l=>{a.length>0?(l.reportInfo(0,`The following packages are awaiting approval. Use ${pe.pretty(r,"yarn npm stage approve <stageId>",pe.Type.CODE)} to approve them.`),l.reportSeparator()):this.package?l.reportInfo(0,`No staged versions found for package ${this.package}`):l.reportInfo(0,"No staged packages found")}),a.length===0)return;let n={children:a.map(l=>{let f=G.parseIdent(l.packageName);return{value:pe.tuple(pe.Type.RESOLUTION,{descriptor:G.makeDescriptor(f,l.tag),locator:G.makeLocator(f,l.version)}),children:{ID:{label:"ID",value:pe.tuple(pe.Type.CODE,l.id)},Staged:{label:"Staged on",value:pe.tuple(pe.Type.NO_HINT,l.createdAt)}}}})};bs.emitTree(n,{configuration:r,json:this.json,stdout:this.context.stdout,separators:1})}};async function b5t(t,e,r){let s=[],a=0,n=100;for(;;){let l={page:String(a),perPage:String(n)};r&&(l.package=r);let f=new URLSearchParams(l).toString(),h=await Jr.get(`/-/stage?${f}`,{configuration:t,registry:e,jsonResponse:!0,authType:Jr.AuthType.ALWAYS_AUTH});if(s.push(...h.items),s.length>=h.total||h.items.length<n)break;a++}return s}We();sr();ga();var $B=class extends mt{constructor(){super(...arguments);this.stageId=ye.String({validator:P0(_h(),[xp(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)])});this.otp=ye.String("--otp",{description:"The OTP token to use with the command"})}static{this.paths=[["npm","stage","reject"]]}static{this.usage=At.Usage({category:"Npm-related commands",description:"reject a staged package version",details:"\n This command will reject a staged package version, permanently removing it from the registry staging area. This operation requires 2FA and will prompt for an OTP token if one is not provided via the `--otp` flag.\n ",examples:[["Reject a staged package","yarn npm stage reject 1de6f3db-2ed9-4d72-b3dd-8f0e2b474a2f"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s=_n.getDefaultRegistry({configuration:r,type:_n.RegistryType.PUBLISH_REGISTRY});return(await Wt.start({configuration:r,stdout:this.context.stdout},async n=>{let l=pe.pretty(r,this.stageId,pe.Type.CODE);n.reportInfo(0,`Rejecting staged package ${pe.pretty(r,l,pe.Type.CODE)}...`),n.reportSeparator(),await Jr.del(`/-/stage/${this.stageId}`,{configuration:r,registry:s,otp:this.otp,authType:Jr.AuthType.ALWAYS_AUTH}),n.reportInfo(0,`Staged package ${pe.pretty(r,l,pe.Type.CODE)} has been rejected.`)})).exitCode()}};We();sr();var JUe=st(Di());We();Mt();sr();var ev=class extends mt{constructor(){super(...arguments);this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.package=ye.String({required:!1})}static{this.paths=[["npm","tag","list"]]}static{this.usage=At.Usage({category:"Npm-related commands",description:"list all dist-tags of a package",details:`
This command will list all tags of a package from the npm registry.
If the package is not specified, Yarn will default to the current workspace.
`,examples:[["List all tags of package `my-pkg`","yarn npm tag list my-pkg"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd),n;if(typeof this.package<"u")n=G.parseIdent(this.package);else{if(!a)throw new Dr(s.cwd,this.context.cwd);if(!a.manifest.name)throw new ht(`Missing 'name' field in ${me.fromPortablePath(Y.join(a.cwd,Or.manifest))}`);n=a.manifest.name}let l=await pR(n,r),h={children:Ye.sortMap(Object.entries(l),([A])=>A).map(([A,m])=>({value:pe.tuple(pe.Type.RESOLUTION,{descriptor:G.makeDescriptor(n,A),locator:G.makeLocator(n,m)})}))};return bs.emitTree(h,{configuration:r,json:this.json,stdout:this.context.stdout})}};async function pR(t,e){let r=`/-/package${Jr.getIdentUrl(t)}/dist-tags`;return Jr.get(r,{configuration:e,ident:t,jsonResponse:!0,customErrorMessage:Jr.customPackageError})}var tv=class extends mt{constructor(){super(...arguments);this.package=ye.String();this.tag=ye.String()}static{this.paths=[["npm","tag","add"]]}static{this.usage=At.Usage({category:"Npm-related commands",description:"add a tag for a specific version of a package",details:`
This command will add a tag to the npm registry for a specific version of a package. If the tag already exists, it will be overwritten.
`,examples:[["Add a `beta` tag for version `2.3.4-beta.4` of package `my-pkg`","yarn npm tag add [email protected] beta"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd);if(!a)throw new Dr(s.cwd,this.context.cwd);let n=G.parseDescriptor(this.package,!0),l=n.range;if(!JUe.default.valid(l))throw new ht(`The range ${pe.pretty(r,n.range,pe.Type.RANGE)} must be a valid semver version`);let f=_n.getPublishRegistry(a.manifest,{configuration:r}),h=pe.pretty(r,n,pe.Type.IDENT),A=pe.pretty(r,l,pe.Type.RANGE),m=pe.pretty(r,this.tag,pe.Type.CODE);return(await Wt.start({configuration:r,stdout:this.context.stdout},async v=>{let D=await pR(n,r);Object.hasOwn(D,this.tag)&&D[this.tag]===l&&v.reportWarning(0,`Tag ${m} is already set to version ${A}`);let I=`/-/package${Jr.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await Jr.put(I,l,{configuration:r,registry:f,ident:n,jsonRequest:!0,jsonResponse:!0}),v.reportInfo(0,`Tag ${m} added to version ${A} of package ${h}`)})).exitCode()}};We();sr();var rv=class extends mt{constructor(){super(...arguments);this.package=ye.String();this.tag=ye.String()}static{this.paths=[["npm","tag","remove"]]}static{this.usage=At.Usage({category:"Npm-related commands",description:"remove a tag from a package",details:`
This command will remove a tag from a package from the npm registry.
`,examples:[["Remove the `beta` tag from package `my-pkg`","yarn npm tag remove my-pkg beta"]]})}async execute(){if(this.tag==="latest")throw new ht("The 'latest' tag cannot be removed.");let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd);if(!a)throw new Dr(s.cwd,this.context.cwd);let n=G.parseIdent(this.package),l=_n.getPublishRegistry(a.manifest,{configuration:r}),f=pe.pretty(r,this.tag,pe.Type.CODE),h=pe.pretty(r,n,pe.Type.IDENT),A=await pR(n,r);if(!Object.hasOwn(A,this.tag))throw new ht(`${f} is not a tag of package ${h}`);return(await Wt.start({configuration:r,stdout:this.context.stdout},async w=>{let v=`/-/package${Jr.getIdentUrl(n)}/dist-tags/${encodeURIComponent(this.tag)}`;await Jr.del(v,{configuration:r,registry:l,ident:n,jsonResponse:!0}),w.reportInfo(0,`Tag ${f} removed from package ${h}`)})).exitCode()}};We();We();sr();var nv=class extends mt{constructor(){super(...arguments);this.scope=ye.String("-s,--scope",{description:"Print username for the registry configured for a given scope"});this.publish=ye.Boolean("--publish",!1,{description:"Print username for the publish registry"})}static{this.paths=[["npm","whoami"]]}static{this.usage=At.Usage({category:"Npm-related commands",description:"display the name of the authenticated user",details:"\n Print the username associated with the current authentication settings to the standard output.\n\n When using `-s,--scope`, the username printed will be the one that matches the authentication settings of the registry associated with the given scope (those settings can be overriden using the `npmRegistries` map, and the registry associated with the scope is configured via the `npmScopes` map).\n\n When using `--publish`, the registry we'll select will by default be the one used when publishing packages (`publishConfig.registry` or `npmPublishRegistry` if available, otherwise we'll fallback to the regular `npmRegistryServer`).\n ",examples:[["Print username for the default registry","yarn npm whoami"],["Print username for the registry on a given scope","yarn npm whoami --scope company"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),s;return this.scope&&this.publish?s=_n.getScopeRegistry(this.scope,{configuration:r,type:_n.RegistryType.PUBLISH_REGISTRY}):this.scope?s=_n.getScopeRegistry(this.scope,{configuration:r}):this.publish?s=_n.getPublishRegistry((await TC(r,this.context.cwd)).manifest,{configuration:r}):s=_n.getDefaultRegistry({configuration:r}),(await Wt.start({configuration:r,stdout:this.context.stdout},async n=>{let l;try{l=await Jr.get("/-/whoami",{configuration:r,registry:s,authType:Jr.AuthType.ALWAYS_AUTH,jsonResponse:!0,ident:this.scope?G.makeIdent(this.scope,""):void 0})}catch(f){if(f.response?.statusCode===401||f.response?.statusCode===403){n.reportError(41,"Authentication failed - your credentials may have expired");return}else throw f}n.reportInfo(0,l.username)})).exitCode()}};var D5t={configuration:{npmPublishAccess:{description:"Default access of the published packages",type:"STRING",default:null},npmPublishProvenance:{description:"Whether to generate provenance for the published packages",type:"BOOLEAN",default:!1},npmAuditExcludePackages:{description:"Array of glob patterns of packages to exclude from npm audit",type:"STRING",default:[],isArray:!0},npmAuditIgnoreAdvisories:{description:"Array of glob patterns of advisory IDs to exclude from npm audit",type:"STRING",default:[],isArray:!0}},commands:[VB,WB,YB,zB,JB,ZB,XB,$B,tv,ev,rv,nv]},P5t=D5t;var Rie={};lr(Rie,{PatchCommand:()=>lv,PatchCommitCommand:()=>cv,PatchFetcher:()=>ER,PatchResolver:()=>IR,default:()=>Y5t,patchUtils:()=>dI});We();We();Mt();Kh();var dI={};lr(dI,{applyPatchFile:()=>k8,diffFolders:()=>xie,ensureUnpatchedDescriptor:()=>Sie,ensureUnpatchedLocator:()=>T8,extractPackageToDisk:()=>Pie,extractPatchFlags:()=>n8e,isParentRequired:()=>Die,isPatchDescriptor:()=>R8,isPatchLocator:()=>dm,loadPatchFiles:()=>yR,makeDescriptor:()=>Q8,makeLocator:()=>bie,makePatchHash:()=>kie,parseDescriptor:()=>gR,parseLocator:()=>mR,parsePatchFile:()=>dR,unpatchDescriptor:()=>G5t,unpatchLocator:()=>q5t});We();Mt();We();Mt();var x5t=/^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@.*/;function iv(t){return Y.relative(Rt.root,Y.resolve(Rt.root,me.toPortablePath(t)))}function k5t(t){let e=t.trim().match(x5t);if(!e)throw new Error(`Bad header line: '${t}'`);return{original:{start:Math.max(Number(e[1]),1),length:Number(e[3]||1)},patched:{start:Math.max(Number(e[4]),1),length:Number(e[6]||1)}}}var R5t=420,T5t=493;var ZUe=()=>({semverExclusivity:null,diffLineFromPath:null,diffLineToPath:null,oldMode:null,newMode:null,deletedFileMode:null,newFileMode:null,renameFrom:null,renameTo:null,beforeHash:null,afterHash:null,fromPath:null,toPath:null,hunks:null}),Q5t=t=>({header:k5t(t),parts:[]}),F5t={"@":"header","-":"deletion","+":"insertion"," ":"context","\\":"pragma",undefined:"context"};function NLine truncated
`)+(a.hunk.parts[0].noNewlineAtEndOfFile?"":`
`):"";await e.mkdirpPromise(Y.dirname(a.path),{chmod:493,utimes:[Oi.SAFE_TIME,Oi.SAFE_TIME]}),await e.writeFilePromise(a.path,n,{mode:a.mode}),await e.utimesPromise(a.path,Oi.SAFE_TIME,Oi.SAFE_TIME)}break;case"patch":await ov(e,a.path,async()=>{await U5t(a,{baseFs:e,dryRun:r})});break;case"mode change":{let l=(await e.statPromise(a.path)).mode;if(XUe(a.newMode)!==XUe(l))continue;await ov(e,a.path,async()=>{await e.chmodPromise(a.path,a.newMode)})}break;default:Ye.assertNever(a);break}}function XUe(t){return(t&64)>0}function $Ue(t){return t.replace(/\s+$/,"")}function M5t(t,e){return $Ue(t)===$Ue(e)}async function U5t({hunks:t,path:e},{baseFs:r,dryRun:s=!1}){let a=await r.statSync(e).mode,l=(await r.readFileSync(e,"utf8")).split(/\n/),f=[],h=0,A=0;for(let w of t){let v=Math.max(A,w.header.patched.start+h),D=Math.max(0,v-A),I=Math.max(0,l.length-v-w.header.original.length),R=Math.max(D,I),N=0,U=0,V=null;for(;N<=R;){if(N<=D&&(U=v-N,V=e8e(w,l,U),V!==null)){N=-N;break}if(N<=I&&(U=v+N,V=e8e(w,l,U),V!==null))break;N+=1}if(V===null)throw new sv(t.indexOf(w),w);f.push(V),h+=N,A=U+w.header.original.length}if(s)return;let m=0;for(let w of f)for(let v of w)switch(v.type){case"splice":{let D=v.index+m;l.splice(D,v.numToDelete,...v.linesToInsert),m+=v.linesToInsert.length-v.numToDelete}break;case"pop":l.pop();break;case"push":l.push(v.line);break;default:Ye.assertNever(v);break}await r.writeFilePromise(e,l.join(`
`),{mode:a})}function e8e(t,e,r){let s=[];for(let a of t.parts)switch(a.type){case"context":case"deletion":{for(let n of a.lines){let l=e[r];if(l==null||!M5t(l,n))return null;r+=1}a.type==="deletion"&&(s.push({type:"splice",index:r-a.lines.length,numToDelete:a.lines.length,linesToInsert:[]}),a.noNewlineAtEndOfFile&&s.push({type:"push",line:""}))}break;case"insertion":s.push({type:"splice",index:r,numToDelete:0,linesToInsert:a.lines}),a.noNewlineAtEndOfFile&&s.push({type:"pop"});break;default:Ye.assertNever(a.type);break}return s}var j5t=/^builtin<([^>]+)>$/;function av(t,e){let{protocol:r,source:s,selector:a,params:n}=G.parseRange(t);if(r!=="patch:")throw new Error("Invalid patch range");if(s===null)throw new Error("Patch locators must explicitly define their source");let l=a?a.split(/&/).map(m=>me.toPortablePath(m)):[],f=n&&typeof n.locator=="string"?G.parseLocator(n.locator):null,h=n&&typeof n.version=="string"?n.version:null,A=e(s);return{parentLocator:f,sourceItem:A,patchPaths:l,sourceVersion:h}}function R8(t){return t.range.startsWith("patch:")}function dm(t){return t.reference.startsWith("patch:")}function gR(t){let{sourceItem:e,...r}=av(t.range,G.parseDescriptor);return{...r,sourceDescriptor:e}}function mR(t){let{sourceItem:e,...r}=av(t.reference,G.parseLocator);return{...r,sourceLocator:e}}function G5t(t){let{sourceItem:e}=av(t.range,G.parseDescriptor);return e}function q5t(t){let{sourceItem:e}=av(t.reference,G.parseLocator);return e}function Sie(t){if(!R8(t))return t;let{sourceItem:e}=av(t.range,G.parseDescriptor);return e}function T8(t){if(!dm(t))return t;let{sourceItem:e}=av(t.reference,G.parseLocator);return e}function t8e({parentLocator:t,sourceItem:e,patchPaths:r,sourceVersion:s,patchHash:a},n){let l=t!==null?{locator:G.stringifyLocator(t)}:{},f=typeof s<"u"?{version:s}:{},h=typeof a<"u"?{hash:a}:{};return G.makeRange({protocol:"patch:",source:n(e),selector:r.join("&"),params:{...f,...h,...l}})}function Q8(t,{parentLocator:e,sourceDescriptor:r,patchPaths:s}){return G.makeDescriptor(t,t8e({parentLocator:e,sourceItem:r,patchPaths:s},G.stringifyDescriptor))}function bie(t,{parentLocator:e,sourcePackage:r,patchPaths:s,patchHash:a}){return G.makeLocator(t,t8e({parentLocator:e,sourceItem:r,sourceVersion:r.version,patchPaths:s,patchHash:a},G.stringifyLocator))}function r8e({onAbsolute:t,onRelative:e,onProject:r,onBuiltin:s},a){let n=a.lastIndexOf("!");n!==-1&&(a=a.slice(n+1));let l=a.match(j5t);return l!==null?s(l[1]):a.startsWith("~/")?r(a.slice(2)):Y.isAbsolute(a)?t(a):e(a)}function n8e(t){let e=t.lastIndexOf("!");return{optional:(e!==-1?new Set(t.slice(0,e).split(/!/)):new Set).has("optional")}}function Die(t){return r8e({onAbsolute:()=>!1,onRelative:()=>!0,onProject:()=>!1,onBuiltin:()=>!1},t)}async function yR(t,e,r){let s=t!==null?await r.fetcher.fetch(t,r):null,a=s&&s.localPath?{packageFs:new Jn(Rt.root),prefixPath:Y.relative(Rt.root,s.localPath)}:s;s&&s!==a&&s.releaseFs&&s.releaseFs();let n=await Ye.releaseAfterUseAsync(async()=>await Promise.all(e.map(async l=>{let f=n8e(l),h=await r8e({onAbsolute:async A=>await fe.readFilePromise(A,"utf8"),onRelative:async A=>{if(a===null)throw new Error("Assertion failed: The parent locator should have been fetched");return await a.packageFs.readFilePromise(Y.join(a.prefixPath,A),"utf8")},onProject:async A=>await fe.readFilePromise(Y.join(r.project.cwd,A),"utf8"),onBuiltin:async A=>await r.project.configuration.firstHook(m=>m.getBuiltinPatch,r.project,A)},l);return{...f,source:h}})));for(let l of n)typeof l.source=="string"&&(l.source=l.source.replace(/\r\n?/g,`
`));return n}async function Pie(t,{cache:e,project:r}){let s=r.storedPackages.get(t.locatorHash);if(typeof s>"u")throw new Error("Assertion failed: Expected the package to be registered");let a=T8(t),n=r.storedChecksums,l=new rs,f=await fe.mktempPromise(),h=Y.join(f,"source"),A=Y.join(f,"user"),m=Y.join(f,".yarn-patch.json"),w=r.configuration.makeFetcher(),v=[];try{let D,I;if(t.locatorHash===a.locatorHash){let R=await w.fetch(t,{cache:e,project:r,fetcher:w,checksums:n,report:l});v.push(()=>R.releaseFs?.()),D=R,I=R}else D=await w.fetch(t,{cache:e,project:r,fetcher:w,checksums:n,report:l}),v.push(()=>D.releaseFs?.()),I=await w.fetch(t,{cache:e,project:r,fetcher:w,checksums:n,report:l}),v.push(()=>I.releaseFs?.());await Promise.all([fe.copyPromise(h,D.prefixPath,{baseFs:D.packageFs}),fe.copyPromise(A,I.prefixPath,{baseFs:I.packageFs}),fe.writeJsonPromise(m,{locator:G.stringifyLocator(t),version:s.version})])}finally{for(let D of v)D()}return fe.detachTemp(f),A}async function xie(t,e){let r=me.fromPortablePath(t).replace(/\\/g,"/"),s=me.fromPortablePath(e).replace(/\\/g,"/"),{stdout:a,stderr:n}=await un.execvp("git",["-c","core.safecrlf=false","-c","core.quotePath=false","diff","--src-prefix=a/","--dst-prefix=b/","--ignore-cr-at-eol","--full-index","--no-index","--no-renames","--text",r,s],{cwd:me.toPortablePath(process.cwd()),env:{...process.env,GIT_CONFIG_NOSYSTEM:"1",HOME:"",XDG_CONFIG_HOME:"",USERPROFILE:""}});if(n.length>0)throw new Error(`Unable to diff directories. Make sure you have a recent version of 'git' available in PATH.
The following error was reported by 'git':
${n}`);let l=r.startsWith("/")?f=>f.slice(1):f=>f;return a.replace(new RegExp(`(a|b)(${Ye.escapeRegExp(`/${l(r)}/`)})`,"g"),"$1/").replace(new RegExp(`(a|b)${Ye.escapeRegExp(`/${l(s)}/`)}`,"g"),"$1/").replace(new RegExp(Ye.escapeRegExp(`${r}/`),"g"),"").replace(new RegExp(Ye.escapeRegExp(`${s}/`),"g"),"")}function kie(t,e){let r=[];for(let{source:s}of t){if(s===null)continue;let a=dR(s);for(let n of a){let{semverExclusivity:l,...f}=n;l!==null&&e!==null&&!zr.satisfiesWithPrereleases(e,l)||r.push(JSON.stringify(f))}}return si.makeHash(`${3}`,...r).slice(0,6)}We();function i8e(t,{configuration:e,report:r}){for(let s of t.parts)for(let a of s.lines)switch(s.type){case"context":r.reportInfo(null,` ${pe.pretty(e,a,"grey")}`);break;case"deletion":r.reportError(28,`- ${pe.pretty(e,a,pe.Type.REMOVED)}`);break;case"insertion":r.reportError(28,`+ ${pe.pretty(e,a,pe.Type.ADDED)}`);break;default:Ye.assertNever(s.type)}}function V5t(t){return t instanceof Error&&"code"in t&&t.code==="ENOENT"}var ER=class{supports(e,r){return!!dm(e)}getLocalPath(e,r){return null}async fetch(e,r){let s=r.checksums.get(e.locatorHash)||null,[a,n,l]=await r.cache.fetchPackageFromCache(e,s,{onHit:()=>r.report.reportCacheHit(e),onMiss:()=>r.report.reportCacheMiss(e,`${G.prettyLocator(r.project.configuration,e)} can't be found in the cache and will be fetched from the disk`),loader:()=>this.patchPackage(e,r),...r.cacheOptions});return{packageFs:a,releaseFs:n,prefixPath:G.getIdentVendorPath(e),localPath:this.getLocalPath(e,r),checksum:l}}async patchPackage(e,r){let{parentLocator:s,sourceLocator:a,sourceVersion:n,patchPaths:l}=mR(e),f=await yR(s,l,r),h=await fe.mktempPromise(),A=Y.join(h,"current.zip"),m=await r.fetcher.fetch(a,r),w=G.getIdentVendorPath(e),v=new _s(A,{create:!0,level:r.project.configuration.get("compressionLevel")});await Ye.releaseAfterUseAsync(async()=>{await v.copyPromise(w,m.prefixPath,{baseFs:m.packageFs,stableSort:!0})},m.releaseFs),v.saveAndClose();for(let{source:D,optional:I}of f){if(D===null)continue;let R=new _s(A,{level:r.project.configuration.get("compressionLevel")}),N=new Jn(Y.resolve(Rt.root,w),{baseFs:R});try{await k8(dR(D),{baseFs:N,version:n})}catch(U){let V=U instanceof sv?U:null;if(!(V!==null||I&&V5t(U)))throw U;let te=r.project.configuration.get("enableInlineHunks"),ie=V!==null&&!te&&!I?" (set enableInlineHunks for details)":"",ae=`${G.prettyLocator(r.project.configuration,e)}: ${U.message}${ie}`,ge=de=>{V===null||!te||i8e(V.hunk,{configuration:r.project.configuration,report:de})};if(R.discardAndClose(),I){r.report.reportWarningOnce(66,ae,{reportExtra:ge});continue}else throw new Zt(66,ae,ge)}R.saveAndClose()}return new _s(A,{level:r.project.configuration.get("compressionLevel")})}};We();var IR=class{supportsDescriptor(e,r){return!!R8(e)}supportsLocator(e,r){return!!dm(e)}shouldPersistResolution(e,r){return!1}bindDescriptor(e,r,s){let{patchPaths:a}=gR(e);return a.every(n=>!Die(n))?e:G.bindDescriptor(e,{locator:G.stringifyLocator(r)})}getResolutionDependencies(e,r){let{sourceDescriptor:s}=gR(e);return{sourceDescriptor:r.project.configuration.normalizeDependency(s)}}async getCandidates(e,r,s){if(!s.fetchOptions)throw new Error("Assertion failed: This resolver cannot be used unless a fetcher is configured");let{parentLocator:a,patchPaths:n}=gR(e),l=await yR(a,n,s.fetchOptions),f=r.sourceDescriptor;if(typeof f>"u")throw new Error("Assertion failed: The dependency should have been resolved");let h=kie(l,f.version);return[bie(e,{parentLocator:a,sourcePackage:f,patchPaths:n,patchHash:h})]}async getSatisfying(e,r,s,a){let[n]=await this.getCandidates(e,r,a);return{locators:s.filter(l=>l.locatorHash===n.locatorHash),sorted:!1}}async resolve(e,r){let{sourceLocator:s}=mR(e);return{...await r.resolver.resolve(s,r),...e}}};We();Mt();sr();var cv=class extends mt{constructor(){super(...arguments);this.save=ye.Boolean("-s,--save",!1,{description:"Add the patch to your resolution entries"});this.patchFolder=ye.String()}static{this.paths=[["patch-commit"]]}static{this.usage=At.Usage({description:"generate a patch out of a directory",details:"\n By default, this will print a patchfile on stdout based on the diff between the folder passed in and the original version of the package. Such file is suitable for consumption with the `patch:` protocol.\n\n With the `-s,--save` option set, the patchfile won't be printed on stdout anymore and will instead be stored within a local file (by default kept within `.yarn/patches`, but configurable via the `patchFolder` setting). A `resolutions` entry will also be added to your top-level manifest, referencing the patched package via the `patch:` protocol.\n\n Note that only folders generated by `yarn patch` are accepted as valid input for `yarn patch-commit`.\n "})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s,workspace:a}=await Yt.find(r,this.context.cwd);if(!a)throw new Dr(s.cwd,this.context.cwd);await s.restoreInstallState();let n=Y.Line truncated
${f.map(h=>`
- ${G.prettyLocator(r,h)}`).join("")}`);l=f[0]}if(!s.storedPackages.has(l.locatorHash))throw new ht("No package found in the project for the given locator");await Wt.start({configuration:r,json:this.json,stdout:this.context.stdout},async f=>{let h=T8(l),A=await Pie(l,{cache:n,project:s});f.reportJson({locator:G.stringifyLocator(h),path:me.fromPortablePath(A)});let m=this.update?" along with its current modifications":"";f.reportInfo(0,`Package ${G.prettyLocator(r,h)} got extracted with success${m}!`),f.reportInfo(0,`You can now edit the following folder: ${pe.pretty(r,me.fromPortablePath(A),"magenta")}`),f.reportInfo(0,`Once you are done run ${pe.pretty(r,`yarn patch-commit -s ${process.platform==="win32"?'"':""}${me.fromPortablePath(A)}${process.platform==="win32"?'"':""}`,"cyan")} and Yarn will store a patchfile based on your changes.`)})}};var W5t={configuration:{enableInlineHunks:{description:"If true, the installs will print unmatched patch hunks",type:"BOOLEAN",default:!1},patchFolder:{description:"Folder where the patch files must be written",type:"ABSOLUTE_PATH",default:"./.yarn/patches"}},commands:[cv,lv],fetchers:[ER],resolvers:[IR]},Y5t=W5t;var Fie={};lr(Fie,{PnpmLinker:()=>CR,default:()=>ejt});We();Mt();sr();var s8e=".package-map.json",CR=class{getCustomDataKey(){return JSON.stringify({name:"PnpmLinker",version:3})}supportsPackage(e,r){return this.isEnabled(r)}async findPackageLocation(e,r){if(!this.isEnabled(r))throw new Error("Assertion failed: Expected the pnpm linker to be enabled");let s=this.getCustomDataKey(),a=r.project.linkersCustomData.get(s);if(!a)throw new ht(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=a.pathsByLocator.get(e.locatorHash);if(typeof n>"u")throw new ht(`Couldn't find ${G.prettyLocator(r.project.configuration,e)} in the currently installed pnpm map - running an install might help`);return n.packageLocation}async findPackageLocator(e,r){if(!this.isEnabled(r))return null;let s=this.getCustomDataKey(),a=r.project.linkersCustomData.get(s);if(!a)throw new ht(`The project in ${pe.pretty(r.project.configuration,`${r.project.cwd}/package.json`,pe.Type.PATH)} doesn't seem to have been installed - running an install there might help`);let n=e.match(/(^.*\/node_modules\/(@[^/]*\/)?[^/]+)(\/.*$)/);if(n){let h=a.locatorByPath.get(n[1]);if(h)return h}let l=e,f=e;do{f=l,l=Y.dirname(f);let h=a.locatorByPath.get(f);if(h)return h}while(l!==f);return null}makeInstaller(e){return new Tie(e)}isEnabled(e){return e.project.configuration.get("nodeLinker")==="pnpm"}},Tie=class{constructor(e){this.opts=e;this.customData={pathsByLocator:new Map,locatorByPath:new Map};this.packageMapNodesByLocator=new Map;this.asyncActions=new Ye.AsyncActions(e.project.configuration.get("pnpmInstallConcurrency")),this.indexFolderPromise=gT(fe,{indexPath:Y.join(e.project.configuration.get("globalFolder"),"index")})}attachCustomData(e){}registerPackageMapNode(e,{packageLocation:r}){let s=l8e(r);this.packageMapNodesByLocator.has(e)||this.packageMapNodesByLocator.set(e,{packageLocation:s,dependencies:new Map})}registerPackageMapDependency(e,r,s){if(!this.packageMapNodesByLocator.has(s.locatorHash))throw new Error(`Assertion failed: Expected the package to have been registered (${G.stringifyLocator(s)})`);e.dependencies.set(r,s.locatorHash)}async installPackage(e,r,s){switch(e.linkType){case"SOFT":return this.installPackageSoft(e,r,s);case"HARD":return this.installPackageHard(e,r,s)}throw new Error("Assertion failed: Unsupported package link type")}async installPackageSoft(e,r,s){let a=Y.resolve(r.packageFs.getRealPath(),r.prefixPath),n=this.opts.project.tryWorkspaceByLocator(e)?Y.join(a,Or.nodeModules):null,l={packageLocation:a,dependenciesLocation:n};return this.customData.pathsByLocator.set(e.locatorHash,l),this.registerPackageMapNode(e.locatorHash,l),{packageLocation:a,buildRequest:null}}async installPackageHard(e,r,s){let a=K5t(e,{project:this.opts.project}),n=a.packageLocation;this.customData.locatorByPath.set(n,G.stringifyLocator(e)),this.customData.pathsByLocator.set(e.locatorHash,a),this.registerPackageMapNode(e.locatorHash,a),s.holdFetchResult(this.asyncActions.set(e.locatorHash,async()=>{await fe.mkdirPromise(n,{recursive:!0}),await fe.copyPromise(n,r.prefixPath,{baseFs:r.packageFs,overwrite:!1,linkStrategy:{type:"HardlinkFromIndex",indexPath:await this.indexFolderPromise,autoRepair:!0}})}));let f=G.isVirtualLocator(e)?G.devirtualizeLocator(e):e,h={manifest:await nr.tryFind(r.prefixPath,{baseFs:r.packageFs})??new nr,misc:{hasBindingGyp:cA.hasBindingGyp(r)}},A=this.opts.project.getDependencyMeta(f,e.version),m=cA.extractBuildRequest(e,h,A,{configuration:this.opts.project.configuration});return{packageLocation:n,buildRequest:m}}async attachInternalDependencies(e,r){if(this.opts.project.configuration.get("nodeLinker")!=="pnpm"||!a8e(e,{project:this.opts.project}))return;let s=Line truncated
${rjt}
`,"--",...s],{cwd:t,strict:!0})},async makeReset(t,e){let r=e.map(s=>me.fromPortablePath(s.path));await un.execvp("git",["reset","HEAD","--",...r],{cwd:t,strict:!0})}};var ajt=[h8e],uv=class extends mt{constructor(){super(...arguments);this.commit=ye.Boolean("-c,--commit",!1,{description:"Commit the staged files"});this.reset=ye.Boolean("-r,--reset",!1,{description:"Remove all files from the staging area"});this.dryRun=ye.Boolean("-n,--dry-run",!1,{description:"Print the commit message and the list of modified files without staging / committing"});this.update=ye.Boolean("-u,--update",!1,{hidden:!0})}static{this.paths=[["stage"]]}static{this.usage=At.Usage({description:"add all yarn files to your vcs",details:"\n This command will add to your staging area the files belonging to Yarn (typically any modified `package.json` and `.yarnrc.yml` files, but also linker-generated files, cache data, etc). It will take your ignore list into account, so the cache files won't be added if the cache is ignored in a `.gitignore` file (assuming you use Git).\n\n Running `--reset` will instead remove them from the staging area (the changes will still be there, but won't be committed until you stage them back).\n\n Since the staging area is a non-existent concept in Mercurial, Yarn will always create a new commit when running this command on Mercurial repositories. You can get this behavior when using Git by using the `--commit` flag which will directly create a commit.\n ",examples:[["Adds all modified project files to the staging area","yarn stage"],["Creates a new commit containing all modified project files","yarn stage --commit"]]})}async execute(){let r=await $e.find(this.context.cwd,this.context.plugins),{project:s}=await Yt.find(r,this.context.cwd),{driver:a,root:n}=await cjt(s.cwd),l=[r.get("cacheFolder"),r.get("globalFolder"),r.get("virtualFolder"),r.get("yarnPath")];await r.triggerHook(w=>w.populateYarnPaths,s,w=>{l.push(w)});let f=new Set;for(let w of l)for(let v of ljt(n,w))f.add(v);let h=new Set([r.get("rcFilename"),Or.lockfile,Or.manifest]),A=await a.filterChanges(n,f,h),m=await a.genCommitMessage(n,A);if(this.dryRun)if(this.commit)this.context.stdout.write(`${m}
`);else for(let w of A)this.context.stdout.write(`${me.fromPortablePath(w.path)}
`);else if(this.reset){let w=await a.filterChanges(n,f,h,{staged:!0});w.length===0?this.context.stdout.write("No staged changes found!"):await a.makeReset(n,w)}else A.length===0?this.context.stdout.write("No changes found!"):this.commit?await a.makeCommit(n,A,m):(await a.makeStage(n,A),this.context.stdout.write(m))}};async function cjt(t){let e=null,r=null;for(let s of ajt)if((r=await s.findRoot(t))!==null){e=s;break}if(e===null||r===null)throw new ht("No stage driver has been found for your current project");return{driver:e,root:r}}function ljt(t,e){let r=[];if(e===null)return r;for(;;){(e===t||e.startsWith(`${t}/`))&&r.push(e);let s;try{s=fe.statSync(e)}catch{break}if(s.isSymbolicLink())e=Y.resolve(Y.dirname(e),fe.readlinkSync(e));else break}return r}var ujt={commands:[uv]},fjt=ujt;var jie={};lr(jie,{default:()=>Ejt});We();We();Mt();var d8e=st(Di());We();var A8e=st(iK()),hjt="e8e1bd300d860104bb8c58453ffa1eb4",Ajt="OFCNCOG2CU",p8e=async(t,e)=>{let r=G.stringifyIdent(t),a=pjt(e).initIndex("npm-search");try{return(await a.getObject(r,{attributesToRetrieve:["types"]})).types?.ts==="definitely-typed"}catch{return!1}},pjt=t=>(0,A8e.default)(Ajt,hjt,{requester:{async send(r){try{let s=await Sn.request(r.url,r.data||null,{configuration:t,headers:r.headers});return{content:s.body,isTimedOut:!1,status:s.statusCode}}catch(s){return{content:s.response.body,isTimedOut:!1,status:s.response.statusCode}}}}});var g8e=t=>t.scope?`${t.scope}__${t.name}`:`${t.name}`,djt=async(t,e,r,s)=>{if(r.scope==="types")return;let{project:a}=t,{configuration:n}=a;if(!(n.get("tsEnableAutoTypes")??(fe.existsSync(Y.join(t.cwd,"tsconfig.json"))||fe.existsSync(Y.join(a.cwd,"tsconfig.json")))))return;let f=n.makeResolver(),h={project:a,resolver:f,report:new rs};if(!await p8e(r,n))return;let m=g8e(r),w=G.parseRange(r.range).selector;if(!zr.validRange(w)){let N=n.normalizeDependency(r),U=await f.getCandidates(N,{},h);w=G.parseRange(U[0].reference).selector}let v=d8e.default.coerce(w);if(v===null)return;let D=`${jf.Modifier.CARET}${v.major}`,I=G.makeDescriptor(G.makeIdent("types",m),D),R=Ye.mapAndFind(a.workspaces,N=>{let U=N.manifest.dependencies.get(r.identHash)?.descriptorHash,V=N.manifest.devDependencies.get(r.identHash)?.descriptorHash;if(U!==r.descriptorHash&&V!==r.descriptorHash)return Ye.mapAndFind.skip;let ee=[];for(let te of nr.allDependencies){let ie=N.manifest[te].get(I.identHash);typeof ie>"u"||ee.push([te,ie])}return ee.length===0?Ye.mapAndFind.skip:ee});if(typeof R<"u")for(let[N,U]of R)t.manifest[N].set(U.identHash,U);else{try{let N=n.normalizeDependency(I);if((await f.getCandidates(N,{},h)).length===0)return}catch{return}t.manifest[jf.Target.DEVELOPMENT].set(I.identHash,I)}},gjt=async(t,e,r)=>{if(r.scope==="types")return;let{project:s}=t,{configuration:a}=s;if(!(a.get("tsEnableAutoTypes")??(fe.existsSync(Y.join(t.cwd,"tsconfig.json"))||fe.existsSync(Y.join(s.cwd,"tsconfig.json")))))return;let l=g8e(r),f=G.makeIdent("types",l);for(let h of nr.allDependencies)typeof t.manifest[h].get(f.identHash)>"u"||t.manifest[h].delete(f.identHash)},mjt=(t,e)=>{e.publishConfig&&e.publishConfig.typings&&(e.typings=e.publishConfig.typings),e.publishConfig&&e.publishConfig.types&&(e.types=e.publishConfig.types)},yjt={configuration:{tsEnableAutoTypes:{description:"Whether Yarn should auto-install @types/ dependencies on 'yarn add'",type:"BOOLEAN",isNullable:!0,default:null}},hooks:{afterWorkspaceDependencyAddition:djt,afterWorkspaceDependencyRemoval:gjt,beforeWorkspacePacking:mjt}},Ejt=yjt;var Kie={};lr(Kie,{VersionApplyCommand:()=>fv,VersionCheckCommand:()=>dv,VersionCommand:()=>gv,default:()=>bjt,versionUtils:()=>vR});sr();var fv=class extends mt{constructor(){super(...arguments);this.all=ye.Boolean("--all",!1,{description:"Bump the version of all workspaces"});this.recursive=ye.Boolean("-R,--recursive",{description:"Bump the version of dependent workspaces as well"});this.exact=ye.Boolean("--exact",!1,{description:"When updating parent workspaces' dependencies, use exact versions of bumped workspaces, removing any range."});this.prerelease=ye.String("--prerelease",{description:"Specify a prerelease pattern to use when working with prerelease versions",tolerateBoolean:!0});this.dryRun=ye.Boolean("--dry-run",!1,{description:"Print version(s)/record(s) without actually bumping versions or recording deferred releases"});this.force=ye.Boolean("--force",!1,{description:"Bypass check for bumping to a lower version than the current/deferred one"});this.json=ye.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"})}static{this.paths=[["version","apply"]]}static{this.usage=At.Usage({category:"Release-related commands",description:"apply deferred records to workspaces",details:`
This command will apply the deferred version changes to workspaces. The applied records are removed from the project.
For more information on the options, see the \`yarn version\` command. For more information on the deferred versioning workflow, see our documentation (https://yarnpkg.com/features/release-workflow#deferred-versioning).
`,examples:[["Apply deferred records of current workspace","yarn version apply"],["Apply deferred records of all the workspaces in the local workspace","yarn version apply --all"]]})}async execute(){let r=["version","decline","--immediate"];return this.all&&r.push("--all"),this.recursive&&r.push("--recursive"),this.exact&&r.push("--exact"),this.prerelease===!0?r.push("--prerelease"):typeof this.prerelease=="string"&&r.push(`--prerelease=${this.prerelease}`),this.dryRun&&r.push("--dry-run"),this.force&&r.push("--force"),this.json&&r.push("--json"),await this.cli.run(r)}};We();Mt();sr();var Yie=st(Di());var vR={};lr(vR,{Decision:()=>Av,applyPrerelease:()=>m8e,applyReleases:()=>Wie,applyStrategy:()=>_8,clearVersionFiles:()=>qie,getUndecidedDependentWorkspaces:()=>BR,getUndecidedWorkspaces:()=>L8,openVersionFile:()=>pv,requireMoreDecisions:()=>Cjt,resolveVersionFiles:()=>Gie,suggestStrategy:()=>Bjt,updateVersionFiles:()=>Vie,validateReleaseDecision:()=>hv});We();Mt();au();sr();xl();var Oa=st(Di()),Ijt=/^(>=|[~^]|)(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/,Av=(A=>(A.UNDECIDED="undecided",A.DECLINE="decline",A.MAJOR="major",A.MINOR="minor",A.PATCH="patch",A.PREMAJOR="premajor",A.PREMINOR="preminor",A.PREPATCH="prepatch",A.PRERELEASE="prerelease",A))(Av||{});function hv(t){let e=Oa.default.valid(t);if(e)return e;let r=Object.values(j5(Av,"UNDECIDED"));if(r.includes(t))return t;let s=Oa.default.valid(t,{loose:!0})?` Did you mean to use "${Oa.default.valid(t,{loose:!0})}"?`:"";throw new ht(`Invalid strategy: "${t}". Expected a valid semver or one of ${r.map(a=>JSON.stringify(a)).join(", ")}.${s}`)}function wjt(t){return t==="premajor"||t==="preminor"||t==="prepatch"||t==="prerelease"}async function Gie(t,{prerelease:e=null}={}){let r=new Map,s=t.configuration.get("deferredVersionFolder");if(!fe.existsSync(s))return r;let a=await fe.readdirPromise(s);for(let n of a){if(!n.endsWith(".yml"))continue;let l=Y.join(s,n),f=await fe.readFilePromise(l,"utf8"),h=Fs(f);for(let[A,m]of Object.entries(h.releases||{})){if(m==="decline")continue;let w=G.parseIdent(A),v=t.tryWorkspaceByIdent(w);if(v===null)throw new Error(`Assertion failed: Expected a release definition file to only reference existing workspaces (${Y.basename(l)} references ${A})`);if(v.manifest.version===null)throw new Error(`Assertion failed: Expected the workspace to have a version (${G.prettyLocator(t.configuration,v.anchoredLocator)})`);let D=r.get(v),I=_8(v.manifest.version,hv(m),e);if(I===null)throw new Error(`Assertion failed: Expected ${v.manifest.version} to support being bumped via strategy ${m}`);let R=typeof D<"u"?Oa.default.gt(I,D)?I:D:I;r.set(v,R)}}return r}async function qie(t){let e=t.configuration.get("deferredVersionFolder");fe.existsSync(e)&&await fe.removePromise(e)}async function Vie(t,e){let r=new Set(e),s=t.configuration.get("deferredVersionFolder");if(!fe.existsSync(s))return;let a=await fe.readdirPromise(s);for(let n of a){if(!n.endsWith(".yml"))continue;let l=Y.join(s,n),f=await fe.readFilePromise(l,"utf8"),h=Fs(f),A=h?.releases;if(A){for(let m of Object.keys(A)){let w=G.parseIdent(m),v=t.tryWorkspaceByIdent(w);(v===null||r.has(v))&&delete h.releases[m]}Object.keys(h.releases).length>0?await fe.changeFilePromise(l,Uc(new Uc.PreserveOrdering(h))):await fe.unlinkPromise(l)}}}async function pv(t,{allowEmpty:e=!1}={}){let r=t.configuration;if(r.projectCwd===null)throw new ht("This command can only be run from within a Yarn project");let s=await fc.fetchRoot(r.projectCwd),a=s!==null?await fc.fetchBase(s,{baseRefs:r.get("changesetBaseRefs")}):null,n=s!==null?await fc.fetchChangedFiles(s,{base:a.hash,project:t}):[],l=r.get("deferredVersionFolder"),f=n.filter(D=>Y.contains(l,D)!==null);if(f.length>1)throw new ht(`Your current branch contains multiple versioning files; this isn't supported:
- ${f.map(D=>me.fromPortablePath(D)).join(`
- `)}`);let h=new Set(Ye.mapAndFilter(n,D=>{let I=t.tryWorkspaceByFilePath(D);return I===null?Ye.mapAndFilter.skip:I}));if(f.length===0&&h.size===0&&!e)return null;let A=f.length===1?f[0]:Y.join(l,`${si.makeHash(Math.random().toString()).slice(0,8)}.yml`),m=fe.existsSync(A)?await fe.readFilePromise(A,"utf8"):"{}",w=Fs(m),v=new Map;for(let D of w.declined||[]){let I=G.parseIdent(D),R=t.getWorkspaceByIdent(I);v.set(R,"decline")}for(let[D,I]of Object.entries(w.releases||{})){let R=G.parseIdent(D),N=t.getWorkspaceByIdent(R);v.set(N,hv(I))}return{project:t,root:s,baseHash:a!==null?a.hash:null,baseTitle:a!==null?a.title:null,changedFiles:new Set(n),changedWorkspaces:h,releaseRoots:new Set([...h].filter(D=>D.manifest.version!==null)),releases:v,async saveAll(){let D={},I=[],R=[];for(let N of t.workspaces){if(N.manifest.version===null)continue;let U=G.stringifyIdent(N.anchoredLocator),V=v.get(N);V==="decline"?I.push(U):typeof V<"u"?D[U]=hv(V):h.has(N)&&R.push(U)}await fe.mkdirPromise(Y.dirname(A),{recursive:!0}),await fe.changeFilePromise(A,Uc(new Uc.PreserveOrdering({releases:Object.keys(D).length>0?D:void 0,declined:I.length>0?I:void 0,undecided:R.length>0?R:void 0})))}}}function Cjt(t){return L8(t).size>0||BR(t).length>0}function L8(t){let e=new Set;for(let r of t.changedWorkspaces)r.manifest.version!==null&&(t.releases.has(r)||e.add(r));return e}function BR(t,{include:e=new Set}={}){let r=[],s=new Map(Ye.mapAndFilter([...t.releases],([n,l])=>l==="decline"?Ye.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n])),a=new Map(Ye.mapAndFilter([...t.releases],([n,l])=>l!=="decline"?Ye.mapAndFilter.skip:[n.anchoredLocator.locatorHash,n]));for(let n of t.project.workspaces)if(!(!e.has(n)&&(a.has(n.anchoredLocator.locatorHash)||s.has(n.anchoredLocator.locatorHash)))&&n.manifest.version!==null)for(let l of nr.hardDependencies)for(let f of n.manifest.getForScope(l).values()){let h=t.project.tryWorkspaceByDescriptor(f);h!==null&&s.has(h.anchoredLocator.locatorHash)&&r.push([n,h])}return r}function Bjt(t,e){let r=Oa.default.clean(e);for(let s of Object.values(Av))if(s!=="undecided"&&s!=="decline"&&Oa.default.inc(t,s)===r)return s;return null}function _8(t,e,r=null){if(Oa.default.valid(e))return e;if(t===null)throw new ht(`Cannot apply the release strategy "${e}" unless the workspace already has a valid version`);if(!Oa.default.valid(t))throw new ht(`Cannot apply the release strategy "${e}" on a non-semver version (${t})`);if(wjt(e)){let a=Oa.default.inc(t,e==="prerelease"?"patch":e.slice(3));if(a===null)throw new ht(`Cannot apply the release strategy "${e.slice(3)}" on the specified version (${t}) while trying to determine the base of the prerelease bump`);return r?m8e(a,{current:t,prerelease:r}):a===Oa.default.truncate(t,"patch")?Oa.default.inc(t,"prerelease"):`${a}-0`}let s=Oa.default.inc(t,e);if(s===null)throw new ht(`Cannot apply the release strategy "${e}" on the specified version (${t})`);return s}function Wie(t,e,{report:r,exact:s}){let a=new Map;for(let n of t.workspaces)for(let l of nr.allDependencies)for(let f of n.manifest[l].values()){let h=t.tryWorkspaceByDescriptor(f);if(h===null||!e.has(h))continue;Ye.getArrayWithDefault(a,h).push([n,l,f.identHash])}for(let[n,l]of e){let f=n.manifest.version;n.manifest.version=l,delete n.manifest.raw.stableVersion;let h=n.manifest.name!==null?G.stringifyIdent(n.manifest.name):null;r.reportInfo(0,`${G.prettyLocator(t.configuration,n.anchoredLocator)}: Bumped to ${l}`),r.reportJson({cwd:me.fromPortablePath(n.cwd),ident:h,deferred:!1,oldVersion:f,newVersion:l});let A=a.get(n);if(!(typeof A>"u"))for(let[m,w,v]of A){let D=m.manifest[w].get(v);if(typeof D>"u")throw new Error("Assertion failed: The dependency should have existed");let I=D.range,R=!1;if(I.startsWith(Gi.protocol)&&(I=I.slice(Gi.protocol.length),R=!0,I===n.relativeCwd))continue;let N=I.match(Ijt);if(!N){r.reportWarning(0,`Couldn't auto-upgrade range ${I} (in ${G.prettyLocator(t.configuration,m.anchoredLocator)})`);continue}let U=s?`${l}`:`${N[1]}${l}`;R&&(U=`${Gi.protocol}${U}`);let V=G.makeDescriptor(D,U);m.manifest[w].set(v,V)}}}var vjt=new Map([["%n",t=>t.length>0&&typeof t[0]=="number"?{increment:t.shift()+1,reset:1}:{increment:null,reset:1}]]);function m8e(t,{current:e,prerelease:r}){let s=new Oa.default.SemVer(e),a=Oa.default.truncate(t,"patch");if(a===null)throw new Error(`Assertion failed: Expected the version to be a valid semver version (${t})`);let n=s.prerelease.slice(),l=Oa.default.truncate(s,"patch")===a,f=[];for(let A of r.split(/\./g)){let m=vjt.get(A);if(typeof m>"u")f.push(A),n[0]===A?n.shift():l=!1;else{let w=m(n);l&&w.increment!==null?f.push(w):(f.push(w.reset),l=!1)}}l&&=n.length===0;let h=f.map(A=>typeof A=="object"?l?A.increment:A.reset:A);return`${a}-${h.join(".")}`}var dv=class extends mt{constructor(){super(...arguments);this.interactive=ye.Boolean("-i,--interactive",{description:"Open an interactive interface used to set version bumps"})}static{this.paths=[["version","check"]]}static{this.usaLine truncated
`)},h=()=>{let we=this.from.map(d=>yv.default.matcher(d));return s.workspaces.filter(d=>{let be=G.stringifyIdent(d.anchoredLocator),Ce=d.relativeCwd;return we.some(Ee=>Ee(be)||Ee(Ce))})},A=[];if(this.since?(f("Option --since is set; selecting the changed workspaces as root for workspace selection"),A=Array.from(await fc.fetchChangedWorkspaces({ref:this.since,project:s}))):this.from?(f("Option --from is set; selecting the specified workspaces"),A=[...h()]):this.worktree?(f("Option --worktree is set; selecting the current workspace"),A=[a]):this.recursive?(f("Option --recursive is set; selecting the current workspace"),A=[a]):this.all&&(f("Option --all is set; selecting all workspaces"),A=[...s.workspaces]),this.dryRun&&!this.all){for(let we of A)f(`
- ${we.relativeCwd}
${G.prettyLocator(r,we.anchoredLocator)}`);A.length>0&&f("")}let m;if(this.recursive?this.since?(f("Option --recursive --since is set; recursively selecting all dependent workspaces"),m=new Set(A.map(we=>[...we.getRecursiveWorkspaceDependents()]).flat())):(f("Option --recursive is set; recursively selecting all transitive dependencies"),m=new Set(A.map(we=>[...we.getRecursiveWorkspaceDependencies()]).flat())):this.worktree?(f("Option --worktree is set; recursively selecting all nested workspaces"),m=new Set(A.map(we=>[...we.getRecursiveWorkspaceChildren()]).flat())):m=null,m!==null&&(A=[...new Set([...A,...m])],this.dryRun))for(let we of m)f(`
- ${we.relativeCwd}
${G.prettyLocator(r,we.anchoredLocator)}`);let w=[],v=!1;if(l?.includes(":")){for(let we of s.workspaces)if(we.manifest.scripts.has(l)&&(v=!v,v===!1))break}for(let we of A){if(l&&!we.manifest.scripts.has(l)&&!v&&!(await qn.getWorkspaceAccessibleBinaries(we)).has(l)){f(`Excluding ${we.relativeCwd} because it doesn't have a "${l}" script`);continue}if(!(l===r.env.npm_lifecycle_event&&we.cwd===a.cwd)){if(this.include.length>0&&!yv.default.isMatch(G.stringifyIdent(we.anchoredLocator),this.include)&&!yv.default.isMatch(we.relativeCwd,this.include)){f(`Excluding ${we.relativeCwd} because it doesn't match the --include filter`);continue}if(this.exclude.length>0&&(yv.default.isMatch(G.stringifyIdent(we.anchoredLocator),this.exclude)||yv.default.isMatch(we.relativeCwd,this.exclude))){f(`Excluding ${we.relativeCwd} because it matches the --exclude filter`);continue}if(this.publicOnly&&we.manifest.private===!0){f(`Excluding ${we.relativeCwd} because it's a private workspace and --no-private was set`);continue}w.push(we)}}if(w.sort((we,d)=>G.stringifyIdent(we.anchoredLocator).localeCompare(G.stringifyIdent(d.anchoredLocator))),this.dryRun)return 0;let D=this.verbose??(this.context.stdout.isTTY?1/0:0),I=D>0,R=D>1,N=this.parallel?this.jobs==="unlimited"?1/0:Number(this.jobs)||Math.ceil(us.availableParallelism()/2):1,U=N===1?!1:this.parallel,V=U?this.interlaced:!0,ee=(0,E8e.default)(N),te=new Map,ie=new Set,ae=0,ge=null,de=!1,xe=await Wt.start({configuration:r,stdout:this.context.stdout,includePrefix:!1},async we=>{let d=async(be,{commandIndex:Ce})=>{if(de)return-1;!U&&R&&Ce>1&&we.reportSeparator();let Ee=Djt(be,{configuration:r,label:I,commandIndex:Ce}),[he,$]=y8e(we,{prefix:Ee,interlaced:V}),[De,Te]=y8e(we,{prefix:Ee,interlaced:V});try{R&&we.reportInfo(null,`${Ee?`${Ee} `:""}Process started`);let ot=Date.now(),j=await this.cli.run([this.commandName,...this.args],{cwd:be.cwd,stdout:he,stderr:De})||0;he.end(),De.end(),await $,await Te;let rt=Date.now();if(R){let Ne=r.get("enableTimers")?`, completed in ${pe.pretty(r,rt-ot,pe.Type.DURATION)}`:"";we.reportInfo(null,`${Ee?`${Ee} `:""}Process exited (exit code ${j})${Ne}`)}return j===130&&(de=!0,ge=j),j}catch(ot){throw he.end(),De.end(),await $,await Te,ot}};for(let be of w)te.set(be.anchoredLocator.locatorHash,be);for(;te.size>0&&!we.hasErrors();){let be=[];for(let[$,De]of te){if(ie.has(De.anchoredDescriptor.descriptorHash))continue;let Te=!0;if(this.topological||this.topologicalDev){let ot=this.topologicalDev?new Map([...De.manifest.dependencies,...De.manifest.devDependencies]):De.manifest.dependencies;for(let j of ot.values()){let rt=s.tryWorkspaceByDescriptor(j);if(Te=rt===null||!te.has(rt.anchoredLocator.locatorHash),!Te)break}}if(Te&&(ie.add(De.anchoredDescriptor.descriptorHash),be.push(ee(async()=>{let ot=await d(De,{commandIndex:++ae});return te.delete($),ie.delete(De.anchoredDescriptor.descriptorHash),{workspace:De,exitCode:ot}})),!U))break}if(be.length===0){let $=Array.from(te.values()).map(De=>G.prettyLocator(r,De.anchoredLocator)).join(", ");we.reportError(3,`Dependency cycle detected (${$})`);return}let Ce=await Promise.all(be);Ce.forEach(({workspace:$,exitCode:De})=>{De!==0&&we.reportError(0,`The command failed in workspace ${G.prettyLocator(r,$.anchoredLocator)} with exit code ${De}`)});let he=Ce.map($=>$.exitCode).find($=>$!==0);(this.topological||this.topologicalDev)&&typeof he<"u"&&we.reportError(0,"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph")}});return ge!==null?ge:xe.exitCode()}};function y8e(t,{prefix:e,interlaced:r}){let s=t.createStreamReporter(e),a=new Ye.DefaultStream;a.pipe(s,{end:!1}),a.on("finish",()=>{s.end()});let n=new Promise(f=>{s.on("finish",()=>{f(a.active)})});if(r)return[a,n];let l=new Ye.BufferStream;return l.pipe(a,{end:!1}),l.on("finish",()=>{a.end()}),[l,n]}function Djt(t,{configuration:e,commandIndex:r,label:s}){if(!s)return null;let n=`[${G.stringifyIdent(t.anchoredLocator)}]:`,l=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],f=l[r%l.length];return pe.pretty(e,n,f)}var Pjt={commands:[mv,Ev]},xjt=Pjt;var QC=()=>({modules:new Map([["@yarnpkg/cli",hD],["@yarnpkg/core",fD],["@yarnpkg/fslib",cS],["@yarnpkg/libzip",bb],["@yarnpkg/parsers",hS],["@yarnpkg/shell",Tb],["clipanion",BS],["semver",kjt],["typanion",ho],["@yarnpkg/plugin-essentials",nY],["@yarnpkg/plugin-catalog",aY],["@yarnpkg/plugin-compat",hY],["@yarnpkg/plugin-constraints",xY],["@yarnpkg/plugin-dlx",kY],["@yarnpkg/plugin-exec",QY],["@yarnpkg/plugin-file",NY],["@yarnpkg/plugin-git",rY],["@yarnpkg/plugin-github",_Y],["@yarnpkg/plugin-http",MY],["@yarnpkg/plugin-init",UY],["@yarnpkg/plugin-interactive-tools",Lz],["@yarnpkg/plugin-jsr",Mz],["@yarnpkg/plugin-link",Uz],["@yarnpkg/plugin-nm",PJ],["@yarnpkg/plugin-npm",pie],["@yarnpkg/plugin-npm-cli",vie],["@yarnpkg/plugin-pack",EZ],["@yarnpkg/plugin-patch",Rie],["@yarnpkg/plugin-pnp",dJ],["@yarnpkg/plugin-pnpm",Fie],["@yarnpkg/plugin-stage",Hie],["@yarnpkg/pLine truncated
Please report this issue at https://github.com/yarnpkg/berry/issues.`)}process.once("beforeExit",n);try{process.exitCode=42,process.exitCode=await Njt(a,t,{selfPath:r,pluginConfiguration:s})}catch(l){ec.defaultContext.stdout.write(a.error(l)),process.exitCode=1}finally{process.off("beforeExit",n),await fe.rmtempPromise()}}_O(process.argv.slice(2),{cwd:Y.cwd(),selfPath:me.toPortablePath(me.resolve(process.argv[1])),pluginConfiguration:QC()});})();
/**
@license
Copyright (c) 2015, Rebecca Turner
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
/**
@license
Copyright Node.js contributors. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
/**
@license
The MIT License (MIT)
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/**
@license
Copyright Joyent, Inc. and other Node contributors.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*! Bundled license information:
is-number/index.js:
(*!
* is-number <https://github.com/jonschlinkert/is-number>
*
* Copyright (c) 2014-present, Jon Schlinkert.
* Released under the MIT License.
*)
to-regex-range/index.js:
(*!
* to-regex-range <https://github.com/micromatch/to-regex-range>
*
* Copyright (c) 2015-present, Jon Schlinkert.
* Released under the MIT License.
*)
fill-range/index.js:
(*!
* fill-range <https://github.com/jonschlinkert/fill-range>
*
* Copyright (c) 2014-present, Jon Schlinkert.
* Licensed under the MIT License.
*)
is-extglob/index.js:
(*!
* is-extglob <https://github.com/jonschlinkert/is-extglob>
*
* Copyright (c) 2014-2016, Jon Schlinkert.
* Licensed under the MIT License.
*)
is-glob/index.js:
(*!
* is-glob <https://github.com/jonschlinkert/is-glob>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*)
queue-microtask/index.js:
(*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
run-parallel/index.js:
(*! run-parallel. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
git-url-parse/lib/index.js:
(*!
* buildToken
* Builds OAuth token prefix (helper function)
*
* @name buildToken
* @function
* @param {GitUrl} obj The parsed Git url object.
* @return {String} token prefix
*)
object-assign/index.js:
(*
object-assign
(c) Sindre Sorhus
@license MIT
*)
react/cjs/react.production.min.js:
(** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
scheduler/cjs/scheduler.production.min.js:
(** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
react-reconciler/cjs/react-reconciler.production.min.js:
(** @license React v0.26.2
* react-reconciler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
is-windows/index.js:
(*!
* is-windows <https://github.com/jonschlinkert/is-windows>
*
* Copyright © 2015-2018, Jon Schlinkert.
* Released under the MIT License.
*)
negotiator/index.js:
(*!
* negotiator
* Copyright(c) 2012 Federico Romero
* Copyright(c) 2012-2014 Isaac Z. Schlueter
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*)
imurmurhash/imurmurhash.js:
(**
* @preserve
* JS Implementation of incremental MurmurHash3 (r150) (as of May 10, 2013)
*
* @author <a href="mailto:[email protected]">Jens Taylor</a>
* @see http://github.com/homebrewing/brauhaus-diff
* @author <a href="mailto:[email protected]">Gary Court</a>
* @see http://github.com/garycourt/murmurhash-js
* @author <a href="mailto:[email protected]">Austin Appleby</a>
* @see http://sites.google.com/site/murmurhash/
*)
make-fetch-happen/lib/fetch.js:
(**
* @license
* Copyright (c) 2010-2012 Mikeal Rogers
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*)
*/
-16
View File
@@ -1,16 +0,0 @@
approvedGitRepositories:
- "**"
compressionLevel: mixed
defaultSemverRangePrefix: ""
enableGlobalCache: false
enableScripts: true
nodeLinker: node-modules
npmMinimalAgeGate: 3d
yarnPath: .yarn/releases/yarn-4.18.0.cjs
+11 -9
View File
@@ -5,15 +5,15 @@ You are helping develop the Home Assistant frontend. This repository is a TypeSc
## Essential Commands
```bash
yarn lint # ESLint + Prettier + TypeScript + Lit
yarn format # Auto-fix ESLint + Prettier
yarn lint:types # TypeScript compiler, run without file arguments
yarn test # Vitest
yarn dev # App dev server, supports --background/--status/--stop/--logs
yarn dev:serve # Local serving dev server, supports -c core URL, -p port, and dev flags
pnpm lint # ESLint + Prettier + TypeScript + Lit
pnpm format # Auto-fix ESLint + Prettier
pnpm lint:types # TypeScript compiler, run without file arguments
pnpm test # Vitest
pnpm dev # App dev server, supports --background/--status/--stop/--logs
pnpm dev:serve # Local serving dev server, supports -c core URL, -p port, and dev flags
```
Never run `tsc` or `yarn lint:types` with file arguments. When `tsc` receives file arguments, it ignores `tsconfig.json` and can emit `.js` files into `src/`. Always run `yarn lint:types` without arguments. For individual file type checking, rely on editor diagnostics.
Never run `tsc` or `pnpm lint:types` with file arguments. When `tsc` receives file arguments, it ignores `tsconfig.json` and can emit `.js` files into `src/`. Always run `pnpm lint:types` without arguments. For individual file type checking, rely on editor diagnostics.
## Architecture
@@ -33,10 +33,11 @@ Never run `tsc` or `yarn lint:types` with file arguments. When `tsc` receives fi
- Do not query or manipulate DOM manually when Lit decorators, component refs, or render state are appropriate.
- Scope styles to components, use theme custom properties, and keep layouts mobile-first and RTL-safe.
- All user-facing text must be localized through the translation system.
- Do not write tests just because you changed some code. Write a test when there is real logic that could break without anyone noticing, and explain what the test protects.
## Project Skills
Detailed guidance lives in project skills under `.agents/skills/`. Load the matching skill before detailed implementation or review:
Detailed guidance lives in `.agents/skills/<name>/SKILL.md`. Load every matching skill before detailed implementation or review. For reviews, load `ha-frontend-review` alongside all companions that apply to the changed code or behavior:
- `ha-frontend-contexts`: Lit contexts, `hass` migration, and rerender-sensitive state access.
- `ha-frontend-components`: dialogs, forms, alerts, shortcuts, tooltips, panels, and Lovelace cards.
@@ -46,7 +47,8 @@ Detailed guidance lives in project skills under `.agents/skills/`. Load the matc
- `ha-frontend-styling`: theme variables, spacing tokens, responsive layout, RTL, and view transitions.
- `ha-frontend-testing`: lint, typecheck, Vitest, Playwright e2e dev servers, and benchmarks.
- `ha-frontend-user-facing-text`: localization, terminology, sentence case, and Home Assistant text style.
- `ha-frontend-review`: PR template use, review checklist, and recurring review issues.
- `ha-frontend-review`: PR template use, existing review feedback, review checklist, recurring issues, and UI/UX evidence including gallery specifications.
- `ha-frontend-ux-readiness`: UI/UX routing that complements frontend review for new user experiences.
- `ha-frontend-gallery`: gallery pages, demos, sidebar structure, content, and verification.
- `ha-frontend-demo`: standalone demo structure, configurations, navigation, shared stubs, and verification.
+169 -162
View File
@@ -1,194 +1,201 @@
Apache License
==============
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
### Terms and Conditions for use, reproduction, and distribution
1. Definitions.
#### 1. Definitions
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
“License” shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
“Licensor” shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
“Legal Entity” shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, “control” means **(i)** the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the
outstanding shares, or **(iii)** beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
“You” (or “Your”) shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
“Source” form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
“Object” form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
“Work” shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
“Derivative Works” shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
“Contribution” shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
“submitted” means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as “Not a Contribution.”
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
#### 2. Grant of Copyright License
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
#### 3. Grant of Patent License
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
#### 4. Redistribution
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of
this License; and
* **(b)** You must cause any modified files to carry prominent notices stating that You
changed the files; and
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
#### 5. Submission of Contributions
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
#### 6. Trademarks
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
#### 7. Disclaimer of Warranty
END OF TERMS AND CONDITIONS
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
APPENDIX: How to apply the Apache License to your work.
#### 8. Limitation of Liability
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
Copyright [yyyy] [name of copyright owner]
#### 9. Accepting Warranty or Additional Liability
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
http://www.apache.org/licenses/LICENSE-2.0
_END OF TERMS AND CONDITIONS_
### APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets `[]` replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same “printed page” as the copyright notice for easier identification within
third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+1 -1
View File
@@ -12,7 +12,7 @@ This is the repository for the official [Home Assistant](https://home-assistant.
- Initial setup: `script/setup`
- Development: [Instructions](https://developers.home-assistant.io/docs/frontend/development/)
- Production build: `yarn build`
- Production build: `pnpm build`
- Gallery: `cd gallery && script/develop_gallery`
## Frontend development
+9 -1
View File
@@ -34,6 +34,14 @@ In production, the following responsibilities are added:
- Minify HTML
- Bundle multiple imports so that the browser can fetch less files
- Generate a second version that is ES5 compatible
- Generate a second version that is compatible with older browsers (legacy build)
Configuration for all these steps are specified in [bundle.js](bundle.js).
## Auditing browser support changes
`node build-scripts/list-plugins-and-polyfills.js` prints, per browserslist
environment (modern/legacy), the Babel transforms preset-env enables and the
Core-JS polyfills that may be injected — as collapsible markdown ready to
paste into a PR. Use it to show the bundle impact when changing
`.browserslistrc` or the Babel configuration.
+8 -8
View File
@@ -78,9 +78,9 @@ const parseArgs = (argv) => {
};
const hints = () =>
" Stop: yarn build --stop\n" +
" Status: yarn build --status\n" +
" Logs: yarn build --logs\n";
" Stop: pnpm build --stop\n" +
" Status: pnpm build --status\n" +
" Logs: pnpm build --logs\n";
const devCommand = (suite) => {
switch (suite) {
@@ -103,9 +103,9 @@ const releaseBuild = (token) => releaseProcessRecord(lockFile, token);
const stopCommandFor = (owner) =>
owner?.kind === "build"
? "yarn build --stop"
? "pnpm build --stop"
: owner?.kind === "dev"
? `yarn ${devCommand(owner.suite)} --stop`
? `pnpm ${devCommand(owner.suite)} --stop`
: undefined;
const acquireBuild = async (modern, foreground) => {
@@ -164,9 +164,9 @@ const reportExisting = (existing) => {
process.stdout.write(
`Dev server (${existing.suite}) already running` +
`${existing.pid ? ` (pid ${existing.pid})` : ""}.\n` +
` Stop: yarn ${command} --stop\n` +
` Status: yarn ${command} --status\n` +
` Logs: yarn ${command} --logs\n`
` Stop: pnpm ${command} --stop\n` +
` Status: pnpm ${command} --status\n` +
` Logs: pnpm ${command} --logs\n`
);
return;
}
+8 -8
View File
@@ -1,15 +1,15 @@
{
"_comment": "Initial JS budget (raw/uncompressed bytes) for the cold-load critical entrypoints. Enforced by build-scripts/check-bundle-size.cjs in CI. Re-seed after an intentional change with `--update --headroom=<percent>`.",
"frontend-modern": {
"app": 595204,
"core": 57741,
"authorize": 576928,
"onboarding": 685964
"app": 624240,
"core": 55144,
"authorize": 594400,
"onboarding": 705499
},
"frontend-legacy": {
"app": 861452,
"core": 258557,
"authorize": 834356,
"onboarding": 1001360
"app": 776696,
"core": 188309,
"authorize": 763316,
"onboarding": 879807
}
}
+52 -12
View File
@@ -31,13 +31,44 @@ module.exports.emptyPackages = ({ isLandingPageBuild }) =>
),
].filter(Boolean);
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
// MapLibre runs its tile work in a worker that it spawns from a URL. The
// package ships that worker as untranspiled ES2022, so it is bundled here as
// its own entry per build target, like the rest of MapLibre. One self-contained
// file: the worker cannot import chunks, and a classic-compatible script runs
// wherever the main bundle does, module workers or not. The layer keeps the
// page's polyfills out of it; see `babelOptions`.
const MAP_WORKER_NAME = "maplibre-gl-worker";
module.exports.mapWorkerName = MAP_WORKER_NAME;
module.exports.mapWorkerEntry = () => ({
[MAP_WORKER_NAME]: {
import: "maplibre-gl/dist/maplibre-gl-worker.mjs",
chunkLoading: false,
layer: "worker",
},
});
// MapLibre is handed the URL at build time, so the name cannot carry a content
// hash. The frontend version stands in for it, in the file name rather than a
// query string: the service worker precaches everything under the bundle
// directory as immutable and matches it with the query stripped, so a `?v=`
// would keep serving the worker of the first version it ever cached.
module.exports.mapWorkerFilename = () =>
`${MAP_WORKER_NAME}.${env.version()}.js`;
module.exports.definedVars = ({
isProdBuild,
latestBuild,
publicPath,
defineOverlay,
}) => ({
__DEV__: !isProdBuild,
__BUILD__: JSON.stringify(latestBuild ? "modern" : "legacy"),
__VERSION__: JSON.stringify(env.version()),
__DEMO__: false,
__BACKWARDS_COMPAT__: false,
__STATIC_PATH__: "/static/",
__MAPLIBRE_WORKER_URL__: JSON.stringify(
`${publicPath}${module.exports.mapWorkerFilename()}`
),
__HASS_URL__: `\`${
"HASS_URL" in process.env
? process.env.HASS_URL
@@ -63,8 +94,10 @@ module.exports.htmlMinifierOptions = {
};
module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
safari10: !latestBuild,
ecma: latestBuild ? 2015 : 5,
// Highest syntax the minifier may emit; it never downlevels. Every browser
// in [modern] is well past ES2020 (universal since spring 2020); the
// [legacy] floors (Chrome 59 / Safari 12) top out at ES2017.
ecma: latestBuild ? 2020 : 2017,
module: latestBuild,
format: { comments: false },
sourceMap: !isTestBuild,
@@ -83,7 +116,7 @@ module.exports.swcOptions = () => ({
},
});
module.exports.babelOptions = ({ latestBuild, isTestBuild, sw }) => ({
module.exports.babelOptions = ({ latestBuild, isTestBuild, sw, worker }) => ({
babelrc: false,
compact: false,
assumptions: {
@@ -119,7 +152,7 @@ module.exports.babelOptions = ({ latestBuild, isTestBuild, sw }) => ({
ignoreModuleNotFound: true,
},
],
// Import helpers and regenerator from runtime package.
// Import helpers from runtime package.
// `moduleName` is pinned so helpers resolve from `@babel/runtime`: the
// corejs3 polyfill provider above otherwise redirects them to the
// (uninstalled) `@babel/runtime-corejs3`, which preset-env used to suppress
@@ -137,9 +170,11 @@ module.exports.babelOptions = ({ latestBuild, isTestBuild, sw }) => ({
],
sourceMaps: !isTestBuild,
overrides: [
{
// Add plugin to inject various polyfills, excluding the polyfills
// themselves to prevent self-injection.
// Add plugin to inject various polyfills, excluding the polyfills
// themselves to prevent self-injection. Not in a worker: these polyfill
// the page (Intl locale data, DOM APIs) and assume one, so injecting them
// into a worker's graph makes its bootstrap fail before it starts.
!worker && {
plugins: [
[
path.join(BABEL_PLUGINS, "custom-polyfill-plugin.js"),
@@ -153,8 +188,6 @@ module.exports.babelOptions = ({ latestBuild, isTestBuild, sw }) => ({
"@lit-labs/virtualizer/polyfills",
"@webcomponents/scoped-custom-element-registry",
"element-internals-polyfill",
"proxy-polyfill",
"unfetch",
].map((p) => new RegExp(`/node_modules/${p}/`)),
],
},
@@ -171,7 +204,7 @@ module.exports.babelOptions = ({ latestBuild, isTestBuild, sw }) => ({
"@formatjs/(?:ecma402-abstract|intl-\\w+)",
].map((p) => new RegExp(`/node_modules/${p}/`)),
},
],
].filter(Boolean),
});
const nameSuffix = (latestBuild) => (latestBuild ? "-modern" : "-legacy");
@@ -221,6 +254,7 @@ module.exports.config = {
onboarding: "./src/entrypoints/onboarding.ts",
core: "./src/entrypoints/core.ts",
"custom-panel": "./src/entrypoints/custom-panel.ts",
...module.exports.mapWorkerEntry(),
},
outputPath: outputPath(paths.app_output_root, latestBuild),
publicPath: publicPath(latestBuild),
@@ -237,6 +271,7 @@ module.exports.config = {
name: "demo" + nameSuffix(latestBuild),
entry: {
main: path.resolve(paths.demo_dir, "src/entrypoint.ts"),
...module.exports.mapWorkerEntry(),
},
outputPath: outputPath(paths.demo_output_root, latestBuild),
publicPath: publicPath(latestBuild),
@@ -257,11 +292,13 @@ module.exports.config = {
media: path.resolve(paths.cast_dir, "src/media/entrypoint.ts"),
};
// Only the receiver renders maps, and it is built for modern browsers only
if (latestBuild) {
entry.receiver = path.resolve(
paths.cast_dir,
"src/receiver/entrypoint.ts"
);
Object.assign(entry, module.exports.mapWorkerEntry());
}
return {
@@ -277,16 +314,18 @@ module.exports.config = {
};
},
gallery({ isProdBuild, latestBuild }) {
gallery({ isProdBuild, latestBuild, isTestBuild }) {
return {
name: "gallery" + nameSuffix(latestBuild),
entry: {
entrypoint: path.resolve(paths.gallery_dir, "src/entrypoint.js"),
...module.exports.mapWorkerEntry(),
},
outputPath: outputPath(paths.gallery_output_root, latestBuild),
publicPath: publicPath(latestBuild),
isProdBuild,
latestBuild,
isTestBuild,
defineOverlay: {
__DEMO__: true,
},
@@ -320,6 +359,7 @@ module.exports.config = {
paths.e2eTestApp_dir,
"src/onboarding-entrypoint.ts"
),
...module.exports.mapWorkerEntry(),
},
outputPath: outputPath(paths.e2eTestApp_output_root, latestBuild),
publicPath: publicPath(latestBuild),
+6 -6
View File
@@ -18,7 +18,7 @@
// health demo, gallery, e2e-app: a fixed port plus the /__ha_dev_status
// endpoint each dev server exposes (see runDevServer in
// build-scripts/gulp/rspack.js).
// process app (yarn dev) and app-serve (yarn dev:serve): plain yarn dev has
// process app (pnpm dev) and app-serve (pnpm dev:serve): plain pnpm dev has
// no port, so these treat the first "Build done" log line as ready.
import fs from "node:fs";
@@ -61,7 +61,7 @@ const developAndServeScript = path.join(
);
const logDir = path.join(buildCacheDir, "ha-dev-server");
// Each suite names its yarn alias (for hints), a liveness model, and how to
// Each suite names its pnpm alias (for hints), a liveness model, and how to
// spawn it. health suites carry a fixed port; process suites carry the log line
// that means "ready" and, for app-serve, forward extra args to the script.
const SUITES = new Map([
@@ -236,7 +236,7 @@ const readSuite = (suite) => {
};
const hints = (suite) => {
const alias = `yarn ${SUITES.get(suite).alias}`;
const alias = `pnpm ${SUITES.get(suite).alias}`;
return (
` Stop: ${alias} --stop\n` +
` Status: ${alias} --status\n` +
@@ -255,7 +255,7 @@ const reportProcessConflict = (suite, existing) => {
if (existing?.kind === "build") {
process.stdout.write(
`Frontend build already running${existing.pid ? ` (pid ${existing.pid})` : ""}. ` +
"Stop it with yarn build --stop.\n"
"Stop it with pnpm build --stop.\n"
);
return;
}
@@ -269,9 +269,9 @@ const reportProcessConflict = (suite, existing) => {
const stopCommandFor = (owner) =>
owner?.kind === "build"
? "yarn build --stop"
? "pnpm build --stop"
: owner?.kind === "dev"
? `yarn ${SUITES.get(owner.suite)?.alias ?? "dev"} --stop`
? `pnpm ${SUITES.get(owner.suite)?.alias ?? "dev"} --stop`
: undefined;
const acquireSuiteForStart = async (suite) => {
+10
View File
@@ -0,0 +1,10 @@
// @ts-check
import { noUnusedElementImport } from "./no-unused-element-import.mjs";
export default {
meta: { name: "eslint-plugin-ha" },
rules: {
"no-unused-element-import": noUnusedElementImport,
},
};
@@ -0,0 +1,188 @@
// @ts-check
import fs from "node:fs";
import path from "node:path";
const TAG_PATTERN =
/@customElement\(\s*["'`]([a-z0-9_-]+)["'`]|customElements\.define\(\s*["'`]([a-z0-9_-]+)["'`]/g;
const EXTENSIONS = /\.(ts|js)$/;
// Entry points register the root element that the served HTML renders.
const ENTRY_POINT = /(^|[\\/])(entrypoints[\\/]|entrypoint\.(ts|js)$)/;
// These resolve a tag from config at runtime, so they register every candidate
// they may be asked for.
const RUNTIME_REGISTRY =
/[\\/]create-element[\\/]|createLovelaceElement\(|getLovelaceElementClass\(/;
/** @type {Map<string, string[]>} */
const tagCache = new Map();
/** Tags the module at `file` registers when imported. */
const registeredTags = (file) => {
let tags = tagCache.get(file);
if (!tags) {
try {
const source = fs.readFileSync(file, "utf8");
tags = [...source.matchAll(TAG_PATTERN)].map((m) => m[1] || m[2]);
} catch {
tags = [];
}
tagCache.set(file, tags);
}
return tags;
};
const isFile = (candidate) => {
try {
return fs.statSync(candidate).isFile();
} catch {
return false;
}
};
const resolveModule = (fromFile, request) => {
const base = path.resolve(path.dirname(fromFile), request);
return [
base,
`${base}.ts`,
`${base}.js`,
base.replace(/\.js$/, ".ts"),
path.join(base, "index.ts"),
path.join(base, "index.js"),
].find((candidate) => EXTENSIONS.test(candidate) && isFile(candidate));
};
// `hui-${type}-card` or "state-card-" + domain never spell the tag out.
const buildsTagAtRuntime = (source, tag) => {
const segments = tag.split("-");
for (let end = 1; end < segments.length; end++) {
const prefix = `${segments.slice(0, end).join("-")}-`;
if (
source.includes(`\`${prefix}\${`) ||
source.includes(`"${prefix}" +`) ||
source.includes(`'${prefix}' +`)
) {
return true;
}
}
return false;
};
// Plain substring matching, so <ha-icon-button> counts as a use of ha-icon.
// That direction is deliberate: it misses dead imports rather than asking for
// a removal that breaks registration.
const usesTag = (body, tag) => body.includes(tag);
// A gallery page registers the elements its sibling markdown demos render, so
// that markdown is part of what the module is used by.
const siblingMarkup = (file) => {
const markdown = file.replace(EXTENSIONS, ".markdown");
try {
return fs.readFileSync(markdown, "utf8");
} catch {
return "";
}
};
/** Blanks out the given ranges so an import path cannot count as a usage. */
const withoutRanges = (source, ranges) => {
let result = source;
for (const [start, end] of ranges) {
result =
result.slice(0, start) + " ".repeat(end - start) + result.slice(end);
}
return result;
};
/**
* Side-effect imports register a custom element. ESLint's unused-import rules
* cannot judge them — there is no binding to be unused — so a registration
* outlives the template that needed it and nothing reports the dead import.
*
* Deliberately not fixable: removing the import is only safe once every file
* that renders the element imports it itself, which this rule cannot see.
*
* Off in eslint.config.mjs while a backlog of those paired cases remains;
* `pnpm lint:element-imports` enables it as a warning to list them. Flip it to
* "error" there once the list is empty.
*
* No disable comments while it is off: ESLint reports them as unused
* directives, which fails lint:eslint. Imports that must stay get theirs in
* the change that turns the rule on.
*/
export const noUnusedElementImport = {
meta: {
type: "suggestion",
docs: {
description:
"Disallow side-effect imports of a custom element the importing file never uses",
},
schema: [],
messages: {
unused:
'"{{request}}" only registers <{{tags}}>, which this file never uses. Remove the import, adding it to whichever file renders the element if that file relies on this registration.',
},
},
create(context) {
const filename = context.filename;
if (!EXTENSIONS.test(filename) || ENTRY_POINT.test(filename)) {
return {};
}
return {
Program(program) {
const imports = program.body.filter(
(node) => node.type === "ImportDeclaration"
);
const sideEffectImports = imports.filter(
(node) =>
node.specifiers.length === 0 &&
typeof node.source.value === "string" &&
node.source.value.startsWith(".")
);
if (!sideEffectImports.length) {
return;
}
const source = context.sourceCode.getText();
if (RUNTIME_REGISTRY.test(filename) || RUNTIME_REGISTRY.test(source)) {
return;
}
// Every import declaration, not just the side-effect ones: a module
// path is never a usage, and `import type { HaCard } from "./ha-card"`
// would otherwise pass off its own path as one.
const body =
withoutRanges(
source,
imports.map((node) => node.range)
) + siblingMarkup(filename);
for (const node of sideEffectImports) {
const request = node.source.value;
const target = resolveModule(filename, request);
if (!target) {
continue;
}
// No tags means no registration to judge: styles, polyfills, mocks.
const tags = registeredTags(target);
if (
!tags.length ||
tags.some(
(tag) => usesTag(body, tag) || buildsTagAtRuntime(body, tag)
)
) {
continue;
}
context.report({
node,
messageId: "unused",
data: { request, tags: tags.join(">, <") },
});
}
},
};
},
};
+29 -8
View File
@@ -5,6 +5,7 @@ import mapStream from "map-stream";
import transform from "gulp-json-transform";
import { LokaliseApi } from "@lokalise/node-api";
import JSZip from "jszip";
import { SERVICE_DOMAINS } from "./gen-demo-core-data.js";
const inDir = "translations";
const inDirFrontend = `${inDir}/frontend`;
@@ -51,15 +52,34 @@ function convertBackendTranslations(data, _file) {
if (!data.component) {
return output;
}
// Keep the entity domains and the domains with automation triggers or
// conditions, so the demo can show states and describe automations. Only
// keep the services of the domains whose services the demo mocks.
Object.keys(data.component).forEach((domain) => {
if (!("entity_component" in data.component[domain])) {
const {
entity_component,
services,
triggers,
conditions,
selector,
title,
} = data.component[domain];
if (
!entity_component &&
!triggers &&
!conditions &&
!SERVICE_DOMAINS.includes(domain)
) {
return;
}
output.component[domain] = { entity_component: {} };
Object.keys(data.component[domain].entity_component).forEach((key) => {
output.component[domain].entity_component[key] =
data.component[domain].entity_component[key];
});
output.component[domain] = {
entity_component,
services: SERVICE_DOMAINS.includes(domain) ? services : undefined,
triggers,
conditions,
selector,
title,
};
});
return output;
}
@@ -155,8 +175,9 @@ gulp.task("fetch-lokalise", async function () {
fs.mkdir(inDirBackend, { recursive: true }),
]);
// The backend project only provides entity_component translations, which are
// merged into the demo, gallery, cast and e2e builds. The shipped app fetches
// The backend project only provides the translations the mocked backend
// needs (see convertBackendTranslations), which are merged into the demo,
// gallery, cast and e2e builds. The shipped app fetches
// them live from core, so builds that only produce the app (release, release
// landing-page) can skip this second, whole-project export to save time.
const projects = Object.entries(lokaliseProjects).filter(
+2 -2
View File
@@ -25,7 +25,7 @@ const SAFARI_TO_MACOS = {
16: [11, 0, 0],
17: [12, 0, 0],
18: [13, 0, 0],
26: [26, 0, 0],
26: [14, 6, 0],
};
const getCommonTemplateVars = () => {
@@ -89,7 +89,7 @@ const minifyHtml = (content, ext) => {
...htmlMinifierOptions,
conservativeCollapse: false,
minifyJS: terserOptions({
latestBuild: false, // Shared scripts should be ES5
latestBuild: false, // Shared scripts must satisfy the legacy targets
isTestBuild: true, // Don't need source maps
}),
}).then((wrapped) =>
@@ -1,7 +1,6 @@
// Task to download the latest Lokalise translations from the nightly workflow artifacts
import { createOAuthDeviceAuth } from "@octokit/auth-oauth-device";
import { retry } from "@octokit/plugin-retry";
import { Octokit } from "@octokit/rest";
import { deleteAsync } from "del";
import { mkdir, readFile, writeFile } from "fs/promises";
@@ -10,11 +9,20 @@ import jszip from "jszip";
import path from "path";
import process from "process";
import { extract } from "tar";
import {
RetryableError,
withRetry,
} from "../../.github/scripts/github-retry.mts";
type Artifact = Awaited<
ReturnType<Octokit["rest"]["actions"]["listArtifactsForRepo"]>
>["data"]["artifacts"][number];
const MAX_AGE = 24; // hours
const OWNER = "home-assistant";
const REPO = "frontend";
const WORKFLOW_NAME = "nightly.yaml";
const BRANCH = "dev";
const ARTIFACT_NAME = "translations";
const CLIENT_ID = "Iv1.3914e28cb27834d1";
const EXTRACT_DIR = "translations";
@@ -36,11 +44,16 @@ gulp.task("fetch-nightly-translations", async function () {
// Read current translations artifact info if it exists,
// and stop if they are not old enough
let currentArtifact;
let currentArtifact: Artifact | null;
try {
currentArtifact = JSON.parse(await readFile(ARTIFACT_FILE, "utf-8"));
const artifact: Artifact = JSON.parse(
await readFile(ARTIFACT_FILE, "utf-8")
);
currentArtifact = artifact;
const currentAge =
(Date.now() - Date.parse(currentArtifact.created_at)) / 3600000;
(Date.now() - Date.parse(artifact.created_at ?? "")) / 3600000;
if (currentAge < MAX_AGE) {
console.log(
"Keeping current translations (only %s hours old)",
@@ -63,19 +76,19 @@ gulp.task("fetch-nightly-translations", async function () {
}
console.warn(
"Failed to fetch nightly translations, continuing with English only:",
err?.message || err
err instanceof Error ? err.message : err
);
}
});
async function fetchTranslations(currentArtifact) {
async function fetchTranslations(currentArtifact: Artifact | null) {
// To store file writing promises
const createExtractDir = mkdir(EXTRACT_DIR, { recursive: true });
const writings = [];
const writings: Promise<void>[] = [];
// Authenticate to GitHub using GitHub action token if it exists,
// otherwise look for a saved user token or generate a new one if none
let tokenAuth;
let tokenAuth: { token: string };
if (process.env.GITHUB_TOKEN) {
tokenAuth = { token: process.env.GITHUB_TOKEN };
} else {
@@ -104,69 +117,86 @@ async function fetchTranslations(currentArtifact) {
});
tokenAuth = await auth({ type: "oauth" });
writings.push(
createExtractDir.then(
createExtractDir.then(() =>
writeFile(TOKEN_FILE, JSON.stringify(tokenAuth, null, 2))
)
);
}
}
// Authenticate with token and request workflow runs from GitHub
console.log("Fetching new translations...");
const octokit = new (Octokit.plugin(retry))({
// Authenticate with token and find the newest translations artifact
const octokit = new Octokit({
userAgent: "Fetch Nightly Translations",
auth: tokenAuth.token,
});
const workflowRunsResponse = await octokit.rest.actions.listWorkflowRuns({
owner: OWNER,
repo: REPO,
workflow_id: WORKFLOW_NAME,
status: "success",
event: "schedule",
per_page: 1,
exclude_pull_requests: true,
});
if (workflowRunsResponse.data.total_count === 0) {
throw Error("No successful nightly workflow runs found");
}
const latestNightlyRun = workflowRunsResponse.data.workflow_runs[0];
// Only the nightly workflow uploads this artifact. Requiring a run from this
// repository's own branch excludes artifacts uploaded by fork pull requests.
const latestArtifact = await withRetry(
"translations artifact lookup",
async () => {
const { data } = await octokit.rest.actions.listArtifactsForRepo({
owner: OWNER,
repo: REPO,
name: ARTIFACT_NAME,
per_page: 10,
});
// Stop if current is already the latest, otherwise Find the translations artifact
if (currentArtifact?.workflow_run.id === latestNightlyRun.id) {
const artifact = data.artifacts.find(
({ expired, workflow_run: run }) =>
!expired &&
run?.head_branch === BRANCH &&
run.head_repository_id === run.repository_id
);
if (!artifact) {
throw new RetryableError(
`No ${ARTIFACT_NAME} artifact found from ${BRANCH}`
);
}
return artifact;
}
);
console.log(
"Latest translations artifact is %s from workflow run %s (%s)",
latestArtifact.id,
latestArtifact.workflow_run?.id,
latestArtifact.created_at
);
// Stop if current is already the latest
if (currentArtifact?.id === latestArtifact.id) {
console.log("Stopping because current translations are still the latest");
return;
}
const latestArtifact = (
await octokit.actions.listWorkflowRunArtifacts({
owner: OWNER,
repo: REPO,
run_id: latestNightlyRun.id,
})
).data.artifacts.find((artifact) => artifact.name === ARTIFACT_NAME);
if (!latestArtifact) {
throw Error("Latest nightly workflow run has no translations artifact");
}
// Remove the current translations
const deleteCurrent = Promise.all(writings).then(
const deleteCurrent = Promise.all(writings).then(() =>
deleteAsync([`${EXTRACT_DIR}/*`, `!${ARTIFACT_FILE}`, `!${TOKEN_FILE}`])
);
// Get the download URL and follow the redirect to download (stored as ArrayBuffer)
const downloadResponse = await octokit.actions.downloadArtifact({
owner: OWNER,
repo: REPO,
artifact_id: latestArtifact.id,
archive_format: "zip",
});
if (downloadResponse.status !== 200) {
const downloadResponse = await withRetry("translations download", () =>
octokit.rest.actions.downloadArtifact({
owner: OWNER,
repo: REPO,
artifact_id: latestArtifact.id,
archive_format: "zip",
})
);
// Octokit types the redirect, but fetch follows it to the archive
if ((downloadResponse.status as number) !== 200) {
throw Error("Failure downloading translations artifact");
}
// Artifact is a tarball, but GitHub adds it to a zip file
console.log("Unpacking downloaded translations...");
const zip = await jszip.loadAsync(downloadResponse.data);
const zip = await jszip.loadAsync(downloadResponse.data as ArrayBuffer);
await deleteCurrent;
const extractStream = zip.file(/.*/)[0].nodeStream().pipe(extract());
await new Promise((resolve, reject) => {
+14 -41
View File
@@ -4,6 +4,7 @@ import fs from "fs-extra";
import gulp from "gulp";
import path from "path";
import paths from "../paths.cjs";
import { ensureMapAssets, mapAssetsDir } from "./map-assets.js";
const npmPath = (...parts) =>
path.resolve(paths.root_dir, "node_modules", ...parts);
@@ -41,37 +42,6 @@ function copyMdiIcons(staticDir) {
fs.copySync(polyPath("build/mdi"), staticPath("mdi"));
}
function copyPolyfills(staticDir) {
const staticPath = genStaticPath(staticDir);
// For custom panels using ES5 builds that don't use Babel 7+
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"),
staticPath("polyfills/")
);
// Web Component polyfills and adapters
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js"),
staticPath("polyfills/")
);
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js.map"),
staticPath("polyfills/")
);
// Lit polyfill support
fs.copySync(
npmPath("lit/polyfill-support.js"),
path.join(staticPath("polyfills/"), "lit-polyfill-support.js")
);
// dialog-polyfill css
copyFileDir(
npmPath("dialog-polyfill/dialog-polyfill.css"),
staticPath("polyfills/")
);
}
function copyFonts(staticDir) {
const staticPath = genStaticPath(staticDir);
// Local fonts
@@ -89,7 +59,7 @@ function copyQrScannerWorker(staticDir) {
copyFileDir(npmPath("qr-scanner/qr-scanner-worker.min.js"), staticPath("js"));
}
function copyMapPanel(staticDir) {
async function copyMapPanel(staticDir) {
const staticPath = genStaticPath(staticDir);
copyFileDir(
npmPath("leaflet/dist/leaflet.css"),
@@ -103,6 +73,12 @@ function copyMapPanel(staticDir) {
npmPath("leaflet/dist/images"),
staticPath("images/leaflet/images/")
);
// Style, glyphs and sprites for the vector base map
await ensureMapAssets();
fs.copySync(mapAssetsDir, staticPath("map/"));
// Controls and popups of the native MapLibre engine
copyFileDir(npmPath("maplibre-gl/dist/maplibre-gl.css"), staticPath("map/"));
}
function copyZXingWasm(staticDir) {
@@ -132,14 +108,13 @@ gulp.task("copy-static-app", async () => {
const staticDir = paths.app_output_static;
// Basic static files
fs.copySync(polyPath("public"), paths.app_output_root);
copyPolyfills(staticDir);
copyFonts(staticDir);
copyTranslations(staticDir);
copyLocaleData(staticDir);
copyMdiIcons(staticDir);
// Panel assets
copyMapPanel(staticDir);
await copyMapPanel(staticDir);
// Qr Scanner assets
copyZXingWasm(staticDir);
@@ -154,8 +129,7 @@ gulp.task("copy-static-demo", async () => {
);
// Copy demo static files
fs.copySync(path.resolve(paths.demo_dir, "public"), paths.demo_output_root);
copyPolyfills(paths.demo_output_static);
copyMapPanel(paths.demo_output_static);
await copyMapPanel(paths.demo_output_static);
copyFonts(paths.demo_output_static);
copyTranslations(paths.demo_output_static);
copyLocaleData(paths.demo_output_static);
@@ -167,8 +141,7 @@ gulp.task("copy-static-cast", async () => {
fs.copySync(polyPath("public/static"), paths.cast_output_static);
// Copy cast static files
fs.copySync(path.resolve(paths.cast_dir, "public"), paths.cast_output_root);
copyPolyfills(paths.cast_output_static);
copyMapPanel(paths.cast_output_static);
await copyMapPanel(paths.cast_output_static);
copyFonts(paths.cast_output_static);
copyTranslations(paths.cast_output_static);
copyLocaleData(paths.cast_output_static);
@@ -184,7 +157,7 @@ gulp.task("copy-static-gallery", async () => {
paths.gallery_output_root
);
copyMapPanel(paths.gallery_output_static);
await copyMapPanel(paths.gallery_output_static);
copyFonts(paths.gallery_output_static);
copyTranslations(paths.gallery_output_static);
copyLocaleData(paths.gallery_output_static);
@@ -200,6 +173,7 @@ gulp.task("copy-static-landing-page", async () => {
copyFonts(paths.landingPage_output_static);
copyTranslations(paths.landingPage_output_static);
copyLocaleData(paths.landingPage_output_static);
});
gulp.task("copy-static-e2e-test-app", async () => {
@@ -214,8 +188,7 @@ gulp.task("copy-static-e2e-test-app", async () => {
fs.copySync(e2ePublic, paths.e2eTestApp_output_root);
}
copyPolyfills(paths.e2eTestApp_output_static);
copyMapPanel(paths.e2eTestApp_output_static);
await copyMapPanel(paths.e2eTestApp_output_static);
copyFonts(paths.e2eTestApp_output_static);
copyTranslations(paths.e2eTestApp_output_static);
copyLocaleData(paths.e2eTestApp_output_static);
+422
View File
@@ -0,0 +1,422 @@
// Generates the service, trigger and condition descriptions the demo and
// gallery serve instead of a backend, from the files in Home Assistant Core.
import gulp from "gulp";
import { CORE_SCHEMA, load, mergeTag } from "js-yaml";
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import process from "node:process";
import prettier from "prettier";
import paths from "../paths.cjs";
const CORE_URL =
process.env.CORE_COMPONENTS_URL ||
"https://raw.githubusercontent.com/home-assistant/core/refs/heads/dev/homeassistant/components";
// Integrations whose services the mocked backend provides
export const SERVICE_DOMAINS = [
"alarm_control_panel",
"automation",
"button",
"calendar",
"camera",
"climate",
"conversation",
"counter",
"cover",
"device_tracker",
"fan",
"frontend",
"group",
"homeassistant",
"humidifier",
"image_processing",
"input_boolean",
"input_button",
"input_datetime",
"input_number",
"input_select",
"input_text",
"lawn_mower",
"light",
"lock",
"logger",
"media_player",
"notify",
"number",
"persistent_notification",
"person",
"recorder",
"remote",
"scene",
"schedule",
"script",
"select",
"siren",
"switch",
"system_log",
"text",
"timer",
"todo",
"tts",
"update",
"vacuum",
"valve",
"water_heater",
"weather",
"zone",
];
// Services that return data. Core sets this when it registers a service, it is
// not part of services.yaml. The value is whether the response is optional.
const RESPONSE_SERVICES = {
"calendar.get_events": false,
"conversation.process": true,
"media_player.browse_media": false,
"media_player.search_media": false,
"recorder.get_statistics": false,
"schedule.get_schedule": false,
"todo.get_items": false,
"weather.get_forecasts": false,
};
// Services that are still in services.yaml, but that core no longer registers
const UNREGISTERED_SERVICES = ["weather.get_forecast"];
// Integrations that provide the new style triggers and conditions
const AUTOMATION_PLATFORM_DOMAINS = [
"air_quality",
"alarm_control_panel",
"assist_satellite",
"battery",
"button",
"calendar",
"climate",
"counter",
"cover",
"door",
"doorbell",
"event",
"fan",
"garage_door",
"gate",
"humidifier",
"humidity",
"illuminance",
"lawn_mower",
"light",
"lock",
"media_player",
"moisture",
"moon",
"motion",
"occupancy",
"power",
"remote",
"scene",
"schedule",
"select",
"siren",
"sun",
"switch",
"temperature",
"text",
"timer",
"todo",
"update",
"vacuum",
"valve",
"vibration",
"water_heater",
"window",
"zone",
];
// YAML 1.2 with merge keys, which matches how core reads these files
const YAML_SCHEMA = CORE_SCHEMA.withTags([mergeTag]);
const HEADER = `// This file is auto-generated from Home Assistant Core. Do not edit by hand.
// Regenerate with \`script/gen_demo_core_data\`.`;
const fetchCoreFile = async (domain, file) => {
const url = `${CORE_URL}/${domain}/${file}`;
const response = await fetch(url);
if (response.status === 404) {
return undefined;
}
if (!response.ok) {
throw new Error(`Failed to fetch ${url}: ${response.status}`);
}
return response.text();
};
// Fetches a file of every domain, keyed by domain
const fetchCoreFiles = async (domains, file) =>
Object.fromEntries(
await Promise.all(
domains.map(async (domain) => [domain, await fetchCoreFile(domain, file)])
)
);
const parseYaml = (content) => load(content, { schema: YAML_SCHEMA }) ?? {};
// Enum references look like "cover.CoverEntityFeature.OPEN"
const ENUM_REFERENCE = /^([a-z_]+)\.[A-Z]\w*\.[A-Z0-9_]+$/;
const enumDomains = (value, domains = new Set()) => {
if (typeof value === "string") {
const match = value.match(ENUM_REFERENCE);
if (match) {
domains.add(match[1]);
}
} else if (value && typeof value === "object") {
Object.values(value).forEach((val) => enumDomains(val, domains));
}
return domains;
};
// Resolves "<domain>.<Enum>.<MEMBER>" to the value of the member, like core
const enumResolver = async (yamls) => {
const domains = [...enumDomains(yamls)];
const [consts, inits] = await Promise.all([
fetchCoreFiles(domains, "const.py"),
fetchCoreFiles(domains, "__init__.py"),
]);
return (reference) => {
const [domain, enumName, member] = reference.split(".");
for (const source of [consts[domain], inits[domain]]) {
const match = source
?.split(`class ${enumName}(`)[1]
?.match(new RegExp(`\\n\\s+${member} = ("[^"]*"|\\d+)`));
if (match) {
return JSON.parse(match[1]);
}
}
throw new Error(`Unknown enum ${reference}`);
};
};
const createResolvers = (enumValue) => {
// In entity filters, every item of the supported features, a feature or a
// list of features, becomes one bit mask
const featureMask = (features) =>
[].concat(features).reduce(
// eslint-disable-next-line no-bitwise
(mask, feature) => mask | enumValue(feature),
0
);
const resolveSelector = (value) => {
if (Array.isArray(value)) {
return value.map(resolveSelector);
}
if (!value || typeof value !== "object") {
return value;
}
return Object.fromEntries(
Object.entries(value).map(([key, val]) => [
key,
key === "supported_features"
? [].concat(val).map(featureMask)
: resolveSelector(val),
])
);
};
// Like core, an empty target allows any target
const resolveTarget = (target) => resolveSelector(target ?? {});
// Field filters keep their lists, with every enum resolved on its own
const resolveField = (field) => {
const result = { ...field };
if (field.selector) {
result.selector = resolveSelector(field.selector);
}
if (field.filter?.supported_features) {
result.filter = {
...result.filter,
supported_features: field.filter.supported_features.map(enumValue),
};
}
if (field.filter?.attribute) {
result.filter = {
...result.filter,
attribute: Object.fromEntries(
Object.entries(field.filter.attribute).map(([name, options]) => [
name,
options.map(enumValue),
])
),
};
}
return result;
};
// Fields can be grouped in sections, which hold fields themselves
const resolveFields = (fields) =>
Object.fromEntries(
Object.entries(fields ?? {}).map(([key, field]) => [
key,
field && "fields" in field && !("selector" in field)
? { ...field, fields: resolveFields(field.fields) }
: resolveField(field ?? {}),
])
);
return { resolveFields, resolveTarget };
};
// Mirrors how core builds the response of get_services
const serviceDescriptions = (yamls, { resolveFields, resolveTarget }) =>
Object.fromEntries(
SERVICE_DOMAINS.map((domain) => {
if (!yamls[domain]) {
throw new Error(`No services.yaml found for ${domain}`);
}
const services = Object.entries(yamls[domain])
.filter(
([service]) =>
!service.startsWith(".") &&
!UNREGISTERED_SERVICES.includes(`${domain}.${service}`)
)
.map(([service, value]) => {
const description = { fields: resolveFields(value?.fields) };
for (const item of ["description", "name"]) {
if (value && item in value) {
description[item] = value[item];
}
}
if (value && "target" in value) {
description.target = resolveTarget(value.target);
}
const key = `${domain}.${service}`;
if (key in RESPONSE_SERVICES) {
description.response = { optional: RESPONSE_SERVICES[key] };
}
return [service, description];
});
return [domain, Object.fromEntries(services)];
})
);
// Mirrors how core builds the trigger and condition platform descriptions
const platformDescriptions = (yamls, { resolveFields, resolveTarget }) =>
Object.fromEntries(
AUTOMATION_PLATFORM_DOMAINS.flatMap((domain) =>
Object.entries(yamls[domain] ?? {})
// Keys starting with a dot only hold YAML anchors
.filter(([key, value]) => !key.startsWith(".") && value)
.map(([key, value]) => {
const absoluteKey = !key.startsWith("_")
? `${domain}.${key}`
: key.slice(1) || domain;
const description = { fields: resolveFields(value.fields) };
if ("target" in value) {
description.target = resolveTarget(value.target);
}
return [absoluteKey, description];
})
)
);
// The trigger or condition icons of every domain that has them
const platformIcons = (icons, category) =>
Object.fromEntries(
Object.entries(icons)
.map(([domain, content]) => [
domain,
content ? JSON.parse(content)[category] : undefined,
])
.filter(([, categoryIcons]) => categoryIcons)
);
const parseYamls = (files) =>
Object.fromEntries(
Object.entries(files)
.filter(([, content]) => content !== undefined)
.map(([domain, content]) => [domain, parseYaml(content)])
);
const writeTs = async (path, content) => {
const file = join(paths.root_dir, path);
const options = await prettier.resolveConfig(file);
await writeFile(
file,
await prettier.format(`${HEADER}\n${content}`, {
...options,
filepath: file,
})
);
};
gulp.task("gen-demo-core-data", async () => {
const [servicesFiles, triggersFiles, conditionsFiles, iconsFiles] =
await Promise.all([
fetchCoreFiles(SERVICE_DOMAINS, "services.yaml"),
fetchCoreFiles(AUTOMATION_PLATFORM_DOMAINS, "triggers.yaml"),
fetchCoreFiles(AUTOMATION_PLATFORM_DOMAINS, "conditions.yaml"),
fetchCoreFiles(AUTOMATION_PLATFORM_DOMAINS, "icons.json"),
]);
const servicesYamls = parseYamls(servicesFiles);
const triggersYamls = parseYamls(triggersFiles);
const conditionsYamls = parseYamls(conditionsFiles);
const resolvers = createResolvers(
await enumResolver([servicesYamls, triggersYamls, conditionsYamls])
);
for (const key of UNREGISTERED_SERVICES) {
const [domain, service] = key.split(".");
if (!(service in (servicesYamls[domain] ?? {}))) {
throw new Error(`Remove ${key} from UNREGISTERED_SERVICES, it is gone`);
}
}
const services = serviceDescriptions(servicesYamls, resolvers);
for (const key of Object.keys(RESPONSE_SERVICES)) {
const [domain, service] = key.split(".");
if (!services[domain]?.[service]) {
throw new Error(`Service ${key} that returns a response does not exist`);
}
}
const triggers = platformDescriptions(triggersYamls, resolvers);
const conditions = platformDescriptions(conditionsYamls, resolvers);
const icons = {
triggers: platformIcons(iconsFiles, "triggers"),
conditions: platformIcons(iconsFiles, "conditions"),
};
await Promise.all([
writeTs(
"src/fake_data/demo_services.ts",
`import type { HassServices } from "home-assistant-js-websocket";
// Core sends more than the HassServices type covers, like sections and list
// examples.
export const demoServices = ${JSON.stringify(services)} as unknown as HassServices;
`
),
writeTs(
"demo/src/stubs/automation_platform_domains.ts",
`
// Integrations that provide the new style triggers and conditions. Their
// translations are part of the demo build.
export const automationPlatformDomains = ${JSON.stringify(AUTOMATION_PLATFORM_DOMAINS)};
`
),
writeTs(
"demo/src/stubs/automation_platforms_data.ts",
`import type { ConditionDescriptions } from "../../../src/data/condition";
import type { TriggerDescriptions } from "../../../src/data/trigger";
export const triggerDescriptions: TriggerDescriptions = ${JSON.stringify(triggers)};
export const conditionDescriptions: ConditionDescriptions = ${JSON.stringify(conditions)};
`
),
writeTs(
"demo/src/stubs/automation_platforms_icons.ts",
`
export const triggerIcons = ${JSON.stringify(icons.triggers)};
export const conditionIcons = ${JSON.stringify(icons.conditions)};
`
),
]);
});
+40
View File
@@ -0,0 +1,40 @@
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import process from "node:process";
import gulp from "gulp";
import paths from "../paths.cjs";
const SOURCE_URL =
process.env.SENSOR_METADATA_URL ||
"https://raw.githubusercontent.com/home-assistant/core/refs/heads/dev/homeassistant/generated/device_classes.json";
const TARGET = join(paths.root_dir, "src", "data", "device_classes.ts");
gulp.task("gen-device-classes", async () => {
const response = await fetch(SOURCE_URL);
if (!response.ok) {
throw new Error(`Failed to fetch ${SOURCE_URL}: ${response.status}`);
}
const data = await response.json();
const domainDeviceClasses = data ?? {};
if (!Object.keys(domainDeviceClasses).length) {
throw new Error(`No device classes found in ${SOURCE_URL}`);
}
const content = `// This file is auto-generated from Home Assistant Core's
// entity platform device classes. Do not edit by hand.
// Regenerate with \`script/gen_device_classes\`.
export const DOMAIN_DEVICE_CLASSES: Record<string, string[]> = {
${Object.entries(domainDeviceClasses)
.map(
([domain, deviceClasses]) =>
` "${domain}": [${deviceClasses.map((deviceClass) => `"${deviceClass}"`).join(", ")}],`
)
.join("\n")}
};
`;
await writeFile(TARGET, content);
});
@@ -1,40 +0,0 @@
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import process from "node:process";
import gulp from "gulp";
import paths from "../paths.cjs";
const SOURCE_URL =
process.env.SENSOR_METADATA_URL ||
"https://raw.githubusercontent.com/home-assistant/core/dev/homeassistant/generated/sensor.json";
const TARGET = join(
paths.root_dir,
"src",
"data",
"sensor_numeric_device_classes.ts"
);
gulp.task("gen-numeric-device-classes", async () => {
const response = await fetch(SOURCE_URL);
if (!response.ok) {
throw new Error(`Failed to fetch ${SOURCE_URL}: ${response.status}`);
}
const data = await response.json();
const classes = [...(data.numeric_device_classes ?? [])].sort();
if (!classes.length) {
throw new Error(`No numeric_device_classes found in ${SOURCE_URL}`);
}
const content = `// This file is auto-generated from Home Assistant Core's \`SensorDeviceClass\`
// (all values minus \`NON_NUMERIC_DEVICE_CLASSES\`). Do not edit by hand.
// Regenerate with \`script/gen_numeric_device_classes\`.
export const SENSOR_NUMERIC_DEVICE_CLASSES: string[] = [
${classes.map((deviceClass) => ` "${deviceClass}",`).join("\n")}
];
`;
await writeFile(TARGET, content);
});
@@ -0,0 +1,83 @@
import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import process from "node:process";
import gulp from "gulp";
import paths from "../paths.cjs";
const SOURCE_URL =
process.env.SENSOR_METADATA_URL ||
"https://raw.githubusercontent.com/home-assistant/core/dev/homeassistant/generated/sensor.json";
const TARGET = join(
paths.root_dir,
"src",
"data",
"sensor_entity_constants.ts"
);
gulp.task("gen-sensor-entity-constants", async () => {
const response = await fetch(SOURCE_URL);
if (!response.ok) {
throw new Error(`Failed to fetch ${SOURCE_URL}: ${response.status}`);
}
const data = await response.json();
const numericDeviceClasses = [...(data.numeric_device_classes ?? [])].sort();
const deviceClassUnits = data.device_class_units ?? {};
const convertibleClassUnits = data.convertible_units ?? {};
const stateClasses = data.state_classes ?? [];
const stateClassUnits = data.state_class_units ?? {};
if (
!numericDeviceClasses.length ||
!stateClasses.length ||
!Object.keys(deviceClassUnits).length ||
!Object.keys(stateClassUnits).length
) {
throw new Error(
`No sensor device classes, state classes or units found in ${SOURCE_URL}`
);
}
const content = `// This file is auto-generated from Home Assistant Core's \`DEVICE_CLASS_UNITS\`
// and \`STATE_CLASS_UNITS\`) and \`SensorDeviceClass\`
// (all values minus \`NON_NUMERIC_DEVICE_CLASSES\`). Do not edit by hand.
// Regenerate with \`script/gen_sensor_entity_constants\`.
export const SENSOR_NUMERIC_DEVICE_CLASSES: string[] = [
${numericDeviceClasses.map((deviceClass) => ` "${deviceClass}",`).join("\n")}
];
export const SENSOR_DEVICE_CLASS_UNITS: Record<string, (string | null)[]> = {
${Object.entries(deviceClassUnits)
.map(
([deviceClass, units]) =>
` ${deviceClass}: [${units.map((u) => (u === null ? "null" : `"${u}"`)).join(", ")}],`
)
.join("\n")}
};
export const SENSOR_DEVICE_CLASS_CONVERTIBLE_UNITS: Record<string, (string | null)[]> = {
${Object.entries(convertibleClassUnits)
.map(
([deviceClass, units]) =>
` ${deviceClass}: [${units.map((u) => (u === null ? "null" : `"${u}"`)).join(", ")}],`
)
.join("\n")}
};
export const SENSOR_STATE_CLASSES: string[] = [
${stateClasses.map((stateClass) => ` "${stateClass}",`).join("\n")}
];
export const SENSOR_STATE_CLASS_UNITS: Record<string, (string | null)[]> = {
${Object.entries(stateClassUnits)
.map(
([stateClass, units]) =>
` ${stateClass}: [${units.map((u) => (u === null ? "null" : `"${u}"`)).join(", ")}],`
)
.join("\n")}
};
`;
await writeFile(TARGET, content);
});
+6 -2
View File
@@ -6,13 +6,17 @@ import "./demo.js";
import "./download-translations.js";
import "./e2e-test-app.js";
import "./entry-html.js";
import "./fetch-nightly-translations.js";
import "./fetch-nightly-translations.mts";
import "./gallery.js";
import "./gather-static.js";
import "./gen-demo-core-data.js";
import "./gen-device-classes.js";
import "./gen-icons-json.js";
import "./gen-numeric-device-classes.js";
import "./gen-sensor-entity-constants.js";
import "./landing-page.js";
import "./locale-data.js";
import "./map-assets.js";
import "./map-sprites.js";
import "./rspack.js";
import "./service-worker.js";
import "./translations.js";
+11 -38
View File
@@ -29,54 +29,27 @@ const LICENSE_OVERRIDES = [
// type-fest ships two license files (MIT for code, CC0 for types).
// We use the MIT license since that covers the bundled code.
packageName: "type-fest",
version: "5.8.0",
version: "5.10.0",
licenseFile: "license-mit",
},
];
// Locate the directory of an installed package matching an exact version.
//
// The copy we care about may be hoisted to the top-level node_modules or
// nested under a dependency when a different version occupies the hoisted
// slot (e.g. a build-only dependency pulling in an older release). Searching
// both keeps this check independent of yarn's hoisting decisions, which can
// shift when unrelated dependencies are added.
// pnpm stores every installed version under
// node_modules/.pnpm/<name>@<version>[(peers)]/node_modules/<name>, with the
// "/" of scoped names replaced by "+". Looking there finds the pinned version
// whether or not it is the one linked at the top level.
async function findPackageDir(packageName, version) {
const candidateDirs = [path.join(NODE_MODULES, packageName)];
const storeDir = path.join(NODE_MODULES, ".pnpm");
const prefix = `${packageName.replace("/", "+")}@${version}`;
const entries = await readdir(storeDir).catch(() => []);
// Collect one level of nesting: node_modules/<dep>/node_modules/<pkg> and
// node_modules/@scope/<dep>/node_modules/<pkg>.
let topLevel = [];
try {
topLevel = await readdir(NODE_MODULES, { withFileTypes: true });
} catch {
// node_modules unreadable — fall back to the hoisted candidate only.
}
for (const entry of topLevel) {
if (!entry.isDirectory() || entry.name === packageName) {
for (const entry of entries) {
if (entry !== prefix && !entry.startsWith(`${prefix}(`)) {
continue;
}
if (entry.name.startsWith("@")) {
const scopeDir = path.join(NODE_MODULES, entry.name);
// eslint-disable-next-line no-await-in-loop
const scoped = await readdir(scopeDir, { withFileTypes: true }).catch(
() => []
);
for (const dep of scoped) {
if (dep.isDirectory()) {
candidateDirs.push(
path.join(scopeDir, dep.name, "node_modules", packageName)
);
}
}
} else {
candidateDirs.push(
path.join(NODE_MODULES, entry.name, "node_modules", packageName)
);
}
}
for (const dir of candidateDirs) {
const dir = path.join(storeDir, entry, "node_modules", packageName);
// eslint-disable-next-line no-await-in-loop
const pkg = await readFile(path.join(dir, "package.json"), "utf-8")
.then(JSON.parse)
+10 -3
View File
@@ -47,16 +47,23 @@ const convertToJSON = async (
`Intl\\.${obj}\\.${addFunc}\\((?<data>.*)\\)`,
"s"
);
const encodedData = localeData.match(
/JSON\.parse\((?<data>"(?:[^"\\]|\\.)*")\)/
)?.groups?.data;
localeData = firstBlock.match(dataRegex)?.groups?.data;
if (!localeData) {
if (!localeData && !encodedData) {
throw Error(`Failed to extract data for language ${lang} from ${pkg}`);
}
// Parse to validate JSON, then stringify to minify
try {
localeData = JSON.stringify(JSON.parse(localeData));
localeData = JSON.stringify(
JSON.parse(encodedData ? JSON.parse(encodedData) : localeData)
);
await writeFile(join(outDir, `${pkg}/${lang}.json`), localeData);
} catch (e) {
throw Error(`Failed to parse JSON for language ${lang} from ${pkg}: ${e}`);
throw Error(`Failed to parse JSON for language ${lang} from ${pkg}: ${e}`, {
cause: e,
});
}
};
+120
View File
@@ -0,0 +1,120 @@
// Generates the MapLibre styles for the vector base map. Only the styles:
// glyphs and tiles come from core's proxy, the sprite sheet ships with the
// frontend (see map-sprites.js). They are generated here because core has no
// node toolchain to run @versatiles/style with.
//
// Only the default pair is written out; anything else is built in the browser
// from the same builder, which is why the preparation is shared with the
// frontend and why the asset URLs are written alongside the styles.
import { createHash } from "node:crypto";
import { readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import { osm } from "@versatiles/style";
import fs from "fs-extra";
import gulp from "gulp";
import paths from "../paths.cjs";
import { finalizeMapStyle } from "../../src/common/map/map-style-transforms.ts";
import {
HA_MAP_COLORS,
HA_MAP_COLORS_DARK,
} from "../../src/common/map/ha-map-palette.ts";
import {
missingSprites,
SHEET_FILES,
SPRITE_SHEET,
spritesDir,
} from "./map-sprites.js";
const PROXY_PATH = "/api/map_tiles";
const outputDir = path.resolve(paths.build_dir, "map");
// Core serves /static with a month of max-age, so a re-vendored sheet would
// otherwise be read from cache next to a style expecting the new one.
const sheetHash = async () => {
const contents = await Promise.all(
SHEET_FILES.map((file) => readFile(path.join(spritesDir, file)))
);
const hash = createHash("sha256");
contents.forEach((content) => hash.update(content));
return hash.digest("hex").slice(0, 8);
};
const styleUrls = (spriteVersion) => ({
// Keeps the generated URLs origin relative.
base: "",
glyphsPattern: `${PROXY_PATH}/fonts/{fontstack}/{range}.pbf`,
sprite: [
{
id: SPRITE_SHEET,
url: `/static/map/sprites/${SPRITE_SHEET}?v=${spriteVersion}`,
},
],
});
const checkSprites = (name, style, sheet) => {
const missing = missingSprites(style, sheet);
if (missing.length) {
throw new Error(
`Style "${name}" references icons missing from the bundled ${SPRITE_SHEET} ` +
`sprite sheet: ${missing.join(", ")}. Run \`pnpm exec gulp update-map-sprites\` ` +
`and commit the result.`
);
}
return style;
};
// The styles a card can pick, each as a light and a dark palette. Kept in sync
// with MAP_STYLES in src/common/map/map-styles.ts.
const STYLES = ["colorful", "natural", "muted", "gray", "toner"];
const PALETTES = STYLES.flatMap((style) => [style, `${style}-dark`]);
// Colors baked in, so the map a dashboard shows without configuration costs
// no builder and no second request.
const SHIPPED = [
["light", "colorful", HA_MAP_COLORS],
["dark", "colorful-dark", HA_MAP_COLORS_DARK],
];
const generateStyles = async () => {
const sheet = await fs.readJson(
path.join(spritesDir, `${SPRITE_SHEET}.json`)
);
const urls = styleUrls(await sheetHash());
// Built so a bump that needs an icon the sheet lacks fails here, not in a
// browser. Recoloring cannot add icons, so the palettes cover it.
PALETTES.forEach((theme) => checkSprites(theme, osm({ theme, urls }), sheet));
return urls;
};
const buildMapAssets = async () => {
await fs.emptyDir(outputDir);
const urls = await generateStyles();
await Promise.all([
// Read by src/common/map/build-map-style.ts, which cannot know the hash
// of the sprite sheet this build vendored.
writeFile(path.join(outputDir, "urls.json"), JSON.stringify(urls)),
...SHIPPED.map(([name, theme, colors]) =>
writeFile(
path.join(outputDir, `${name}.json`),
JSON.stringify(finalizeMapStyle(name, osm({ theme, colors, urls })))
)
),
]);
};
// Shared so it does not have to be wired into every pipeline separately.
let pending;
export const ensureMapAssets = () => {
pending ??= buildMapAssets();
return pending;
};
gulp.task("build-map-assets", ensureMapAssets);
// Runs in the required lint job so a @versatiles/style bump that needs new
// icons cannot merge before the sheet is re-vendored on that branch.
gulp.task("check-map-sprites", generateStyles);
export const mapAssetsDir = outputDir;
+80
View File
@@ -0,0 +1,80 @@
import { spawn } from "node:child_process";
import { createRequire } from "node:module";
import path from "node:path";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";
import gulp from "gulp";
import paths from "../paths.cjs";
const require = createRequire(import.meta.url);
export const SPRITE_SHEET = "base";
export const spritesDir = path.resolve(
paths.root_dir,
"public",
"static",
"map",
"sprites"
);
export const SHEET_FILES = [".json", ".png", "@2x.json", "@2x.png"].map(
(suffix) => `${SPRITE_SHEET}${suffix}`
);
// The only style properties that resolve to a sprite image.
const IMAGE_PROPERTIES = [
"icon-image",
"fill-pattern",
"line-pattern",
"fill-extrusion-pattern",
"background-pattern",
];
const collectStrings = (value, into) => {
if (typeof value === "string") {
into.push(value);
} else if (Array.isArray(value)) {
value.forEach((item) => collectStrings(item, into));
} else if (value && typeof value === "object") {
Object.values(value).forEach((item) => collectStrings(item, into));
}
return into;
};
export const spriteIds = (style) => {
const prefix = `${SPRITE_SHEET}:`;
const strings = style.layers.flatMap((layer) =>
IMAGE_PROPERTIES.flatMap((property) =>
collectStrings([layer.layout?.[property], layer.paint?.[property]], [])
)
);
return new Set(
strings
.filter((value) => value.startsWith(prefix))
.map((value) => value.slice(prefix.length))
);
};
export const missingSprites = (style, sheet) =>
[...spriteIds(style)].filter((id) => !(id in sheet));
gulp.task("update-map-sprites", async () => {
const { version } = require("@versatiles/style/package.json");
const url = `https://github.com/versatiles-org/versatiles-style/releases/download/v${version}/sprites.tar.gz`;
const response = await fetch(url);
if (!response.ok || !response.body) {
throw new Error(`Failed to fetch ${url}: ${response.status}`);
}
const tar = spawn("tar", ["-xzf", "-", "-C", spritesDir, ...SHEET_FILES], {
stdio: ["pipe", "inherit", "inherit"],
});
const exited = new Promise((resolve, reject) => {
tar.on("error", reject);
tar.on("close", (code) =>
code === 0 ? resolve() : reject(new Error(`tar exited with ${code}`))
);
});
await pipeline(Readable.fromWeb(response.body), tar.stdin);
await exited;
});
+1
View File
@@ -252,6 +252,7 @@ gulp.task("rspack-prod-gallery", () =>
createGalleryConfig({
isProdBuild: true,
latestBuild: true,
isTestBuild: env.isTestBuild(),
})
)
);
+5 -2
View File
@@ -10,7 +10,7 @@ import { finished } from "node:stream/promises";
import env from "../env.cjs";
import paths from "../paths.cjs";
import { mergeTranslations } from "./merge-translations.js";
import "./fetch-nightly-translations.js";
import "./fetch-nightly-translations.mts";
const inFrontendDir = "translations/frontend";
const inBackendDir = "translations/backend";
@@ -137,6 +137,9 @@ const lokaliseTransform = (data, path, original = data) => {
gulp.task("clean-translations", () => deleteAsync([workDir]));
// Keep translationMetadata.json, the dev server's rspack watcher imports it.
const cleanTranslationOutput = () => deleteAsync([outDir]);
const makeWorkDir = () => mkdir(workDir, { recursive: true });
const createTestTranslation = () =>
@@ -307,7 +310,7 @@ gulp.task(
gulp.series(
gulp.parallel(
"fetch-nightly-translations",
gulp.series("clean-translations", makeWorkDir)
gulp.series(cleanTranslationOutput, makeWorkDir)
),
createTestTranslation,
createMasterTranslation,
+62 -27
View File
@@ -1,38 +1,55 @@
#!/usr/bin/env node
// Script to print Babel plugins and Core JS polyfills that will be used by browserslist environments
import { version as babelVersion } from "@babel/core";
import presetEnv from "@babel/preset-env";
import compilationTargets from "@babel/helper-compilation-targets";
import { transformSync } from "@babel/core";
import compilationTargets, {
getInclusionReasons,
} from "@babel/helper-compilation-targets";
import coreJSCompat from "core-js-compat";
import { logPlugin } from "@babel/preset-env/lib/debug.js";
import shippedPolyfills from "../node_modules/babel-plugin-polyfill-corejs3/lib/shipped-proposals.js";
import { babelOptions } from "./bundle.cjs";
const detailsOpen = (heading) =>
`<details>\n<summary><h4>${heading}</h4></summary>\n`;
const detailsClose = "</details>\n";
const dummyAPI = {
version: babelVersion,
// eslint-disable-next-line @typescript-eslint/no-empty-function
assertVersion: () => {},
caller: (callback) =>
callback({
name: "Dummy Bundler",
supportsStaticESM: true,
supportsDynamicImport: true,
supportsTopLevelAwait: true,
supportsExportNamespaceFrom: true,
}),
targets: () => ({}),
// Copied from @babel/preset-env's internal `logPlugin`, which Babel 8 no
// longer exposes (the package rolls up into lib/index.js and exports nothing
// but the preset). Prints an item with the targets that require it.
const logPlugin = (item, targetVersions, list) => {
const filteredList = getInclusionReasons(item, targetVersions, list);
const support = list[item];
if (!support) {
console.log(` ${item}`);
return;
}
let formattedTargets = `{`;
let first = true;
for (const target of Object.keys(filteredList)) {
if (!first) formattedTargets += `,`;
first = false;
formattedTargets += ` ${target}`;
if (support[target]) formattedTargets += ` < ${support[target]}`;
}
formattedTargets += ` }`;
console.log(` ${item} ${formattedTargets}`);
};
// Copied from babel-plugin-polyfill-corejs3's generated
// corejs3ShippedProposalsList, which v1 no longer exposes (it is inlined in
// the package's rolled-up bundle).
const shippedProposalsList = new Set([
"esnext.array.group",
"esnext.array.group-to-map",
"esnext.iterator.zip",
"esnext.iterator.zip-keyed",
"esnext.symbol.metadata",
]);
// Generate filter function based on proposal/method inputs
// Copied and adapted from babel-plugin-polyfill-corejs3/esm/index.mjs
const polyfillFilter = (method, proposals, shippedProposals) => (name) => {
if (proposals || method === "entry-global") return true;
if (shippedProposals && shippedPolyfills.default.has(name)) {
if (shippedProposals && shippedProposalsList.has(name)) {
return true;
}
if (name.startsWith("esnext.")) {
@@ -47,7 +64,9 @@ const polyfillFilter = (method, proposals, shippedProposals) => (name) => {
for (const buildType of ["Modern", "Legacy"]) {
const browserslistEnv = buildType.toLowerCase();
const babelOpts = babelOptions({ latestBuild: browserslistEnv === "modern" });
const presetEnvOpts = babelOpts.presets[0][1];
const presetEnvOpts = babelOpts.presets.find(
(preset) => Array.isArray(preset) && preset[0] === "@babel/preset-env"
)?.[1];
// Core-JS polyfills are injected by babel-plugin-polyfill-corejs3 (Babel 8
// removed preset-env's `useBuiltIns`), so read its options here.
const corejsOpts = babelOpts.plugins.find(
@@ -55,22 +74,38 @@ for (const buildType of ["Modern", "Legacy"]) {
Array.isArray(plugin) && plugin[0] === "babel-plugin-polyfill-corejs3"
)?.[1];
// Invoking preset-env in debug mode will log the included plugins
// Transforming an empty file with preset-env in debug mode logs the included
// plugins. The caller declares the same capabilities babel-loader does, so
// plugins gated on bundler support (e.g. transform-export-namespace-from)
// match the build.
presetEnvOpts.debug = true;
console.log(detailsOpen(`${buildType} Build Babel Plugins`));
presetEnv.default(dummyAPI, {
...presetEnvOpts,
browserslistEnv,
debug: true,
transformSync("", {
...babelOpts,
configFile: false,
filename: "audit.js",
caller: {
name: "list-plugins-and-polyfills",
supportsStaticESM: true,
supportsDynamicImport: true,
supportsTopLevelAwait: true,
supportsExportNamespaceFrom: true,
},
});
console.log(detailsClose);
// Manually log the Core-JS polyfills using the same technique
if (corejsOpts) {
console.log(detailsOpen(`${buildType} Build Core-JS Polyfills`));
const targets = compilationTargets.default(babelOpts?.targets, {
const targets = compilationTargets(babelOpts.targets, {
browserslistEnv,
});
const polyfillList = coreJSCompat({ targets }).list.filter(
// `version` limits the list to modules the installed core-js ships,
// mirroring the provider's own filtering.
const polyfillList = coreJSCompat({
targets,
version: corejsOpts.version,
}).list.filter(
polyfillFilter(
corejsOpts.method,
corejsOpts.proposals,
+147 -12
View File
@@ -1,4 +1,6 @@
const { existsSync } = require("fs");
const fs = require("fs");
const { existsSync } = fs;
const path = require("path");
const rspack = require("@rspack/core");
// eslint-disable-next-line @typescript-eslint/naming-convention
@@ -16,6 +18,72 @@ const SafeWebpackBar = require("./safe-webpackbar.cjs");
const paths = require("./paths.cjs");
const bundle = require("./bundle.cjs");
// Build-toolchain packages whose version changes the emitted bytes but which
// are loader/compiler machinery, not modules in the build graph — so rspack's
// node_modules snapshot cannot see them. Their versions are folded into the
// persistent cache `version` so a toolchain upgrade invalidates the cache,
// while ordinary runtime-dependency bumps (handled by the snapshot) do not.
const TOOLCHAIN_PACKAGES = [
"@rspack/core",
"@babel/core",
"@babel/preset-env",
"babel-plugin-polyfill-corejs3",
"@babel/plugin-transform-runtime",
"@babel/plugin-transform-class-properties",
"@babel/plugin-transform-private-methods",
"@babel/runtime",
"babel-loader",
"core-js",
"terser",
"terser-webpack-plugin",
"browserslist",
"caniuse-lite",
];
// Our own build logic — the config, loaders and babel plugins. Their contents
// (not their paths) go into the cache version, so a change invalidates the
// cache the same way `buildDependencies` would, but without tying validity to
// absolute paths — rspack compares buildDependencies by path, which breaks a
// cache reused on another machine/checkout (a different workspace path).
const CONFIG_FILES = [
__filename,
path.join(__dirname, "bundle.cjs"),
path.join(__dirname, "minify-template-literals-loader.cjs"),
path.join(__dirname, "lit-disable-dev-mode-loader.cjs"),
path.join(__dirname, "babel-plugins", "custom-polyfill-plugin.js"),
path.join(__dirname, "babel-plugins", "inline-constants-plugin.cjs"),
];
// Patches change a package's files but not its version, which is all the
// node_modules snapshot checks, so their contents go into the version too.
const PATCHES_DIR = path.join(paths.root_dir, "patches");
// Content hash of the toolchain versions and our own build files, used as the
// persistent cache `version`. Everything here is path-independent so the cache
// stays valid when reused on a different machine or checkout path.
const cacheVersion = () => {
const parts = [
...TOOLCHAIN_PACKAGES.map(
(pkg) => `${pkg}@${require(`${pkg}/package.json`).version}`
),
...CONFIG_FILES.map(
(file) => `${path.basename(file)}:${fs.readFileSync(file, "utf8")}`
),
...(existsSync(PATCHES_DIR) ? fs.readdirSync(PATCHES_DIR) : [])
.filter((file) => file.endsWith(".patch"))
.sort()
.map(
(file) =>
`${file}:${fs.readFileSync(path.join(PATCHES_DIR, file), "utf8")}`
),
];
return require("crypto")
.createHash("sha256")
.update(parts.join("\n"))
.digest("hex")
.slice(0, 16);
};
class LogStartCompilePlugin {
ignoredFirst = false;
@@ -47,7 +115,10 @@ const createRspackConfig = ({
dontHash = new Set();
}
const ignorePackages = bundle.ignorePackages({ latestBuild });
const litHtmlRoot = path.resolve(__dirname, "../node_modules/lit-html");
// pnpm links node_modules/lit-html into its store; rspack compares real paths
const litHtmlRoot = fs.realpathSync(
path.resolve(__dirname, "../node_modules/lit-html")
);
const litHtmlDevelopmentRoot = path.join(litHtmlRoot, "development");
const litDisableDevModeLoader = path.join(
__dirname,
@@ -76,11 +147,19 @@ const createRspackConfig = ({
[
{
loader: "babel-loader",
// Options are stored per loader identity, not per call. A
// file imported by both the page and a worker gets two
// modules but, without distinct idents, one set of options:
// whichever layer resolved it first. That handed the worker
// the page's transform, polyfills included, and the page the
// worker's.
ident: `babel-loader-${info.issuerLayer ?? "page"}`,
options: {
...bundle.babelOptions({
latestBuild,
isTestBuild,
sw: info.issuerLayer === "sw",
worker: info.issuerLayer === "worker",
}),
cacheDirectory: !isProdBuild,
cacheCompression: false,
@@ -120,6 +199,19 @@ const createRspackConfig = ({
worker: ["*context.audioWorklet.addModule()", "..."],
},
},
{
// MapLibre's worker loads ESM plugins through `import(url)`, and the
// page side builds a blob import from `new URL(url, import.meta.url)`
// for a cross-origin worker. Neither path is taken here: the RTL
// plugin is UMD and the worker is served from the page's origin.
// Rspack's stubs for these fully dynamic requests are exactly what
// should remain - rejecting, and free of syntax the legacy floor
// cannot parse - so the warnings about them are noise.
test: /[\\/]maplibre-gl[\\/]dist[\\/]maplibre-gl(?:-worker)?\.mjs$/,
parser: {
exprContextCritical: false,
},
},
{
test: /\.css$/,
type: "asset/source",
@@ -201,7 +293,12 @@ const createRspackConfig = ({
}
),
new rspack.DefinePlugin(
bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })
bundle.definedVars({
isProdBuild,
latestBuild,
publicPath,
defineOverlay,
})
),
new rspack.IgnorePlugin({
checkResource(resource, context) {
@@ -217,12 +314,20 @@ const createRspackConfig = ({
) {
return false;
}
if (!ignorePackages.length) {
return false;
}
let fullPath;
try {
fullPath = resource.startsWith(".")
? path.resolve(context, resource)
: require.resolve(resource);
} catch (err) {
// ESM-only packages have no CommonJS entry to resolve. The ignore
// list holds resolved CommonJS paths, so they can never match.
if (err.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
return false;
}
console.error(
"Error in Home Assistant ignore plugin",
resource,
@@ -288,10 +393,7 @@ const createRspackConfig = ({
"lit/directives/join$": "lit/directives/join.js",
"lit/directives/repeat$": "lit/directives/repeat.js",
"lit/directives/live$": "lit/directives/live.js",
"lit/directives/keyed$": latestBuild
? "lit/directives/keyed.js"
: path.resolve(__dirname, "../src/common/lit/keyed-es5.ts"),
"lit/polyfill-support$": "lit/polyfill-support.js",
"lit/directives/keyed$": "lit/directives/keyed.js",
"@lit-labs/virtualizer/layouts/grid":
"@lit-labs/virtualizer/layouts/grid.js",
"@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver":
@@ -339,9 +441,12 @@ const createRspackConfig = ({
output: {
module: latestBuild,
filename: ({ chunk }) =>
!isProdBuild || isStatsBuild || dontHash.has(chunk.name)
? "[name].js"
: "[name].[contenthash].js",
// Versioned instead of hashed; MapLibre gets the URL at build time
chunk.name === bundle.mapWorkerName
? bundle.mapWorkerFilename()
: !isProdBuild || isStatsBuild || dontHash.has(chunk.name)
? "[name].js"
: "[name].[contenthash].js",
chunkFilename:
isProdBuild && !isStatsBuild ? "[name].[contenthash].js" : "[name].js",
assetModuleFilename:
@@ -376,6 +481,34 @@ const createRspackConfig = ({
])
),
},
// Persistent filesystem cache for production builds, opt-in per environment
// via RSPACK_CACHE ("readwrite" writes it, "readonly" only reads a warm
// cache — e.g. CI reusing the nightly-written one). Unset (releases, local,
// tests) = no cache.
...(isProdBuild && process.env.RSPACK_CACHE
? {
cache: {
type: "persistent",
// `name` is already unique per variant (frontend-modern/-legacy).
name,
// Content-based version (node major + toolchain versions + our own
// build files + patches). Everything is path-independent, so
// the cache stays valid when reused on another machine/checkout.
// Runtime deps are deliberately absent — rspack's node_modules
// snapshot invalidates their modules per-package, so a single
// unrelated bump keeps the rest warm. buildDependencies is
// intentionally not used: rspack compares it by absolute path,
// which breaks cross-machine reuse.
version: `node${process.versions.node.split(".")[0]}-${cacheVersion()}`,
storage: {
type: "filesystem",
directory: path.resolve(paths.root_dir, ".rspack-cache"),
},
// CI reads the nightly-written cache but must not modify it.
readonly: process.env.RSPACK_CACHE === "readonly",
},
}
: {}),
experiments: {
outputModule: true,
},
@@ -405,8 +538,10 @@ const createDemoConfig = ({
const createCastConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
const createGalleryConfig = ({ isProdBuild, latestBuild, isTestBuild }) =>
createRspackConfig(
bundle.config.gallery({ isProdBuild, latestBuild, isTestBuild })
);
const createLandingPageConfig = ({ isProdBuild, latestBuild }) =>
createRspackConfig(bundle.config.landingPage({ isProdBuild, latestBuild }));
+1 -3
View File
@@ -15,7 +15,6 @@ import {
saveTokens,
} from "../../../../src/common/auth/token_storage";
import { atLeastVersion } from "../../../../src/common/config/version";
import { toggleAttribute } from "../../../../src/common/dom/toggle_attribute";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-icon";
import "../../../../src/components/ha-list";
@@ -197,8 +196,7 @@ class HcCast extends LitElement {
protected updated(changedProps: PropertyValues<this>) {
super.updated(changedProps);
toggleAttribute(
this,
this.toggleAttribute(
"hide-icons",
this.lovelaceViews ? !this.lovelaceViews.some((view) => view.icon) : true
);
+2 -2
View File
@@ -27,6 +27,7 @@ import type {
LovelaceConfig,
LovelaceDashboardStrategyConfig,
} from "../../../../src/data/lovelace/config/types";
import { normalizeLovelaceConfig } from "../../../../src/data/lovelace/config/normalize";
import { isStrategyDashboard } from "../../../../src/data/lovelace/config/types";
import { fetchResources } from "../../../../src/data/lovelace/resource";
import { loadLovelaceResources } from "../../../../src/panels/lovelace/common/load-resources";
@@ -34,7 +35,6 @@ import { HassElement } from "../../../../src/state/hass-element";
import { castContext } from "../cast_context";
import "./hc-launch-screen";
import { getPanelTitleFromUrlPath } from "../../../../src/data/panel";
import { checkLovelaceConfig } from "../../../../src/panels/lovelace/common/check-lovelace-config";
const DEFAULT_CONFIG: LovelaceDashboardStrategyConfig = {
strategy: {
@@ -359,7 +359,7 @@ export class HcMain extends HassElement {
this._urlPath || "lovelace"
);
castContext.setApplicationState(title || "");
this._lovelaceConfig = checkLovelaceConfig(
this._lovelaceConfig = normalizeLovelaceConfig(
lovelaceConfig
) as LovelaceConfig;
}
+100 -2
View File
@@ -1,11 +1,16 @@
import { navigate } from "../../../src/common/navigate";
import { slugify } from "../../../src/common/string/slugify";
import type { LocalizeFunc } from "../../../src/common/translations/localize";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
import type { Lovelace } from "../../../src/panels/lovelace/types";
import { setDemoAreas } from "../stubs/area_registry";
import { setPlatformEntityRegistryEntries } from "../stubs/entity_registry";
import { energyEntities } from "../stubs/entities";
import { connectivityEntities } from "../stubs/connectivity/fixtures";
import { setDemoFloors } from "../stubs/floor_registry";
import { getDemoTheme } from "../stubs/frontend";
import type { DemoConfig, DemoTheme } from "./types";
import type { EntityInput } from "../../../src/fake_data/entities/types";
import type { DemoAutomation, DemoConfig, DemoTheme } from "./types";
export const applyDemoTheme = (hass: MockHomeAssistant, theme: DemoTheme) => {
if (typeof theme === "function") {
@@ -15,6 +20,95 @@ export const applyDemoTheme = (hass: MockHomeAssistant, theme: DemoTheme) => {
hass.mockTheme(null, getDemoTheme(theme));
};
export const automationEntity = ({
config: automation,
entityId,
state = "on",
icon,
lastTriggered,
}: DemoAutomation): EntityInput => ({
entity_id: entityId ?? `automation.${slugify(automation.alias)}`,
platform: "automation",
state,
attributes: {
id: automation.id,
friendly_name: automation.alias,
last_triggered:
lastTriggered === undefined
? null
: new Date(Date.now() - lastTriggered * 60000).toISOString(),
mode: automation.mode ?? "single",
current: 0,
// Like core, only the modes that can run more than once have a maximum
...((automation.mode === "queued" || automation.mode === "parallel") && {
max: automation.max ?? 10,
}),
icon,
},
});
// Automations saved in the editor during this session, per demo
// Automations saved in the editor during this session, per demo. A deleted
// automation is null.
const savedAutomations: Record<
string,
Record<string, DemoAutomation | null>
> = {};
export const saveDemoAutomation = (
id: string,
automation: DemoAutomation | null
) => {
savedAutomations[selectedDemo] = {
...savedAutomations[selectedDemo],
[id]: automation,
};
};
// The automations of a demo config, with the ones saved in the editor
export const demoAutomations = (
demo: string,
config: DemoConfig
): DemoAutomation[] => {
const saved = savedAutomations[demo] ?? {};
const configured = config.automations ?? [];
const ids = new Set(configured.map((automation) => automation.config.id));
return [
...configured.map((automation) =>
automation.config.id in saved ? saved[automation.config.id] : automation
),
...Object.values(saved).filter(
(automation) => automation && !ids.has(automation.config.id)
),
].filter((automation): automation is DemoAutomation => automation !== null);
};
// The automation entities are derived from the configs the editor shows, so
// their names and IDs always match.
export const demoConfigEntities = (
demo: string,
config: DemoConfig,
localize: LocalizeFunc
): EntityInput[] => [
...config.entities(localize),
...demoAutomations(demo, config).map(automationEntity),
];
// Like core, the automations of a demo config are in the entity registry
export const registerDemoAutomations = (
hass: MockHomeAssistant,
demo: string,
config: DemoConfig
) =>
setPlatformEntityRegistryEntries(
hass,
"automation",
demoAutomations(demo, config).map((automation) => ({
entity_id: automationEntity(automation).entity_id,
unique_id: automation.config.id,
}))
);
export const demoConfigs: Record<string, () => Promise<DemoConfig>> = {
sections: () => import("./sections").then((mod) => mod.demoSections),
home: () => import("./home").then((mod) => mod.demoHome),
@@ -51,8 +145,12 @@ export const setDemoConfig = async (
setDemoFloors(hass, config.floors);
setDemoAreas(hass, config.areas);
hass.addEntities(config.entities(hass.localize), true);
hass.addEntities(demoConfigEntities(demo, config, hass.localize), true);
registerDemoAutomations(hass, demo, config);
hass.addEntities(energyEntities());
// Replaced the whole state map above, so the entities that do not belong to a
// demo config have to be added back.
hass.addEntities(connectivityEntities());
// Let the new registries and entities reach the dashboard before saving the
// config, so dashboard strategies generate against them
+27 -23
View File
@@ -7,7 +7,7 @@ import type { HomeDashboardStrategyConfig } from "../../../../src/panels/lovelac
import { HomeDashboardStrategy } from "../../../../src/panels/lovelace/strategies/home/home-dashboard-strategy";
import type { HomeOverviewViewStrategyConfig } from "../../../../src/panels/lovelace/strategies/home/home-overview-view-strategy";
import { HomeOverviewViewStrategy } from "../../../../src/panels/lovelace/strategies/home/home-overview-view-strategy";
import { generateLovelaceSectionStrategy } from "../../../../src/panels/lovelace/strategies/get-strategy";
import type { HeadingCardConfig } from "../../../../src/panels/lovelace/cards/types";
import type { HomeAssistant } from "../../../../src/types";
export interface DemoHomeDashboardStrategyConfig extends Omit<
@@ -61,29 +61,33 @@ class DemoHomeOverviewViewStrategy extends ReactiveElement {
{ ...config, type: "home-overview" },
hass
);
// Expand the favorites section so the demo card can be added to it
const sections = await Promise.all(
(view.sections || []).map(async (section) => {
if (
!isStrategySection(section) ||
section.strategy.type !== "common-controls"
) {
return section;
}
// The demo card takes up the space of two tiles
const limit = (section.strategy.limit as number | undefined) ?? 8;
const favorites = await generateLovelaceSectionStrategy(
{ ...section, strategy: { ...section.strategy, limit: limit - 2 } },
hass
);
const [heading, ...cards] = favorites.cards || [];
return {
...favorites,
// Place the demo card first so the tiles fill the rows next to it
cards: [heading, { type: "custom:ha-demo-next-card" }, ...cards],
};
})
// Add the demo card to the favorites section, found by its heading
const favoritesHeading = hass.localize(
"ui.panel.lovelace.strategy.home.favorites"
);
const sections = (view.sections || []).map((section) => {
if (
isStrategySection(section) ||
!section.cards?.some(
(card) =>
card.type === "heading" &&
(card as HeadingCardConfig).heading === favoritesHeading
)
) {
return section;
}
const [heading, ...cards] = section.cards;
return {
...section,
// Place the demo card first so the tiles fill the rows next to it. It
// takes up the space of two tiles, so keep two less, but at least six.
cards: [
heading,
{ type: "custom:ha-demo-next-card" },
...cards.slice(0, Math.max(6, cards.length - 2)),
],
};
});
return {
...view,
+361
View File
@@ -0,0 +1,361 @@
import type { DemoAutomation } from "../types";
export const demoAutomationsSections: DemoAutomation[] = [
{
lastTriggered: 60 * 9,
state: "off",
icon: "mdi:auto-mode",
config: {
id: "1700669321947",
alias: "Home Assistant Auto-update",
description:
"Installs Home Assistant updates at night, so nobody is bothered by the restart.",
triggers: [{ trigger: "time", at: "03:00:00" }],
conditions: [
{
condition: "update.is_available",
target: { entity_id: "update.home_assistant_core_update" },
options: { for: "00:00:00" },
},
],
actions: [
{
action: "update.install",
target: { entity_id: "update.home_assistant_core_update" },
data: { backup: true },
},
],
mode: "queued",
},
},
{
lastTriggered: 25,
config: {
id: "1700669322001",
alias: "Kitchen lights on motion",
description:
"Turns on the kitchen lights when motion is detected and turns them off again once the kitchen has been empty for 2 minutes.",
triggers: [
{
trigger: "motion.detected",
target: { entity_id: "binary_sensor.kitchen_motion" },
options: { for: "00:00:00" },
},
],
conditions: [],
actions: [
{
action: "light.turn_on",
target: {
entity_id: ["light.kitchen_spotlights", "light.worktop_spotlights"],
},
data: { brightness_pct: 80 },
},
{
wait_for_trigger: [
{
trigger: "motion.cleared",
target: { entity_id: "binary_sensor.kitchen_motion" },
options: { for: "00:02:00" },
},
],
},
{
action: "light.turn_off",
target: {
entity_id: ["light.kitchen_spotlights", "light.worktop_spotlights"],
},
},
],
mode: "restart",
},
},
{
lastTriggered: 60 * 3,
config: {
id: "1700669322002",
alias: "Outdoor light from sunset to sunrise",
description:
"Uses trigger IDs to handle both sunset and sunrise in one automation.",
triggers: [
{
trigger: "sun.sunset",
id: "sunset",
options: {
offset: { days: 0, hours: 0, minutes: 15, seconds: 0 },
offset_type: "before",
},
},
{
trigger: "sun.sunrise",
id: "sunrise",
options: {
offset: { days: 0, hours: 0, minutes: 0, seconds: 0 },
offset_type: "before",
},
},
],
conditions: [],
actions: [
{
choose: [
{
conditions: [{ condition: "trigger", id: "sunset" }],
sequence: [
{
action: "light.turn_on",
target: { entity_id: "light.outdoor_light" },
},
],
},
{
conditions: [{ condition: "trigger", id: "sunrise" }],
sequence: [
{
action: "light.turn_off",
target: { entity_id: "light.outdoor_light" },
},
],
},
],
},
],
mode: "single",
},
},
{
lastTriggered: 60 * 14,
config: {
id: "1700669322003",
alias: "Flood light on motion when dark",
description:
"Turns on the flood light for 5 minutes when someone walks by in the dark.",
triggers: [
{
trigger: "motion.detected",
target: { entity_id: "binary_sensor.outdoor_motion_sensor_motion" },
options: { for: "00:00:00" },
},
],
conditions: [
{
condition: "illuminance.is_value",
target: { entity_id: "sensor.outdoor_motion_sensor_illuminance" },
options: {
threshold: {
type: "below",
value: { number: 50, unit_of_measurement: "lx" },
},
for: "00:00:00",
},
},
],
actions: [
{
action: "light.turn_on",
target: { entity_id: "light.flood_light" },
},
{ delay: { hours: 0, minutes: 5, seconds: 0, milliseconds: 0 } },
{
action: "light.turn_off",
target: { entity_id: "light.flood_light" },
},
],
mode: "restart",
},
},
{
lastTriggered: 60 * 26,
config: {
id: "1700669322004",
alias: "Close the shutters when it gets hot",
description:
"Keeps the living room cool by closing the shutters on hot, sunny days.",
triggers: [
{
trigger: "temperature.crossed_threshold",
target: { entity_id: "sensor.outdoor_temperature" },
options: {
threshold: {
type: "above",
value: { number: 25, unit_of_measurement: "°C" },
},
for: "00:10:00",
},
},
],
conditions: [{ condition: "sun.is_up" }],
actions: [
{
action: "cover.close_cover",
target: {
entity_id: [
"cover.living_room_garden_shutter",
"cover.living_room_graveyard_shutter",
"cover.living_room_left_shutter",
"cover.living_room_right_shutter",
],
},
},
],
mode: "single",
},
},
{
lastTriggered: 60 * 50,
config: {
id: "1700669322005",
alias: "Fridge door left open",
description:
"Sends a reminder when the fridge door has been open for 2 minutes.",
triggers: [
{
trigger: "door.opened",
target: { entity_id: "binary_sensor.fridge_door" },
options: { for: "00:02:00" },
},
],
conditions: [],
actions: [
{
action: "notify.notify",
data: {
title: "Fridge door",
message: "The fridge door has been open for 2 minutes.",
},
},
],
mode: "single",
},
},
{
lastTriggered: 90,
config: {
id: "1700669322006",
alias: "Meeting mode",
description:
"Pauses the music in the study and turns on the lights when a meeting starts.",
triggers: [
{
trigger: "switch.turned_on",
target: { entity_id: "switch.in_meeting" },
options: { for: "00:00:00" },
},
],
conditions: [],
actions: [
{
action: "media_player.media_pause",
target: { entity_id: "media_player.study_nest_hub" },
},
{
action: "light.turn_on",
target: { entity_id: "light.study_spotlights" },
data: { brightness_pct: 100, color_temp_kelvin: 4000 },
},
],
mode: "single",
},
},
{
lastTriggered: 60 * 20,
config: {
id: "1700669322009",
alias: "Lights up when the music pauses",
description:
"Turns on the living room spotlights when the music is paused in the evening.",
triggers: [
{
trigger: "media_player.paused_playing",
target: { entity_id: "media_player.living_room_nest_mini" },
options: { for: "00:00:00" },
},
],
conditions: [{ condition: "sun.is_set" }],
actions: [
{
action: "light.turn_on",
target: { entity_id: "light.living_room_spotlights" },
data: { brightness_pct: 40 },
},
],
mode: "single",
},
},
{
lastTriggered: 60 * 7,
config: {
id: "1700669322007",
alias: "Lower heating when the car leaves",
triggers: [
{
trigger: "zone.left",
target: { entity_id: "device_tracker.car" },
options: { zone: "zone.home", for: "00:00:00" },
},
],
conditions: [
{
condition: "time",
weekday: ["mon", "tue", "wed", "thu", "fri"],
},
],
actions: [
{
action: "climate.set_temperature",
target: {
entity_id: ["climate.ground_floor", "climate.first_floor"],
},
data: { temperature: 17 },
},
],
mode: "single",
},
},
{
lastTriggered: 60 * 11,
config: {
id: "1700669322008",
alias: "Good night",
description:
"Turns off all lights and closes the shutters at 23:00 on weeknights.",
triggers: [
{
trigger: "time",
at: "23:00:00",
weekday: ["sun", "mon", "tue", "wed", "thu"],
},
],
conditions: [],
actions: [
{
action: "light.turn_off",
target: {
entity_id: [
"light.floor_lamp",
"light.living_room_spotlights",
"light.bar_lamp",
"light.kitchen_spotlights",
"light.worktop_spotlights",
"light.study_spotlights",
],
},
},
{
action: "cover.close_cover",
target: {
entity_id: [
"cover.living_room_garden_shutter",
"cover.living_room_graveyard_shutter",
"cover.living_room_left_shutter",
"cover.living_room_right_shutter",
"cover.kitchen_shutter",
"cover.study_shutter",
],
},
},
],
mode: "single",
},
},
];
+12 -13
View File
@@ -140,6 +140,18 @@ export const demoEntitiesSections: DemoConfig["entities"] = (localize) =>
friendly_name: "Outdoor humidity",
},
},
// Used by the automation for when the car leaves home
"zone.home": {
entity_id: "zone.home",
state: "0",
attributes: {
latitude: 52.3731339,
longitude: 4.8903147,
radius: 100,
friendly_name: "Home",
icon: "mdi:home",
},
},
"device_tracker.car": {
entity_id: "device_tracker.car",
state: "not_home",
@@ -514,19 +526,6 @@ export const demoEntitiesSections: DemoConfig["entities"] = (localize) =>
friendly_name: "Outdoor motion sensor Illuminance",
},
},
"automation.home_assistant_auto_update": {
entity_id: "automation.home_assistant_auto_update",
state: "off",
attributes: {
id: "1700669321947",
last_triggered: "2024-02-29T18:02:05.343139+00:00",
mode: "queued",
current: 0,
max: 50,
icon: "mdi:auto-mode",
friendly_name: "Home Assistant Auto-update",
},
},
"update.home_assistant_operating_system_update": {
entity_id: "update.home_assistant_operating_system_update",
state: "off",
+2
View File
@@ -1,4 +1,5 @@
import type { DemoConfig } from "../types";
import { demoAutomationsSections } from "./automations";
import { demoEntitiesSections } from "./entities";
import { demoLovelaceSections } from "./lovelace";
@@ -8,5 +9,6 @@ export const demoSections: DemoConfig = {
name: "Home Demo",
lovelace: demoLovelaceSections,
entities: demoEntitiesSections,
automations: demoAutomationsSections,
theme: { theme: "default", dark: false },
};
+12
View File
@@ -1,5 +1,6 @@
import type { TemplateResult } from "lit";
import type { LocalizeFunc } from "../../../src/common/translations/localize";
import type { ManualAutomationConfig } from "../../../src/data/automation";
import type { LovelaceRawConfig } from "../../../src/data/lovelace/config/types";
import type { EntityInput } from "../../../src/fake_data/entities/types";
import type { ThemeSettings } from "../../../src/types";
@@ -8,6 +9,16 @@ import type { DemoFloor } from "../stubs/floor_registry";
export type DemoTheme = ThemeSettings | (() => Record<string, string> | null);
export interface DemoAutomation {
config: ManualAutomationConfig & { id: string; alias: string };
/** Defaults to the alias as slug */
entityId?: string;
state?: "on" | "off";
icon?: string;
/** Minutes ago */
lastTriggered?: number;
}
export interface DemoConfig {
index?: number;
name: string;
@@ -17,6 +28,7 @@ export interface DemoConfig {
string | ((localize: LocalizeFunc) => string | TemplateResult<1>);
lovelace: (localize: LocalizeFunc) => LovelaceRawConfig;
entities: (localize: LocalizeFunc) => EntityInput[];
automations?: DemoAutomation[];
floors?: DemoFloor[];
areas?: DemoArea[];
theme: DemoTheme;
+62 -12
View File
@@ -1,18 +1,34 @@
import { customElement } from "lit/decorators";
import type { LocalizeFunc } from "../../src/common/translations/localize";
import { isNavigationClick } from "../../src/common/dom/is-navigation-click";
import { navigate } from "../../src/common/navigate";
import type { MockHomeAssistant } from "../../src/fake_data/provide_hass";
import { provideHass } from "../../src/fake_data/provide_hass";
import { HomeAssistantAppEl } from "../../src/layouts/home-assistant";
import type { HomeAssistant } from "../../src/types";
import { applyDemoTheme, selectedDemoConfig } from "./configs/demo-configs";
import {
applyDemoTheme,
demoConfigEntities,
registerDemoAutomations,
selectedDemo,
selectedDemoConfig,
} from "./configs/demo-configs";
import { mockAreaRegistry, setDemoAreas } from "./stubs/area_registry";
import {
connectivityCommands,
connectivityComponents,
connectivityEntities,
connectivityEntityRegistryEntries,
} from "./stubs/connectivity/fixtures";
import { mockAuth } from "./stubs/auth";
import { demoDevices } from "./stubs/devices";
import { mockDeviceRegistry } from "./stubs/device_registry";
import { mockEnergy } from "./stubs/energy";
import { energyEntities } from "./stubs/entities";
import { mockEntityRegistry } from "./stubs/entity_registry";
import {
mockEntityRegistry,
mockEntityRegistryDisplay,
} from "./stubs/entity_registry";
import { mockEvents } from "./stubs/events";
import { mockFloorRegistry, setDemoFloors } from "./stubs/floor_registry";
import { mockFrontend } from "./stubs/frontend";
@@ -20,9 +36,11 @@ import { mockHardware } from "./stubs/hardware";
import { mockHassioSupervisor } from "./stubs/hassio_supervisor";
import { mockIntegration } from "./stubs/integration";
import { mockLabelRegistry } from "./stubs/label_registry";
import { automationPlatformDomains } from "./stubs/automation_platform_domains";
import { mockIcons } from "./stubs/icons";
import { mockHistory } from "./stubs/history";
import { mockLovelace } from "./stubs/lovelace";
import { zoneRegistryEntries } from "./stubs/map";
import { mockMediaPlayer } from "./stubs/media_player";
import { mockPersistentNotification } from "./stubs/persistent_notification";
import { mockRecorder } from "./stubs/recorder";
@@ -51,6 +69,12 @@ const CONFIG_PANEL_COMMANDS = [
"system_health/",
"backup/",
"automation/config",
"trigger_platforms/subscribe",
"condition_platforms/subscribe",
"get_triggers_for_target",
"get_conditions_for_target",
"get_services_for_target",
"extract_from_target",
"script/config",
"config/automation/config",
"config/script/config",
@@ -60,6 +84,8 @@ const CONFIG_PANEL_COMMANDS = [
"assist_pipeline/",
"config/entity_registry/settings/",
"slugify",
"marketplace/",
...connectivityCommands,
];
@customElement("ha-demo")
@@ -80,26 +106,45 @@ export class HaDemo extends HomeAssistantAppEl {
config: {
...hass.config,
components: [
...(hass.config?.components ?? []),
"backup",
"webhook",
"usage_prediction",
"assist_pipeline",
"hassio",
"hardware",
// Some automation platforms are loaded already
...new Set([
...(hass.config?.components ?? []),
"backup",
"webhook",
"usage_prediction",
"assist_pipeline",
"hassio",
"hardware",
"marketplace",
...connectivityComponents,
...automationPlatformDomains,
]),
],
},
panels: {
...hass.panels,
// Opened from the settings page, not listed in the sidebar
marketplace: {
component_name: "marketplace",
icon: null,
title: null,
config: null,
url_path: "marketplace",
},
},
});
const localizePromise =
// @ts-ignore
this._loadFragmentTranslations(hass.language, "page-demo").then(
() => this.hass!.localize
// hass is not updated yet when another fragment started loading
// meanwhile, so use the localize with these translations directly
(localize?: LocalizeFunc) => localize ?? this.hass!.localize
);
mockLovelace(hass, localizePromise);
mockAuth(hass);
mockTranslations(hass);
mockTranslations(hass, localizePromise);
mockHistory(hass);
mockRecorder(hass);
mockTodo(hass);
@@ -129,6 +174,7 @@ export class HaDemo extends HomeAssistantAppEl {
mockFloorRegistry(hass);
mockLabelRegistry(hass);
mockUsagePrediction(hass);
mockEntityRegistryDisplay(hass);
mockEntityRegistry(hass, [
{
config_entry_id: "co2signal",
@@ -172,16 +218,20 @@ export class HaDemo extends HomeAssistantAppEl {
created_at: 0,
modified_at: 0,
},
...connectivityEntityRegistryEntries,
...zoneRegistryEntries,
]);
hass.addEntities(energyEntities());
hass.addEntities(connectivityEntities());
// Once config is loaded AND localize, set registries, entities and theme.
Promise.all([selectedDemoConfig, localizePromise]).then(
([conf, localize]) => {
setDemoFloors(hass, conf.floors);
setDemoAreas(hass, conf.areas);
hass.addEntities(conf.entities(localize));
hass.addEntities(demoConfigEntities(selectedDemo, conf, localize));
registerDemoAutomations(hass, selectedDemo, conf);
applyDemoTheme(hass, conf.theme);
}
);
+3
View File
@@ -39,6 +39,9 @@
html {
background-color: var(--primary-background-color, #fafafa);
color: var(--primary-text-color, #212121);
/* Prevent iOS Safari from inflating text when rotating to landscape */
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
@media (prefers-color-scheme: dark) {
html {
+3
View File
@@ -15,6 +15,7 @@ const pipelines: AssistPipeline[] = [
tts_voice: "JennyNeural",
wake_word_entity: null,
wake_word_id: null,
prefer_local_intents: false,
},
{
id: "01local",
@@ -29,6 +30,7 @@ const pipelines: AssistPipeline[] = [
tts_voice: null,
wake_word_entity: null,
wake_word_id: null,
prefer_local_intents: false,
},
{
id: "01chatgpt",
@@ -43,6 +45,7 @@ const pipelines: AssistPipeline[] = [
tts_voice: "ElviraNeural",
wake_word_entity: null,
wake_word_id: null,
prefer_local_intents: false,
},
];
+19
View File
@@ -1,3 +1,4 @@
import type { OwnProfileMutableParams } from "../../../src/data/person";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
export const mockAuth = (hass: MockHomeAssistant) => {
@@ -6,4 +7,22 @@ export const mockAuth = (hass: MockHomeAssistant) => {
hass.mockWS("auth/sign_path", (msg: { path: string }) => ({
path: msg.path,
}));
let name: string | undefined;
// The profile dialog refreshes the user subscription after saving, which
// writes the updated user back to hass.user. Read the current user on each
// call so later changes to it, such as a non-admin user, are kept.
hass.mockWS("auth/current_user", (_msg, currentHass: MockHomeAssistant) =>
name && currentHass.user ? { ...currentHass.user, name } : currentHass.user
);
hass.mockWS(
"person/update_own_profile",
(msg: Partial<OwnProfileMutableParams>, currentHass: MockHomeAssistant) => {
if (msg.name) {
name = msg.name;
}
return { user_name: name ?? currentHass.user?.name, person: null };
}
);
};
+142 -56
View File
@@ -1,69 +1,155 @@
import type { AutomationConfig } from "../../../src/data/automation";
import type { ScriptConfig } from "../../../src/data/script";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
import { computeDomain } from "../../../src/common/entity/compute_domain";
import { slugify } from "../../../src/common/string/slugify";
import {
automationEntity,
demoAutomations,
saveDemoAutomation,
selectedDemo,
selectedDemoConfig,
} from "../configs/demo-configs";
import type { DemoAutomation } from "../configs/types";
import { mockAutomationPlatforms } from "./automation_platforms";
import {
addEntityRegistryEntry,
getEntityRegistryEntry,
removeEntityRegistryEntry,
} from "./entity_registry";
const demoAutomationConfig = (entityId: string): AutomationConfig => ({
id: entityId.split(".")[1],
alias: "Demo automation",
description: "An example automation shown in the demo.",
triggers: [
{ trigger: "state", entity_id: "binary_sensor.basement_floor_wet" },
],
conditions: [],
actions: [
{
action: "light.turn_on",
target: { entity_id: "light.bed_light" },
},
],
mode: "single",
});
const automationConfig = async (
id: string | undefined
): Promise<AutomationConfig> => {
const automation = demoAutomations(
selectedDemo,
await selectedDemoConfig
).find((a) => a.config.id === id);
if (!automation) {
throw new Error("Automation not found");
}
return automation.config;
};
const demoScriptConfig = (): ScriptConfig => ({
alias: "Demo script",
description: "An example script shown in the demo.",
sequence: [
{
action: "light.turn_on",
target: { entity_id: "light.bed_light" },
},
],
mode: "single",
});
const scriptConfig = (
currentHass: MockHomeAssistant,
entityId: string
): ScriptConfig => {
const alias =
currentHass.states[entityId]?.attributes.friendly_name ?? entityId;
return {
alias,
sequence: [
{
action: "persistent_notification.create",
data: { message: `${alias} ran` },
},
],
mode: "single",
};
};
export const mockAutomation = (hass: MockHomeAssistant) => {
hass.mockWS("automation/config", (msg: { entity_id: string }) => ({
config: demoAutomationConfig(msg.entity_id),
}));
hass.mockWS("script/config", () => ({ config: demoScriptConfig() }));
hass.mockAPI(/config\/automation\/config\/.+/, () =>
demoAutomationConfig("automation.demo")
);
hass.mockAPI(/config\/script\/config\/.+/, () => demoScriptConfig());
// Trigger/condition type pickers subscribe for integration-provided
// platforms. The demo only uses the built-in ones, so emit empty records.
hass.mockWS(
"trigger_platforms/subscribe",
(
_msg,
_hass,
onChange?: (descriptions: Record<string, unknown>) => void
) => {
onChange?.({});
return () => undefined;
"automation/config",
async (msg: { entity_id: string }, currentHass: MockHomeAssistant) => ({
config: await automationConfig(
currentHass.states[msg.entity_id]?.attributes.id
),
})
);
hass.mockAPI(
/config\/automation\/config\/.+/,
(currentHass, method, path, parameters) => {
const id = decodeURIComponent(path.split("/").pop()!);
const existing = Object.values(currentHass.states).find(
(stateObj) =>
computeDomain(stateObj.entity_id) === "automation" &&
stateObj.attributes.id === id
);
if (method === "DELETE") {
// Like core, remove the automation with its entity
saveDemoAutomation(id, null);
if (existing) {
const { [existing.entity_id]: _state, ...states } =
currentHass.states;
const { [existing.entity_id]: _entity, ...entities } =
currentHass.entities;
currentHass.updateHass({ states, entities });
// Otherwise a service call to it would add its state again
delete currentHass.mockEntities[existing.entity_id];
removeEntityRegistryEntry(currentHass, existing.entity_id);
}
return { result: "ok" };
}
if (method === "POST") {
// Core stores the ID in the config
const config = {
...(parameters as DemoAutomation["config"]),
id,
};
config.alias ||= id;
// Like core, update the automation entity, or add it for a new one
// A new automation gets a free entity ID, like core
const slug = `automation.${slugify(config.alias)}`;
let entityId = existing?.entity_id ?? slug;
for (let i = 2; !existing && entityId in currentHass.states; i++) {
entityId = `${slug}_${i}`;
}
const lastTriggered = existing?.attributes.last_triggered;
const automation: DemoAutomation = {
config,
entityId,
state: existing?.state as DemoAutomation["state"],
icon: existing?.attributes.icon,
lastTriggered: lastTriggered
? (Date.now() - Date.parse(lastTriggered)) / 60000
: undefined,
};
// Kept per demo, so it is still there after switching demos
saveDemoAutomation(id, automation);
// A display entry of a new automation is left over from another demo
const display = existing ? currentHass.entities[entityId] : undefined;
currentHass.addEntities(automationEntity(automation));
// Adding the entity resets its display entry, keep what the registry
// holds
if (display) {
const registryName = getEntityRegistryEntry(entityId)?.name;
currentHass.entities[entityId] = {
...currentHass.entities[entityId],
...(registryName && { name: registryName }),
area_id: display.area_id,
labels: display.labels,
icon: display.icon,
hidden: display.hidden,
};
}
if (!existing) {
addEntityRegistryEntry(currentHass, {
entity_id: entityId,
platform: "automation",
unique_id: id,
});
}
return { result: "ok" };
}
return automationConfig(id);
}
);
// Scripts do not have demo configs yet, show the script under its own name.
hass.mockWS(
"condition_platforms/subscribe",
(
_msg,
_hass,
onChange?: (descriptions: Record<string, unknown>) => void
) => {
onChange?.({});
return () => undefined;
}
"script/config",
(msg: { entity_id: string }, currentHass: MockHomeAssistant) => ({
config: scriptConfig(currentHass, msg.entity_id),
})
);
hass.mockAPI(/config\/script\/config\/.+/, (currentHass, _method, path) =>
scriptConfig(
currentHass,
`script.${decodeURIComponent(path.split("/").pop()!)}`
)
);
mockAutomationPlatforms(hass);
};
@@ -0,0 +1,52 @@
// This file is auto-generated from Home Assistant Core. Do not edit by hand.
// Regenerate with `script/gen_demo_core_data`.
// Integrations that provide the new style triggers and conditions. Their
// translations are part of the demo build.
export const automationPlatformDomains = [
"air_quality",
"alarm_control_panel",
"assist_satellite",
"battery",
"button",
"calendar",
"climate",
"counter",
"cover",
"door",
"doorbell",
"event",
"fan",
"garage_door",
"gate",
"humidifier",
"humidity",
"illuminance",
"lawn_mower",
"light",
"lock",
"media_player",
"moisture",
"moon",
"motion",
"occupancy",
"power",
"remote",
"scene",
"schedule",
"select",
"siren",
"sun",
"switch",
"temperature",
"text",
"timer",
"todo",
"update",
"vacuum",
"valve",
"vibration",
"water_heater",
"window",
"zone",
];
+270
View File
@@ -0,0 +1,270 @@
import type { HassServiceTarget } from "home-assistant-js-websocket";
import { ensureArray } from "../../../src/common/array/ensure-array";
import { computeDomain } from "../../../src/common/entity/compute_domain";
import type { ConditionDescriptions } from "../../../src/data/condition";
import type { ExtractFromTargetResult } from "../../../src/data/target";
import type { TriggerDescriptions } from "../../../src/data/trigger";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
import { getLabelIds } from "./label_registry";
import {
conditionDescriptions,
triggerDescriptions,
} from "./automation_platforms_data";
type Descriptions = TriggerDescriptions | ConditionDescriptions;
interface EntityFilter {
integration?: string;
domain?: string | string[];
device_class?: string | string[];
supported_features?: number[];
}
// Expands a target to its areas, devices and entities, like core does
const expandTarget = (
hass: MockHomeAssistant,
target: HassServiceTarget,
primaryEntitiesOnly = true
) => {
const missing = {
floors: [] as string[],
areas: [] as string[],
devices: [] as string[],
labels: [] as string[],
};
const knownLabelIds = getLabelIds();
const floorIds = ensureArray(target.floor_id ?? []);
const labelIds = ensureArray(target.label_id ?? []);
missing.floors.push(...floorIds.filter((id) => !(id in hass.floors)));
// Like core, unknown labels are reported, but still expanded
missing.labels.push(...labelIds.filter((id) => !knownLabelIds.includes(id)));
const hasLabel = (labels?: string[]) =>
labelIds.some((labelId) => labels?.includes(labelId));
// Unknown areas and devices are reported, but still referenced
const areaIds = new Set(ensureArray(target.area_id ?? []));
missing.areas.push(...[...areaIds].filter((id) => !(id in hass.areas)));
for (const area of Object.values(hass.areas)) {
if (
(area.floor_id && floorIds.includes(area.floor_id)) ||
hasLabel(area.labels)
) {
areaIds.add(area.area_id);
}
}
// A targeted or labeled device includes its child devices
const deviceIds = new Set<string>();
const addDevice = (deviceId: string) => {
deviceIds.add(deviceId);
for (const device of Object.values(hass.devices)) {
if (device.parent_device_id === deviceId) {
deviceIds.add(device.id);
}
}
};
for (const deviceId of ensureArray(target.device_id ?? [])) {
if (!(deviceId in hass.devices)) {
missing.devices.push(deviceId);
}
addDevice(deviceId);
}
for (const device of Object.values(hass.devices)) {
if (hasLabel(device.labels)) {
addDevice(device.id);
}
}
// A child device without its own area is in the area of its parent device
const deviceArea = (deviceId: string) => {
const device = hass.devices[deviceId];
return (
device?.area_id ??
(device?.parent_device_id
? hass.devices[device.parent_device_id]?.area_id
: undefined)
);
};
const areaDeviceIds = new Set<string>();
for (const device of Object.values(hass.devices)) {
const areaId = deviceArea(device.id);
if (areaId && areaIds.has(areaId)) {
areaDeviceIds.add(device.id);
}
}
const entityIds = new Set(ensureArray(target.entity_id ?? []));
for (const entity of Object.values(hass.entities)) {
// The display registry keeps the entities of a previous demo, and like
// core, hidden entities are never included indirectly
if (!(entity.entity_id in hass.states) || entity.hidden) {
continue;
}
const primary = !primaryEntitiesOnly || !entity.entity_category;
if (
hasLabel(entity.labels) ||
(primary &&
((entity.device_id && deviceIds.has(entity.device_id)) ||
(entity.area_id && areaIds.has(entity.area_id)) ||
// An entity with its own area is not in the area of its device
(!entity.area_id &&
entity.device_id &&
areaDeviceIds.has(entity.device_id))))
) {
entityIds.add(entity.entity_id);
}
}
return {
areas: [...areaIds],
devices: [...new Set([...deviceIds, ...areaDeviceIds])],
entities: [...entityIds],
missing,
};
};
const matchesFilter = (
hass: MockHomeAssistant,
entityId: string,
filter: EntityFilter
) =>
(!filter.integration ||
hass.entities[entityId]?.platform === filter.integration) &&
(!filter.domain ||
ensureArray(filter.domain).includes(computeDomain(entityId))) &&
(!filter.device_class ||
ensureArray(filter.device_class).includes(
hass.states[entityId]?.attributes.device_class ?? ""
)) &&
// Like core, the entity needs all the features of one of the feature sets
(!filter.supported_features ||
filter.supported_features.some(
(features) =>
// eslint-disable-next-line no-bitwise
((hass.states[entityId]?.attributes.supported_features ?? 0) &
features) ===
features
));
type TargetDescriptions = Record<
string,
{
target?: {
entity?: EntityFilter | EntityFilter[];
primary_entities_only?: boolean;
} | null;
}
>;
// Like core, the components with a target that apply to at least one entity
// of the target. A target without entity filters applies to any entity.
const componentsForTarget = (
hass: MockHomeAssistant,
target: HassServiceTarget,
descriptions: TargetDescriptions
) => {
const entityIds = expandTarget(hass, target, false).entities;
const targetedIds = ensureArray(target.entity_id ?? []);
return Object.entries(descriptions)
.filter(([, description]) => {
if (!description.target) {
return false;
}
const filters = ensureArray(description.target.entity ?? []);
const primaryEntitiesOnly =
description.target.primary_entities_only ?? true;
return entityIds.some(
(entityId) =>
// Entities with a category only count when targeted directly,
// unless the component allows them
(!primaryEntitiesOnly ||
targetedIds.includes(entityId) ||
!hass.entities[entityId]?.entity_category) &&
(!filters.length ||
filters.some((filter) => matchesFilter(hass, entityId, filter)))
);
})
.map(([key]) => key);
};
const mockForTarget = (
hass: MockHomeAssistant,
type: string,
descriptions: Descriptions
) =>
hass.mockWS(
type,
(msg: { target: HassServiceTarget }, currentHass: MockHomeAssistant) =>
componentsForTarget(
currentHass,
msg.target,
descriptions as TargetDescriptions
)
);
const mockPlatformSubscription = (
hass: MockHomeAssistant,
type: string,
descriptions: Descriptions
) =>
hass.mockWS(
type,
(_msg, _hass, onChange?: (descriptions: Descriptions) => void) => {
onChange?.(descriptions);
return () => undefined;
}
);
export const mockAutomationPlatforms = (hass: MockHomeAssistant) => {
mockPlatformSubscription(
hass,
"trigger_platforms/subscribe",
triggerDescriptions
);
mockPlatformSubscription(
hass,
"condition_platforms/subscribe",
conditionDescriptions
);
mockForTarget(hass, "get_triggers_for_target", triggerDescriptions);
mockForTarget(hass, "get_conditions_for_target", conditionDescriptions);
hass.mockWS(
"extract_from_target",
(
msg: { target: HassServiceTarget; primary_entities_only?: boolean },
currentHass: MockHomeAssistant
): ExtractFromTargetResult => {
const { areas, devices, entities, missing } = expandTarget(
currentHass,
msg.target,
msg.primary_entities_only ?? true
);
return {
missing_areas: missing.areas,
missing_devices: missing.devices,
missing_floors: missing.floors,
missing_labels: missing.labels,
referenced_areas: areas,
referenced_devices: devices,
referenced_entities: entities,
};
}
);
hass.mockWS(
"get_services_for_target",
(msg: { target: HassServiceTarget }, currentHass: MockHomeAssistant) =>
componentsForTarget(
currentHass,
msg.target,
// Keyed by <domain>.<service>, like the triggers and conditions
Object.fromEntries(
Object.entries(currentHass.services).flatMap(([domain, services]) =>
Object.entries(services).map(([service, description]) => [
`${domain}.${service}`,
description,
])
)
) as TargetDescriptions
)
);
};
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,495 @@
// This file is auto-generated from Home Assistant Core. Do not edit by hand.
// Regenerate with `script/gen_demo_core_data`.
export const triggerIcons = {
air_quality: {
co2_changed: { trigger: "mdi:molecule-co2" },
co2_crossed_threshold: { trigger: "mdi:molecule-co2" },
co_changed: { trigger: "mdi:molecule-co" },
co_cleared: { trigger: "mdi:check-circle" },
co_crossed_threshold: { trigger: "mdi:molecule-co" },
co_detected: { trigger: "mdi:molecule-co" },
gas_cleared: { trigger: "mdi:check-circle" },
gas_detected: { trigger: "mdi:gas-cylinder" },
n2o_changed: { trigger: "mdi:factory" },
n2o_crossed_threshold: { trigger: "mdi:factory" },
no2_changed: { trigger: "mdi:factory" },
no2_crossed_threshold: { trigger: "mdi:factory" },
no_changed: { trigger: "mdi:factory" },
no_crossed_threshold: { trigger: "mdi:factory" },
ozone_changed: { trigger: "mdi:weather-sunny-alert" },
ozone_crossed_threshold: { trigger: "mdi:weather-sunny-alert" },
pm10_changed: { trigger: "mdi:blur" },
pm10_crossed_threshold: { trigger: "mdi:blur" },
pm1_changed: { trigger: "mdi:blur" },
pm1_crossed_threshold: { trigger: "mdi:blur" },
pm25_changed: { trigger: "mdi:blur" },
pm25_crossed_threshold: { trigger: "mdi:blur" },
pm4_changed: { trigger: "mdi:blur" },
pm4_crossed_threshold: { trigger: "mdi:blur" },
smoke_cleared: { trigger: "mdi:check-circle" },
smoke_detected: { trigger: "mdi:smoke-detector-variant" },
so2_changed: { trigger: "mdi:factory" },
so2_crossed_threshold: { trigger: "mdi:factory" },
voc_changed: { trigger: "mdi:air-filter" },
voc_crossed_threshold: { trigger: "mdi:air-filter" },
voc_ratio_changed: { trigger: "mdi:air-filter" },
voc_ratio_crossed_threshold: { trigger: "mdi:air-filter" },
},
alarm_control_panel: {
armed: { trigger: "mdi:shield" },
armed_away: { trigger: "mdi:shield-lock" },
armed_home: { trigger: "mdi:shield-home" },
armed_night: { trigger: "mdi:shield-moon" },
armed_vacation: { trigger: "mdi:shield-airplane" },
disarmed: { trigger: "mdi:shield-off" },
triggered: { trigger: "mdi:bell-ring" },
},
assist_satellite: {
idle: { trigger: "mdi:chat-sleep" },
listening: { trigger: "mdi:chat-question" },
processing: { trigger: "mdi:chat-processing" },
responding: { trigger: "mdi:chat-alert" },
},
battery: {
became_low: { trigger: "mdi:battery-alert" },
level_changed: { trigger: "mdi:battery-unknown" },
level_crossed_threshold: { trigger: "mdi:battery-alert" },
no_longer_low: { trigger: "mdi:battery" },
started_charging: { trigger: "mdi:battery-charging" },
stopped_charging: { trigger: "mdi:battery" },
},
button: { pressed: { trigger: "mdi:gesture-tap-button" } },
calendar: {
event_ended: { trigger: "mdi:calendar-end" },
event_started: { trigger: "mdi:calendar-start" },
},
climate: {
hvac_mode_changed: { trigger: "mdi:thermostat" },
started_cooling: { trigger: "mdi:snowflake" },
started_drying: { trigger: "mdi:water-percent" },
started_heating: { trigger: "mdi:fire" },
target_humidity_changed: { trigger: "mdi:water-percent" },
target_humidity_crossed_threshold: { trigger: "mdi:water-percent" },
target_temperature_changed: { trigger: "mdi:thermometer" },
target_temperature_crossed_threshold: { trigger: "mdi:thermometer" },
turned_off: { trigger: "mdi:power-off" },
turned_on: { trigger: "mdi:power-on" },
},
counter: {
decremented: { trigger: "mdi:numeric-negative-1" },
incremented: { trigger: "mdi:numeric-positive-1" },
maximum_reached: { trigger: "mdi:sort-numeric-ascending-variant" },
minimum_reached: { trigger: "mdi:sort-numeric-descending-variant" },
reset: { trigger: "mdi:refresh" },
},
cover: {
awning_closed: { trigger: "mdi:storefront-outline" },
awning_opened: { trigger: "mdi:storefront-outline" },
blind_closed: { trigger: "mdi:blinds-horizontal-closed" },
blind_opened: { trigger: "mdi:blinds-horizontal" },
curtain_closed: { trigger: "mdi:curtains-closed" },
curtain_opened: { trigger: "mdi:curtains" },
shade_closed: { trigger: "mdi:roller-shade-closed" },
shade_opened: { trigger: "mdi:roller-shade" },
shutter_closed: { trigger: "mdi:window-shutter" },
shutter_opened: { trigger: "mdi:window-shutter-open" },
},
door: {
closed: { trigger: "mdi:door-closed" },
opened: { trigger: "mdi:door-open" },
},
doorbell: { rang: { trigger: "mdi:doorbell" } },
event: { received: { trigger: "mdi:eye-check" } },
fan: {
turned_off: { trigger: "mdi:fan-off" },
turned_on: { trigger: "mdi:fan" },
},
garage_door: {
closed: { trigger: "mdi:garage" },
opened: { trigger: "mdi:garage-open" },
},
gate: {
closed: { trigger: "mdi:gate" },
opened: { trigger: "mdi:gate-open" },
},
humidifier: {
mode_changed: { trigger: "mdi:air-humidifier" },
started_drying: { trigger: "mdi:arrow-down-bold" },
started_humidifying: { trigger: "mdi:arrow-up-bold" },
turned_off: { trigger: "mdi:air-humidifier-off" },
turned_on: { trigger: "mdi:air-humidifier" },
},
humidity: {
changed: { trigger: "mdi:water-percent" },
crossed_threshold: { trigger: "mdi:water-percent" },
},
illuminance: {
changed: { trigger: "mdi:brightness-6" },
cleared: { trigger: "mdi:brightness-4" },
crossed_threshold: { trigger: "mdi:brightness-6" },
detected: { trigger: "mdi:brightness-7" },
},
lawn_mower: {
became_idle: { trigger: "mdi:stop" },
errored: { trigger: "mdi:alert-circle-outline" },
paused_mowing: { trigger: "mdi:pause" },
returned_to_dock: { trigger: "mdi:home-import-outline" },
started_mowing: { trigger: "mdi:play" },
started_returning: { trigger: "mdi:home-import-outline" },
},
light: {
brightness_changed: { trigger: "mdi:lightbulb-on-50" },
brightness_crossed_threshold: { trigger: "mdi:lightbulb-on-50" },
turned_off: { trigger: "mdi:lightbulb-off" },
turned_on: { trigger: "mdi:lightbulb-on" },
},
lock: {
jammed: { trigger: "mdi:lock-alert" },
locked: { trigger: "mdi:lock" },
opened: { trigger: "mdi:lock-open-variant" },
unlocked: { trigger: "mdi:lock-open-variant" },
},
media_player: {
muted: { trigger: "mdi:volume-mute" },
paused_playing: { trigger: "mdi:pause" },
started_playing: { trigger: "mdi:play" },
stopped_playing: { trigger: "mdi:stop" },
turned_off: { trigger: "mdi:power" },
turned_on: { trigger: "mdi:power" },
unmuted: { trigger: "mdi:volume-high" },
volume_changed: { trigger: "mdi:volume-medium" },
volume_crossed_threshold: { trigger: "mdi:volume-medium" },
},
moisture: {
changed: { trigger: "mdi:water-percent" },
cleared: { trigger: "mdi:water-off" },
crossed_threshold: { trigger: "mdi:water-percent" },
detected: { trigger: "mdi:water" },
},
moon: { phase_changed: { trigger: "mdi:moon-waning-crescent" } },
motion: {
cleared: { trigger: "mdi:motion-sensor-off" },
detected: { trigger: "mdi:motion-sensor" },
},
occupancy: {
cleared: { trigger: "mdi:home-outline" },
detected: { trigger: "mdi:home-account" },
},
power: {
changed: { trigger: "mdi:flash" },
crossed_threshold: { trigger: "mdi:flash" },
},
remote: {
turned_off: { trigger: "mdi:remote-off" },
turned_on: { trigger: "mdi:remote" },
},
scene: { activated: { trigger: "mdi:palette" } },
schedule: {
block_ended: { trigger: "mdi:calendar-blank" },
block_started: { trigger: "mdi:calendar-clock" },
},
select: { selection_changed: { trigger: "mdi:format-list-bulleted" } },
siren: {
turned_off: { trigger: "mdi:bullhorn-outline" },
turned_on: { trigger: "mdi:bullhorn" },
},
sun: {
blue_hour_ended: { trigger: "mdi:weather-sunset" },
blue_hour_started: { trigger: "mdi:weather-sunset" },
dawn: { trigger: "mdi:weather-sunset-up" },
dusk: { trigger: "mdi:weather-sunset-down" },
elevation_changed: { trigger: "mdi:sun-angle" },
elevation_crossed_threshold: { trigger: "mdi:sun-angle" },
golden_hour_ended: { trigger: "mdi:weather-sunset" },
golden_hour_started: { trigger: "mdi:weather-sunset" },
midnight_sun_ended: { trigger: "mdi:weather-sunset" },
midnight_sun_started: { trigger: "mdi:weather-sunny" },
polar_night_ended: { trigger: "mdi:weather-sunset-up" },
polar_night_started: { trigger: "mdi:weather-night" },
solar_midnight: { trigger: "mdi:weather-night" },
solar_noon: { trigger: "mdi:weather-sunny" },
sunrise: { trigger: "mdi:weather-sunset-up" },
sunset: { trigger: "mdi:weather-sunset-down" },
},
switch: {
turned_off: { trigger: "mdi:toggle-switch-variant-off" },
turned_on: { trigger: "mdi:toggle-switch-variant" },
},
temperature: {
changed: { trigger: "mdi:thermometer" },
crossed_threshold: { trigger: "mdi:thermometer" },
},
text: { changed: { trigger: "mdi:form-textbox" } },
timer: {
cancelled: { trigger: "mdi:timer-cancel" },
finished: { trigger: "mdi:timer-check" },
paused: { trigger: "mdi:timer-pause" },
remaining_time_reached: { trigger: "mdi:timer-alert-outline" },
restarted: { trigger: "mdi:timer-refresh" },
started: { trigger: "mdi:timer-play" },
},
todo: {
item_added: { trigger: "mdi:clipboard-plus" },
item_completed: { trigger: "mdi:clipboard-check" },
item_removed: { trigger: "mdi:clipboard-minus" },
},
update: { became_available: { trigger: "mdi:package-up" } },
vacuum: {
errored: { trigger: "mdi:alert-circle-outline" },
paused_cleaning: { trigger: "mdi:pause" },
returned_to_dock: { trigger: "mdi:home-outline" },
started_cleaning: { trigger: "mdi:play" },
started_returning: { trigger: "mdi:home-import-outline" },
},
valve: {
closed: { trigger: "mdi:valve-closed" },
opened: { trigger: "mdi:valve-open" },
},
vibration: {
cleared: { trigger: "mdi:vibrate-off" },
detected: { trigger: "mdi:vibrate" },
},
water_heater: {
operation_mode_changed: { trigger: "mdi:water-boiler" },
target_temperature_changed: { trigger: "mdi:thermometer" },
target_temperature_crossed_threshold: { trigger: "mdi:thermometer" },
turned_off: { trigger: "mdi:water-boiler-off" },
turned_on: { trigger: "mdi:water-boiler" },
},
window: {
closed: { trigger: "mdi:window-closed" },
opened: { trigger: "mdi:window-open" },
},
zone: {
entered: { trigger: "mdi:map-marker-plus" },
left: { trigger: "mdi:map-marker-minus" },
occupancy_cleared: { trigger: "mdi:account-off" },
occupancy_detected: { trigger: "mdi:account-group" },
},
};
export const conditionIcons = {
air_quality: {
is_co2_value: { condition: "mdi:molecule-co2" },
is_co_cleared: { condition: "mdi:check-circle" },
is_co_detected: { condition: "mdi:molecule-co" },
is_co_value: { condition: "mdi:molecule-co" },
is_gas_cleared: { condition: "mdi:check-circle" },
is_gas_detected: { condition: "mdi:gas-cylinder" },
is_n2o_value: { condition: "mdi:factory" },
is_no2_value: { condition: "mdi:factory" },
is_no_value: { condition: "mdi:factory" },
is_ozone_value: { condition: "mdi:weather-sunny-alert" },
is_pm10_value: { condition: "mdi:blur" },
is_pm1_value: { condition: "mdi:blur" },
is_pm25_value: { condition: "mdi:blur" },
is_pm4_value: { condition: "mdi:blur" },
is_smoke_cleared: { condition: "mdi:check-circle" },
is_smoke_detected: { condition: "mdi:smoke-detector-variant" },
is_so2_value: { condition: "mdi:factory" },
is_voc_ratio_value: { condition: "mdi:air-filter" },
is_voc_value: { condition: "mdi:air-filter" },
},
alarm_control_panel: {
is_armed: { condition: "mdi:shield" },
is_armed_away: { condition: "mdi:shield-lock" },
is_armed_home: { condition: "mdi:shield-home" },
is_armed_night: { condition: "mdi:shield-moon" },
is_armed_vacation: { condition: "mdi:shield-airplane" },
is_disarmed: { condition: "mdi:shield-off" },
is_triggered: { condition: "mdi:bell-ring" },
},
assist_satellite: {
is_idle: { condition: "mdi:chat-sleep" },
is_listening: { condition: "mdi:chat-question" },
is_processing: { condition: "mdi:chat-processing" },
is_responding: { condition: "mdi:chat-alert" },
},
battery: {
is_charging: { condition: "mdi:battery-charging" },
is_level: { condition: "mdi:battery-unknown" },
is_low: { condition: "mdi:battery-alert" },
is_not_charging: { condition: "mdi:battery" },
is_not_low: { condition: "mdi:battery" },
},
calendar: { is_event_active: { condition: "mdi:calendar-check" } },
climate: {
is_cooling: { condition: "mdi:snowflake" },
is_drying: { condition: "mdi:water-percent" },
is_heating: { condition: "mdi:fire" },
is_hvac_mode: { condition: "mdi:thermostat" },
is_off: { condition: "mdi:power-off" },
is_on: { condition: "mdi:power-on" },
is_target_humidity: { condition: "mdi:water-percent" },
is_target_temperature: { condition: "mdi:thermometer" },
},
counter: { is_value: { condition: "mdi:counter" } },
cover: {
awning_is_closed: { condition: "mdi:storefront-outline" },
awning_is_open: { condition: "mdi:storefront-outline" },
blind_is_closed: { condition: "mdi:blinds-horizontal-closed" },
blind_is_open: { condition: "mdi:blinds-horizontal" },
curtain_is_closed: { condition: "mdi:curtains-closed" },
curtain_is_open: { condition: "mdi:curtains" },
shade_is_closed: { condition: "mdi:roller-shade-closed" },
shade_is_open: { condition: "mdi:roller-shade" },
shutter_is_closed: { condition: "mdi:window-shutter" },
shutter_is_open: { condition: "mdi:window-shutter-open" },
},
door: {
is_closed: { condition: "mdi:door-closed" },
is_open: { condition: "mdi:door-open" },
},
fan: {
is_off: { condition: "mdi:fan-off" },
is_on: { condition: "mdi:fan" },
},
garage_door: {
is_closed: { condition: "mdi:garage" },
is_open: { condition: "mdi:garage-open" },
},
gate: {
is_closed: { condition: "mdi:gate" },
is_open: { condition: "mdi:gate-open" },
},
humidifier: {
is_drying: { condition: "mdi:arrow-down-bold" },
is_humidifying: { condition: "mdi:arrow-up-bold" },
is_mode: { condition: "mdi:air-humidifier" },
is_off: { condition: "mdi:air-humidifier-off" },
is_on: { condition: "mdi:air-humidifier" },
is_target_humidity: { condition: "mdi:water-percent" },
},
humidity: { is_value: { condition: "mdi:water-percent" } },
illuminance: {
is_detected: { condition: "mdi:brightness-7" },
is_not_detected: { condition: "mdi:brightness-4" },
is_value: { condition: "mdi:brightness-percent" },
},
lawn_mower: {
is_docked: { condition: "mdi:home-import-outline" },
is_encountering_an_error: { condition: "mdi:alert-circle-outline" },
is_idle: { condition: "mdi:stop" },
is_mowing: { condition: "mdi:play" },
is_paused: { condition: "mdi:pause" },
is_returning: { condition: "mdi:home-import-outline" },
},
light: {
is_brightness: { condition: "mdi:lightbulb-on-50" },
is_off: { condition: "mdi:lightbulb-off" },
is_on: { condition: "mdi:lightbulb-on" },
},
lock: {
is_jammed: { condition: "mdi:lock-alert" },
is_locked: { condition: "mdi:lock" },
is_open: { condition: "mdi:lock-open-variant" },
is_unlocked: { condition: "mdi:lock-open-variant" },
},
media_player: {
is_muted: { condition: "mdi:volume-mute" },
is_not_playing: { condition: "mdi:stop" },
is_off: { condition: "mdi:cast-off" },
is_on: { condition: "mdi:cast" },
is_paused: { condition: "mdi:pause" },
is_playing: { condition: "mdi:play" },
is_unmuted: { condition: "mdi:volume-high" },
is_volume: { condition: "mdi:volume-medium" },
},
moisture: {
is_detected: { condition: "mdi:water" },
is_not_detected: { condition: "mdi:water-off" },
is_value: { condition: "mdi:water-percent" },
},
moon: {
is_phase: { condition: "mdi:moon-full" },
is_waning: { condition: "mdi:moon-waning-crescent" },
is_waxing: { condition: "mdi:moon-waxing-crescent" },
},
motion: {
is_detected: { condition: "mdi:motion-sensor" },
is_not_detected: { condition: "mdi:motion-sensor-off" },
},
occupancy: {
is_detected: { condition: "mdi:home-account" },
is_not_detected: { condition: "mdi:home-outline" },
},
power: { is_value: { condition: "mdi:flash" } },
remote: {
is_off: { condition: "mdi:remote-off" },
is_on: { condition: "mdi:remote" },
},
schedule: {
is_off: { condition: "mdi:calendar-blank" },
is_on: { condition: "mdi:calendar-clock" },
},
select: { is_option_selected: { condition: "mdi:format-list-bulleted" } },
siren: {
is_off: { condition: "mdi:bullhorn-outline" },
is_on: { condition: "mdi:bullhorn" },
},
sun: {
elevation: { condition: "mdi:sun-angle" },
is_ascending: { condition: "mdi:weather-sunset-up" },
is_blue_hour: { condition: "mdi:weather-sunset" },
is_descending: { condition: "mdi:weather-sunset-down" },
is_evening_twilight: { condition: "mdi:weather-sunset-down" },
is_golden_hour: { condition: "mdi:weather-sunset" },
is_midnight_sun: { condition: "mdi:weather-sunny" },
is_morning_twilight: { condition: "mdi:weather-sunset-up" },
is_night: { condition: "mdi:weather-night" },
is_polar_night: { condition: "mdi:weather-night" },
is_set: { condition: "mdi:weather-sunny-off" },
is_up: { condition: "mdi:weather-sunny" },
},
switch: {
is_off: { condition: "mdi:toggle-switch-variant-off" },
is_on: { condition: "mdi:toggle-switch-variant" },
},
temperature: { is_value: { condition: "mdi:thermometer" } },
text: { is_equal_to: { condition: "mdi:form-textbox" } },
timer: {
is_active: { condition: "mdi:timer" },
is_idle: { condition: "mdi:timer-off" },
is_paused: { condition: "mdi:timer-pause" },
},
todo: {
all_completed: { condition: "mdi:clipboard-check" },
incomplete: { condition: "mdi:clipboard-alert" },
},
update: {
is_available: { condition: "mdi:package-up" },
is_not_available: { condition: "mdi:package" },
},
vacuum: {
is_cleaning: { condition: "mdi:play" },
is_docked: { condition: "mdi:home-import-outline" },
is_encountering_an_error: { condition: "mdi:alert-circle-outline" },
is_paused: { condition: "mdi:pause" },
is_returning: { condition: "mdi:home-import-outline" },
},
valve: {
is_closed: { condition: "mdi:valve-closed" },
is_open: { condition: "mdi:valve-open" },
},
vibration: {
is_detected: { condition: "mdi:vibrate" },
is_not_detected: { condition: "mdi:vibrate-off" },
},
water_heater: {
is_off: { condition: "mdi:water-boiler-off" },
is_on: { condition: "mdi:water-boiler" },
is_operation_mode: { condition: "mdi:water-boiler" },
is_target_temperature: { condition: "mdi:thermometer" },
},
window: {
is_closed: { condition: "mdi:window-closed" },
is_open: { condition: "mdi:window-open" },
},
zone: {
in_zone: { condition: "mdi:map-marker-check" },
not_in_zone: { condition: "mdi:map-marker-remove" },
occupancy_is_detected: { condition: "mdi:account-group" },
occupancy_is_not_detected: { condition: "mdi:account-off" },
},
};
+11 -2
View File
@@ -1,7 +1,6 @@
import type {
BackupAgentsInfo,
BackupConfig,
BackupContent,
BackupInfo,
} from "../../../src/data/backup";
import { BackupScheduleRecurrence } from "../../../src/data/backup";
@@ -28,9 +27,19 @@ const backupInfo: BackupInfo = {
"backup.local": { size: 1024 * 1024 * 512, protected: true },
"cloud.cloud": { size: 1024 * 1024 * 512, protected: true },
},
} as BackupContent,
failed_agent_ids: [],
failed_addons: [],
failed_folders: [],
extra_metadata: {},
addons: [],
database_included: true,
folders: [],
homeassistant_included: true,
homeassistant_version: "2026.9.0",
},
],
agent_errors: {},
agent_error_translations: {},
last_attempted_automatic_backup: recent,
last_completed_automatic_backup: recent,
last_action_event: { manager_state: "idle" },
+7 -3
View File
@@ -20,12 +20,14 @@ const demoWebhooks: Webhook[] = [
domain: "automation",
name: "Front door motion",
local_only: false,
allowed_methods: ["POST", "PUT"],
},
{
webhook_id: "demo_companion_app",
domain: "mobile_app",
name: "Companion app",
local_only: false,
allowed_methods: ["POST", "PUT"],
},
];
@@ -49,12 +51,13 @@ const demoCloudhooks = Object.fromEntries(
// object directly and reset on reload.
const cloudStatus: CloudStatusLoggedIn = {
logged_in: true,
auto_login: null,
cloud: "connected",
cloud_last_disconnect_reason: null,
email: "[email protected]",
google_registered: false,
google_local_connected: false,
google_entities: emptyFilter(),
google_domains: ["light", "switch", "climate", "cover"],
alexa_registered: true,
alexa_entities: emptyFilter(),
remote_domain: "demo-instance.ui.nabu.casa",
@@ -75,10 +78,11 @@ const cloudStatus: CloudStatusLoggedIn = {
alexa_enabled: true,
remote_enabled: true,
remote_allow_remote_enable: true,
strict_connection: "disabled",
google_secure_devices_pin: undefined,
google_secure_devices_pin: null,
cloudhooks: demoCloudhooks,
alexa_default_expose: null,
alexa_report_state: true,
google_default_expose: null,
google_report_state: true,
tts_default_voice: ["en-US", "JennyNeural"],
cloud_ice_servers_enabled: false,
+10
View File
@@ -7,10 +7,12 @@ import { mockBlueprint } from "./blueprint";
import { mockCloud } from "./cloud";
import { mockConfig } from "./config";
import { mockConfigEntries } from "./config_entries";
import { mockConnectivity } from "./connectivity";
import { mockDeviceAutomation } from "./device_automation";
import { mockEntityRegistrySettings } from "./entity_registry_settings";
import { mockEntitySources } from "./entity_sources";
import { mockExpose } from "./expose";
import { mockMarketplace } from "./marketplace";
import { mockNetwork } from "./network";
import { mockPerson } from "./person";
import { mockScene } from "./scene";
@@ -26,6 +28,7 @@ export const mockConfigPanel = (hass: MockHomeAssistant) => {
mockCloud(hass);
mockConfig(hass);
mockConfigEntries(hass);
mockConnectivity(hass);
mockDeviceAutomation(hass);
mockEntitySources(hass);
mockBlueprint(hass);
@@ -43,4 +46,11 @@ export const mockConfigPanel = (hass: MockHomeAssistant) => {
mockAssist(hass);
mockEntityRegistrySettings(hass);
mockSlugify(hass);
mockMarketplace(hass);
hass.mockWS("llm/api/list", () => ({
apis: [
{ id: "assist", name: "Assist" },
{ id: "music_assistant", name: "Music Assistant" },
],
}));
};
+22
View File
@@ -5,6 +5,7 @@ import type {
import type { ConfigFlowInProgressMessage } from "../../../src/data/config_flow";
import type { IntegrationType } from "../../../src/data/integration";
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
import { connectivityConfigEntries } from "./connectivity/fixtures";
const baseEntry = {
source: "user",
@@ -19,6 +20,7 @@ const baseEntry = {
pref_disable_polling: false,
disabled_by: null,
reason: null,
error_reason_translation_domain: null,
error_reason_translation_key: null,
error_reason_translation_placeholders: null,
};
@@ -79,6 +81,26 @@ export const demoConfigEntries: {
title: "Comfort level",
},
},
{
type: "service",
entry: {
...baseEntry,
entry_id: "mock-mcp-server",
domain: "mcp_server",
title: "Assist, Music Assistant",
supports_options: true,
},
},
{
type: "system",
entry: {
...baseEntry,
entry_id: "mock-marketplace",
domain: "marketplace",
title: "Marketplace",
},
},
...connectivityConfigEntries,
];
const filterEntries = (filters?: {
@@ -0,0 +1,71 @@
import { manifest } from "../../manifest";
import { configEntry, device } from "../helpers";
import type { ConnectivityFixtures } from "../types";
export const LOCAL_SOURCE = "00:1A:7D:DA:71:11";
export const PROXY_SOURCE = "E8:DB:84:A1:C2:30";
export const SHED_SOURCE = "A4:CF:12:9B:44:70";
const ADAPTER_ENTRY_ID = "mock-bluetooth";
const PROXY_LIVING_ENTRY_ID = "mock-bluetooth-proxy-living";
const PROXY_SHED_ENTRY_ID = "mock-bluetooth-proxy-shed";
export const bluetoothFixtures: ConnectivityFixtures = {
components: ["bluetooth"],
commands: ["bluetooth/"],
manifests: [manifest("bluetooth", "Bluetooth", { integration_type: "hub" })],
configEntries: [
{
type: "hub",
entry: configEntry(
ADAPTER_ENTRY_ID,
"bluetooth",
`hci0 (${LOCAL_SOURCE})`,
{ source: "usb", supports_options: true }
),
},
{
type: "hub",
entry: configEntry(
PROXY_LIVING_ENTRY_ID,
"bluetooth",
"Living room proxy",
{ source: "esphome" }
),
},
{
type: "hub",
entry: configEntry(PROXY_SHED_ENTRY_ID, "bluetooth", "Shed proxy", {
source: "esphome",
}),
},
],
// Adapters and proxies are matched to their scanner by the bluetooth
// connection tuple, see ./mock.
devices: [
device(
"bluetooth-hci0",
"hci0",
"Home Assistant",
"Home Assistant Green",
ADAPTER_ENTRY_ID,
{ connections: [["bluetooth", LOCAL_SOURCE]] }
),
device(
"bluetooth-proxy-living",
"Living room proxy",
"Espressif",
"ESP32-C3",
PROXY_LIVING_ENTRY_ID,
{ area_id: "living_room", connections: [["bluetooth", PROXY_SOURCE]] }
),
device(
"bluetooth-proxy-shed",
"Shed proxy",
"Espressif",
"ESP32",
PROXY_SHED_ENTRY_ID,
{ connections: [["bluetooth", SHED_SOURCE]] }
),
],
};
Loaded 100 of 1929 files, more files were not shown because too many files have changed in this diff. Show more