diff --git a/app/api/__generated__/timeseries-metadata.ts b/app/api/__generated__/timeseries-metadata.ts new file mode 100644 index 000000000..03960d23e --- /dev/null +++ b/app/api/__generated__/timeseries-metadata.ts @@ -0,0 +1,2841 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ + +// generated by tools/generate_timeseries_metadata.ts from the oximeter schema +// TOML files in omicron. do not update manually. see docs/update-pinned-api.md + +import type { DatumType, FieldSchema, Units } from './Api' + +export const omicronVersion = '9d95e0cf4542d2bc776c40b69f97ba6e05cff199' + +type Field = Omit + +export const targets: Partial> = { + 'bfd-session': { + description: 'A Bidirectional Forwarding Protocol (BFD) session', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'The hostname of the machine running the BFD session', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack running the BFD session', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled running the BFD session', + }, + { + name: 'peer', + fieldType: 'ip_addr', + description: 'Address of the BFD session peer', + }, + ], + }, + 'bgp-session': { + description: 'A peer-to-peer session of the Border Gateway Protocol', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'Hostname of the server running our BGP peer', + }, + { + name: 'local_asn', + fieldType: 'u32', + description: 'The Autonomous System Number (ASN) advertised by our BGP peer', + }, + { + name: 'peer', + fieldType: 'ip_addr', + description: 'IP address of the other peer in our BGP session', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack on which our BGP peer is running', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled on which our BGP peer is running', + }, + ], + }, + 'collection-target': { + description: + 'A collection such as project or silo, whose provisioned virtual resources are tracked', + fields: [ + { name: 'id', fieldType: 'uuid', description: 'UUID of the tracked collection' }, + ], + }, + 'database-transaction': { + description: 'A named transaction run in the control plane database', + fields: [ + { name: 'name', fieldType: 'string', description: 'The name of the transaction' }, + ], + }, + 'ddm-router': { + description: 'A Delay-Driven Multipath (DDM) router', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'The hostname of the machine running the DDM router', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack running the DDM router', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled running the DDM router', + }, + ], + }, + 'ddm-session': { + description: 'A session in a Delay-Driven Multipath (DDM) router', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'The hostname of the machine running the DDM router', + }, + { + name: 'interface', + fieldType: 'string', + description: 'The host interface on which the DDM session is running', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack running the DDM router', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled running the DDM router', + }, + ], + }, + dendrite: { + description: 'Oxide switch management daemon', + fields: [ + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack containing the switch', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled managing the switch', + }, + { + name: 'sled_model', + fieldType: 'string', + description: 'The model of the sled managing the switch', + }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled managing the switch', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled managing the switch', + }, + ], + }, + 'hardware-component': { + description: 'A hardware component on a compute sled, switch, or power shelf', + fields: [ + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack on which this measurement was recorded.', + }, + { + name: 'slot', + fieldType: 'u32', + description: + 'The cubby number or switch slot of the service processor reporting the measurement', + }, + { + name: 'chassis_kind', + fieldType: 'string', + description: + "What kind of thing the component resides on.\n\nThis will be one of 'sled', for components on compute sleds; 'switch', for components on rack switches; or 'power', for components on power shelves.", + }, + { + name: 'chassis_serial', + fieldType: 'string', + description: 'Serial number of the sled, switch, or power shelf', + }, + { + name: 'chassis_model', + fieldType: 'string', + description: 'Model number of the sled, switch, or power shelf', + }, + { + name: 'chassis_revision', + fieldType: 'u32', + description: 'Revision number of the sled, switch, or power shelf', + }, + { + name: 'hubris_archive_id', + fieldType: 'string', + description: + 'Hubris firmware archive ID of the service processor when the measurement was recorded.', + }, + { + name: 'gateway_id', + fieldType: 'uuid', + description: + 'ID of the Management Gateway Service process which recorded the measurement.', + }, + { + name: 'component_kind', + fieldType: 'string', + description: 'What type of hardware component this thing is.', + }, + { + name: 'component_id', + fieldType: 'string', + description: + 'The service processor component ID uniquely identifying the hardware component on the sled, switch, or power shelf.', + }, + { + name: 'description', + fieldType: 'string', + description: + "A human-readable description of the hardware component. This may include its location or role in the system (e.g. a DIMM's number, or a temperature sensor's location).", + }, + ], + }, + 'http-service': { + description: 'An Oxide HTTP server', + fields: [ + { + name: 'name', + fieldType: 'string', + description: 'The name of the HTTP server, or program running it', + }, + { name: 'id', fieldType: 'uuid', description: 'UUID of the HTTP server' }, + ], + }, + 'instance-network-interface': { + description: 'A network interface attached to a virtual machine instance', + fields: [ + { + name: 'interface_id', + fieldType: 'uuid', + description: 'The ID of the network interface', + }, + { + name: 'instance_id', + fieldType: 'uuid', + description: + 'The ID of the virtual machine instance this network interface is attached to', + }, + { + name: 'project_id', + fieldType: 'uuid', + description: + 'The ID of the project containing the virtual machine instance this network interface is attached to', + }, + { + name: 'silo_id', + fieldType: 'uuid', + description: + 'The ID of the silo containing the virtual machine instance this network interface is attached to', + }, + ], + }, + 'kstat-sampler': { + description: 'A software object sampling kernel statistics', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'The hostname (or zonename) of the machine hosting the sampler', + }, + ], + }, + 'management-network-data-link': { + description: 'A data link on the management network', + fields: [ + { + name: 'kind', + fieldType: 'string', + description: + 'The kind or class of the data link, such as whether it is a physical or virtual device', + }, + { + name: 'model', + fieldType: 'string', + description: + 'Model type of the link, indicating what implements the link. For example, this might be the model number of a physical NIC, or the name of the software component that implements a virtual link.', + }, + { + name: 'network', + fieldType: 'string', + description: 'Network type of the link (examples: primary-data, management, vpc)', + }, + { + name: 'link_name', + fieldType: 'string', + description: 'The name of the link as it appears to Oxide-internal software', + }, + { name: 'rack_id', fieldType: 'uuid', description: "ID for the link's rack" }, + { name: 'sled_id', fieldType: 'uuid', description: "ID for the link's sled" }, + { + name: 'sled_model', + fieldType: 'string', + description: "Model number of the link's sled", + }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + { + name: 'switch_id', + fieldType: 'uuid', + description: 'ID of the switch the link is on', + }, + { + name: 'switch_model', + fieldType: 'string', + description: 'Model number of the switch the link is on', + }, + { + name: 'switch_revision', + fieldType: 'u32', + description: 'Revision number of the switch the link is on', + }, + { + name: 'switch_serial', + fieldType: 'string', + description: 'Serial number of the switch the link is on', + }, + { + name: 'switch_slot', + fieldType: 'u16', + description: 'Slot number of the switch the link is on', + }, + ], + }, + 'mg-lower': { + description: + 'The lower-half of the Oxide Maghemite routing daemon, which syncs routing information to an underlying routing platform, such as a switch ASIC. The routing information may be programmed directly from the control plane, or learned through routing protocols exchanging information with peers.', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'The hostname of the machine running the router', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack running the router', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled running the router', + }, + ], + }, + 'opte-port': { + description: + 'An OPTE port implementing a VPC network interface for an instance, service, or probe', + fields: [ + { name: 'port_name', fieldType: 'string', description: 'Name of the OPTE port' }, + { + name: 'interface_id', + fieldType: 'uuid', + description: "The ID of the OPTE port's network interface", + }, + { + name: 'interface_kind', + fieldType: 'string', + description: "The kind of the OPTE port's network interface", + }, + { + name: 'parent_id', + fieldType: 'uuid', + description: "The ID of the OPTE port's parent (instance, service, or probe)", + }, + { + name: 'zone_name', + fieldType: 'string', + description: 'Name of the zone owning the port', + }, + { name: 'rack_id', fieldType: 'uuid', description: "ID for the port's rack" }, + { name: 'sled_id', fieldType: 'uuid', description: "ID for the port's sled" }, + { + name: 'sled_model', + fieldType: 'string', + description: "Model number of the port's sled", + }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + ], + }, + 'oximeter-collector': { + description: 'An instance of the oximeter metric collector service', + fields: [ + { + name: 'collector_id', + fieldType: 'uuid', + description: 'UUID of the oximeter collector instance', + }, + { + name: 'collector_ip', + fieldType: 'ip_addr', + description: 'IP address of the oximeter collector instance', + }, + { + name: 'collector_port', + fieldType: 'u16', + description: 'Port of the oximeter collector instance', + }, + ], + }, + 'sled-cpu': { + description: 'CPU metrics for a compute sled', + fields: [ + { name: 'rack_id', fieldType: 'uuid', description: "ID for the CPU's rack" }, + { name: 'sled_id', fieldType: 'uuid', description: "ID for the CPU's sled" }, + { name: 'sled_model', fieldType: 'string', description: 'Model number of the sled' }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + ], + }, + 'sled-data-link': { + description: 'A network data link on a compute sled', + fields: [ + { + name: 'kind', + fieldType: 'string', + description: 'The kind or class of the data link', + }, + { name: 'link_name', fieldType: 'string', description: 'Name of the data link' }, + { name: 'rack_id', fieldType: 'uuid', description: "ID for the link's rack" }, + { name: 'sled_id', fieldType: 'uuid', description: "ID for the link's sled" }, + { + name: 'sled_model', + fieldType: 'string', + description: "Model number of the link's sled", + }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + { + name: 'zone_name', + fieldType: 'string', + description: 'Name of the zone owning the link', + }, + ], + }, + 'static-routing-config': { + description: 'Static routing configuration used by the Oxide routing daemons', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'The hostname of the machine running the router', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack running the router', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled running the router', + }, + ], + }, + 'switch-data-link': { + description: 'A network data link on an Oxide switch', + fields: [ + { + name: 'kind', + fieldType: 'string', + description: + 'The kind or class of the data link, such as whether it is a physical or virtual device', + }, + { + name: 'model', + fieldType: 'string', + description: + 'Model type of the link, indicating what implements the link. For example, this might be the model number of a physical NIC, or the name of the software component that implements a virtual link.', + }, + { + name: 'network', + fieldType: 'string', + description: 'Network type of the link (examples: primary-data, management, vpc)', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: "ID of the rack the link's switch is in", + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: "ID of the sled managing the link's switch", + }, + { + name: 'sled_model', + fieldType: 'string', + description: "Model number of the sled managing the link's switch", + }, + { + name: 'sled_revision', + fieldType: 'u32', + description: "Revision number of the sled managing the link's switch", + }, + { + name: 'sled_serial', + fieldType: 'string', + description: "Serial number of the sled managing the link's switch", + }, + { + name: 'switch_id', + fieldType: 'uuid', + description: 'ID of the switch the link is on', + }, + { + name: 'switch_model', + fieldType: 'string', + description: 'Model number of the switch the link is on', + }, + { + name: 'switch_revision', + fieldType: 'u32', + description: 'Revision number of the switch the link is on', + }, + { + name: 'switch_serial', + fieldType: 'string', + description: 'Serial number of the switch the link is on', + }, + { + name: 'switch_slot', + fieldType: 'u16', + description: 'Slot number of the switch the link is on', + }, + { + name: 'asic_fab', + fieldType: 'string', + description: 'Fabrication plant identifier of the switch ASIC the link is on', + }, + { + name: 'asic_lot', + fieldType: 'string', + description: 'Lot identifier of the switch ASIC the link is on', + }, + { + name: 'asic_wafer', + fieldType: 'u8', + description: 'Wafer identifier of the switch ASIC the link is on', + }, + { + name: 'asic_wafer_loc_x', + fieldType: 'i16', + description: 'X-coordinate wafer location of the switch ASIC the link is on', + }, + { + name: 'asic_wafer_loc_y', + fieldType: 'i16', + description: 'Y-coordinate wafer location of the switch ASIC the link is on', + }, + ], + }, + 'switch-port-control-data-link': { + description: + 'Network data for datalinks related to a switch and management control data', + fields: [ + { + name: 'kind', + fieldType: 'string', + description: + 'The kind or class of the data link, such as whether it is a physical or virtual device', + }, + { + name: 'model', + fieldType: 'string', + description: + 'Model type of the link, indicating what implements the link. For example, this might be the model number of a physical NIC, or the name of the software component that implements a virtual link.', + }, + { + name: 'network', + fieldType: 'string', + description: 'Network type of the link (examples: primary-data, management, vpc)', + }, + { + name: 'link_name', + fieldType: 'string', + description: 'The name of the link as it appears to Oxide-internal software', + }, + { name: 'rack_id', fieldType: 'uuid', description: "ID for the link's rack" }, + { name: 'sled_id', fieldType: 'uuid', description: "ID for the link's sled" }, + { + name: 'sled_model', + fieldType: 'string', + description: "Model number of the link's sled", + }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + { + name: 'switch_id', + fieldType: 'uuid', + description: 'ID of the switch the link is on', + }, + { + name: 'switch_model', + fieldType: 'string', + description: 'Model number of the switch the link is on', + }, + { + name: 'switch_revision', + fieldType: 'u32', + description: 'Revision number of the switch the link is on', + }, + { + name: 'switch_serial', + fieldType: 'string', + description: 'Serial number of the switch the link is on', + }, + { + name: 'switch_slot', + fieldType: 'u16', + description: 'Slot number of the switch the link is on', + }, + { + name: 'asic_fab', + fieldType: 'string', + description: 'Fabrication plant identifier of the switch ASIC the link is on', + }, + { + name: 'asic_lot', + fieldType: 'string', + description: 'Lot identifier of the switch ASIC the link is on', + }, + { + name: 'asic_wafer', + fieldType: 'u8', + description: 'Wafer identifier of the switch ASIC the link is on', + }, + { + name: 'asic_wafer_loc_x', + fieldType: 'i16', + description: 'X-coordinate wafer location of the switch ASIC the link is on', + }, + { + name: 'asic_wafer_loc_y', + fieldType: 'i16', + description: 'Y-coordinate wafer location of the switch ASIC the link is on', + }, + ], + }, + 'switch-rib': { + description: 'Maghemite router routing information base', + fields: [ + { + name: 'hostname', + fieldType: 'string', + description: 'Name of the host running the Oxide router', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled running the Oxide router', + }, + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack of the sled running the Oxide router', + }, + ], + }, + 'switch-table': { + description: 'A table on a Sidecar switch ASIC', + fields: [ + { + name: 'rack_id', + fieldType: 'uuid', + description: 'ID of the rack containing the switch', + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled responsible for managing the switch', + }, + { name: 'switch_id', fieldType: 'uuid', description: 'ID of the switch' }, + { + name: 'switch_model', + fieldType: 'string', + description: 'Model number of the switch', + }, + { + name: 'switch_revision', + fieldType: 'u32', + description: 'Revision number of the switch', + }, + { + name: 'switch_serial', + fieldType: 'string', + description: 'Serial number of the switch', + }, + { name: 'switch_slot', fieldType: 'u16', description: 'Slot number of the switch' }, + { + name: 'asic_fab', + fieldType: 'string', + description: 'Fabrication plant identifier of the switch ASIC', + }, + { + name: 'asic_lot', + fieldType: 'string', + description: 'Lot identifier of the switch ASIC', + }, + { + name: 'asic_wafer', + fieldType: 'u8', + description: 'Wafer identifier of the switch ASIC', + }, + { + name: 'asic_wafer_loc_x', + fieldType: 'i16', + description: 'X-coordinate wafer location of the switch ASIC', + }, + { + name: 'asic_wafer_loc_y', + fieldType: 'i16', + description: 'Y-coordinate wafer location of the switch ASIC', + }, + { name: 'table', fieldType: 'string', description: 'Name of the switch table' }, + ], + }, + 'virtual-disk': { + description: 'A virtual disk', + fields: [ + { + name: 'attached_instance_id', + fieldType: 'uuid', + description: 'ID of the instance the disk is attached to', + }, + { + name: 'block_size', + fieldType: 'u32', + description: 'Block size of the disk, in bytes', + }, + { name: 'disk_id', fieldType: 'uuid', description: 'ID of the disk' }, + { + name: 'project_id', + fieldType: 'uuid', + description: 'ID of the project containing the disk', + }, + { + name: 'silo_id', + fieldType: 'uuid', + description: 'ID for the silo containing the disk', + }, + ], + }, + 'virtual-machine': { + description: 'A guest virtual machine instance', + fields: [ + { + name: 'instance_id', + fieldType: 'uuid', + description: 'ID of the virtual machine instance', + }, + { + name: 'project_id', + fieldType: 'uuid', + description: "ID of the virtual machine instance's project", + }, + { + name: 'silo_id', + fieldType: 'uuid', + description: "ID of the virtual machine instance's silo", + }, + { + name: 'sled_id', + fieldType: 'uuid', + description: 'ID of the sled hosting the instance', + }, + { + name: 'sled_model', + fieldType: 'string', + description: 'Model number of the sled hosting the instance', + }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled hosting the instance', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled hosting the instance', + }, + ], + }, + 'vm-health-check': { + description: 'A virtual machine instance', + fields: [ + { + name: 'rack_id', + fieldType: 'uuid', + description: 'The rack ID of the Nexus process which performed the health check', + }, + { + name: 'nexus_id', + fieldType: 'uuid', + description: 'The ID of the Nexus process which performed the health check', + }, + { name: 'instance_id', fieldType: 'uuid', description: "The instance's ID" }, + { name: 'silo_id', fieldType: 'uuid', description: "The ID of the instance's silo" }, + { + name: 'project_id', + fieldType: 'uuid', + description: "The ID of the instance's project", + }, + { + name: 'vmm_id', + fieldType: 'uuid', + description: "The VMM ID of the instance's virtual machine manager", + }, + { + name: 'sled_agent_id', + fieldType: 'uuid', + description: 'The ID of the sled-agent managing the instance', + }, + { + name: 'sled_agent_ip', + fieldType: 'ip_addr', + description: 'The IP address of the sled-agent managing the instance', + }, + { + name: 'sled_agent_port', + fieldType: 'u16', + description: 'The port of the sled-agent managing the instance', + }, + ], + }, + zfs_dataset: { + description: 'Disk usage for a zfs dataset', + fields: [ + { name: 'rack_id', fieldType: 'uuid', description: 'ID for the rack' }, + { name: 'sled_id', fieldType: 'uuid', description: 'ID for the sled' }, + { name: 'sled_model', fieldType: 'string', description: 'Model number of the sled' }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + ], + }, + zfs_pool: { + description: 'Disk usage for a zfs pool', + fields: [ + { name: 'rack_id', fieldType: 'uuid', description: 'ID for the rack' }, + { name: 'sled_id', fieldType: 'uuid', description: 'ID for the sled' }, + { name: 'sled_model', fieldType: 'string', description: 'Model number of the sled' }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + ], + }, + zone: { + description: 'Metrics for a host zone', + fields: [ + { name: 'rack_id', fieldType: 'uuid', description: 'ID for the rack' }, + { name: 'sled_id', fieldType: 'uuid', description: 'ID for the sled' }, + { name: 'sled_model', fieldType: 'string', description: 'Model number of the sled' }, + { + name: 'sled_revision', + fieldType: 'u32', + description: 'Revision number of the sled', + }, + { + name: 'sled_serial', + fieldType: 'string', + description: 'Serial number of the sled', + }, + ], + }, +} + +export const timeseries: Partial< + Record< + string, + { + /** key into `targets` */ + target: string + description: string + units: Units + datumType: DatumType + fields: Field[] + } + > +> = { + 'bfd_session:control_packet_send_failures': { + target: 'bfd-session', + description: 'Total number of failures to send a control packets to a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bfd_session:control_packets_received': { + target: 'bfd-session', + description: 'Total number of control packets received from a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bfd_session:control_packets_sent': { + target: 'bfd-session', + description: 'Total number of control packets sent to a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bfd_session:message_receive_error': { + target: 'bfd-session', + description: + 'Total number of failures to receive a BFD packet from the internal dispatcher', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bfd_session:timeout_expired': { + target: 'bfd-session', + description: + 'Total number of expired timeouts waiting for a BFD packet from the internal dispatcher', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bfd_session:transition_to_down': { + target: 'bfd-session', + description: + 'Total number of times the BFD session has entered the down state, whether because the peer could not be reached, or because the session was marked administratively down.', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bfd_session:transition_to_init': { + target: 'bfd-session', + description: 'Total number of times the BFD session has entered the init state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bfd_session:transition_to_up': { + target: 'bfd-session', + description: 'Total number of times the BFD session has entered the up state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:active_connections_accepted': { + target: 'bgp-session', + description: 'Number of active connections initiated by us accepted by the other peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:connection_retries': { + target: 'bgp-session', + description: 'Number of times our connection retry timer has expired', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:hold_timer_expirations': { + target: 'bgp-session', + description: 'Number of times our hold timer has expired', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:idle_hold_timer_expirations': { + target: 'bgp-session', + description: 'Number of times our idle hold timer has expired', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:keepalive_send_failures': { + target: 'bgp-session', + description: 'Number of times we failed to send a keep-alive message to the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:keepalives_received': { + target: 'bgp-session', + description: 'Number of keep-alive messages received from the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:keepalives_sent': { + target: 'bgp-session', + description: 'Number keep-alive messages to the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:notification_send_failures': { + target: 'bgp-session', + description: 'Number of times we failed to send a notification message to the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:open_handle_failures': { + target: 'bgp-session', + description: 'Number of times we failed to handle an open message from the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:open_send_failures': { + target: 'bgp-session', + description: 'Number of times we failed to send an open message to the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:opens_received': { + target: 'bgp-session', + description: 'Number of open messages received from the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:opens_sent': { + target: 'bgp-session', + description: 'Number of open messages sent to the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:passive_connections_accepted': { + target: 'bgp-session', + description: 'Number of TCP connections accepted by our BGP peer socket', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:prefixes_advertised': { + target: 'bgp-session', + description: 'Number of prefixes advertised by our BGP peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:prefixes_imported': { + target: 'bgp-session', + description: 'Number of prefixes imported by our BGP peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:transition_to_active': { + target: 'bgp-session', + description: 'Number of times our BGP peer has entered the active state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:transition_to_connect': { + target: 'bgp-session', + description: 'Number of times our BGP peer has entered the connect state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:transition_to_established': { + target: 'bgp-session', + description: 'Number of times our BGP peer has entered the established state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:transition_to_idle': { + target: 'bgp-session', + description: 'Number of times our BGP peer has entered the idle state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:transition_to_open_confirm': { + target: 'bgp-session', + description: 'Number of times our BGP peer has entered the open-confirm state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:transition_to_open_sent': { + target: 'bgp-session', + description: 'Number of times our BGP peer has entered the open-sent state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:transition_to_session_setup': { + target: 'bgp-session', + description: 'Number of times our BGP peer has entered the session-setup state', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:unexpected_keepalive_messages': { + target: 'bgp-session', + description: 'Number of unexpected keep-alive messages from the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:unexpected_open_messages': { + target: 'bgp-session', + description: 'Number of unexpected open messages from the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:unexpected_update_messages': { + target: 'bgp-session', + description: 'Number of unexpected update messages from the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:update_nexthop_missing': { + target: 'bgp-session', + description: + 'Number of update messages received with reachability entries, but no next hop path attribute', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:update_send_failures': { + target: 'bgp-session', + description: 'Number of times we failed to send an update message to the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:updates_received': { + target: 'bgp-session', + description: 'Number of update messages received from the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'bgp_session:updates_sent': { + target: 'bgp-session', + description: 'Number of update messages sent to the peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'collection_target:cpus_provisioned': { + target: 'collection-target', + description: 'Total number of vCPUs provisioned in the collection', + units: 'count', + datumType: 'i64', + fields: [], + }, + 'collection_target:ram_provisioned': { + target: 'collection-target', + description: 'Total memory provisioned in the collection', + units: 'bytes', + datumType: 'i64', + fields: [], + }, + 'collection_target:virtual_disk_space_provisioned': { + target: 'collection-target', + description: 'Total virtual disk space provisioned in the collection', + units: 'bytes', + datumType: 'i64', + fields: [], + }, + 'database_transaction:retry_data': { + target: 'database-transaction', + description: 'Information about a retried transaction', + units: 'seconds', + datumType: 'f64', + fields: [ + { + name: 'attempt', + fieldType: 'u32', + description: 'The attempt at running the transaction', + }, + ], + }, + 'ddm_router:originated_tunnel_endpoints': { + target: 'ddm-router', + description: 'Current number of tunnel endpoints this router advertises', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'ddm_router:originated_underlay_prefixes': { + target: 'ddm-router', + description: + 'Current number of prefixes on the underlay network this router advertises', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'ddm_session:advertisements_received': { + target: 'ddm-session', + description: 'Total number of advertisements received from a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:advertisements_sent': { + target: 'ddm-session', + description: 'Total number of advertisements sent to a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:imported_tunnel_endpoints': { + target: 'ddm-session', + description: 'Current count of tunnel endpoints imported from a peer', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'ddm_session:imported_underlay_prefixes': { + target: 'ddm-session', + description: 'Current count of underlay prefixes imported from a peer', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'ddm_session:peer_address_changes': { + target: 'ddm-session', + description: 'Total number of times a peer changed its underlay address', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:peer_expirations': { + target: 'ddm-session', + description: + 'Total number of times a peer was expired because we received no messages from it within the expiration threshold', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:peer_sessions_established': { + target: 'ddm-session', + description: 'Total number of times a session was established with a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:solicitations_received': { + target: 'ddm-session', + description: 'Total number of soliciation messages received from a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:solicitations_sent': { + target: 'ddm-session', + description: 'Total number of soliciation messages sent to a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:update_send_fail': { + target: 'ddm-session', + description: 'Total number of failures to send an update message to a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:updates_received': { + target: 'ddm-session', + description: 'Total number of update messages received from a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'ddm_session:updates_sent': { + target: 'ddm-session', + description: 'Total number of update messages sent to a peer', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'dendrite:sample_collection_duration': { + target: 'dendrite', + description: 'Duration spent collecting all timeseries samples', + units: 'seconds', + datumType: 'f64', + fields: [ + { + name: 'switch_id', + fieldType: 'uuid', + description: 'ID of the switch being managed', + }, + { + name: 'switch_model', + fieldType: 'string', + description: 'The model number of the switch being managed', + }, + { + name: 'switch_revision', + fieldType: 'u32', + description: 'Revision number of the switch being managed', + }, + { + name: 'switch_serial', + fieldType: 'string', + description: 'Serial number of the switch being managed', + }, + { + name: 'switch_slot', + fieldType: 'u16', + description: 'Slot number of the switch being managed', + }, + { + name: 'asic_fab', + fieldType: 'string', + description: 'Fabrication plant identifier of the switch ASIC being managed', + }, + { + name: 'asic_lot', + fieldType: 'string', + description: 'Lot identifier of the switch ASIC being managed', + }, + { + name: 'asic_wafer', + fieldType: 'u8', + description: 'Wafer identifier of the switch ASIC being managed', + }, + { + name: 'asic_wafer_loc_x', + fieldType: 'i16', + description: 'X-coordinate wafer location of the switch ASIC being managed', + }, + { + name: 'asic_wafer_loc_y', + fieldType: 'i16', + description: 'Y-coordinate wafer location of the switch ASIC being managed', + }, + ], + }, + 'hardware_component:amd_cpu_tctl': { + target: 'hardware-component', + description: + "A CPU Tctl (control temperature) reading from an AMD CPU.\n\nNote that, unlike other temperature metrics, this is not a measurement of temperature in degrees Celsius or Fahrenheit, but is instead a dimensionless quantity used by the processor's thermal control loop. This value has two notable thresholds:\n\n1. At a value of 95, the CPU will begin internal thermal throttling.\n2. At a value of 100, the CPU will shut down.", + units: 'none', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:current': { + target: 'hardware-component', + description: 'Output current reading in amperes', + units: 'amps', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:fan_speed': { + target: 'hardware-component', + description: 'A fan speed measurement, in rotations per minute', + units: 'rpm', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:input_current': { + target: 'hardware-component', + description: 'Input electric current reading in amperes', + units: 'amps', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:input_energy': { + target: 'hardware-component', + description: 'Sampled input energy.\n', + units: 'joules', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:input_power': { + target: 'hardware-component', + description: 'Input power.\n', + units: 'watts', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:input_voltage': { + target: 'hardware-component', + description: 'Input electric voltage reading, in volts', + units: 'volts', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:output_energy': { + target: 'hardware-component', + description: 'Sampled output energy.\n', + units: 'joules', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:poll_error_count': { + target: 'hardware-component', + description: + "Cumulative count of errors encountered whilst polling a component's sensors.\n\nUnlike the `sensor_error_count` metric, this counts errors encountered by the management gateway while polling the component, rather than errors reported by the component itself.", + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'error', + fieldType: 'string', + description: 'The kind of sensor error that occurred', + }, + ], + }, + 'hardware_component:power': { + target: 'hardware-component', + description: 'Power reading, in watts', + units: 'watts', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:pwm': { + target: 'hardware-component', + description: 'PWM duty cycle normalized to the 0.0-1.0 range.\n', + units: 'none', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:sensor_error_count': { + target: 'hardware-component', + description: 'Cumulative count of errors reported by a sensor', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + { + name: 'error', + fieldType: 'string', + description: 'The kind of sensor error that occurred', + }, + { + name: 'sensor_kind', + fieldType: 'string', + description: + "Which kind of sensor could not be read due to a sensor error.\n\nThis will be one of 'temperature', 'current', 'power', 'voltage', 'input_current', 'input_voltage', 'fan_speed', 'amd_cpu_tctl', 'pwm', 'input_power', 'output_energy', or 'input_energy' (the same names as the metrics emitted by these sensors when they are read successfully).", + }, + ], + }, + 'hardware_component:temperature': { + target: 'hardware-component', + description: + 'A physical temperature reading from a hardware component.\n\nNote that AMD host CPUs report a control temperature (Tctl) value, which is *not* a temperature measurement in degrees Celsius, but a dimensionless value that represents how close the CPU is to thermal throttling. This value is recorded in a separate `hardware_component:amd_cpu_tctl` metric.', + units: 'degrees_celsius', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'hardware_component:voltage': { + target: 'hardware-component', + description: 'Output voltage reading, in volts', + units: 'volts', + datumType: 'f32', + fields: [ + { + name: 'sensor', + fieldType: 'string', + description: 'The name of a sensor that recorded a sensor reading.', + }, + ], + }, + 'http_service:request_latency_histogram': { + target: 'http-service', + description: 'Duration for the server to handle a request', + units: 'nanoseconds', + datumType: 'histogram_u64', + fields: [ + { + name: 'operation_id', + fieldType: 'string', + description: + 'The identifier for the HTTP operation.In most cases, this the OpenAPI `operationId` field that uniquely identifies the\nendpoint the request is targeted to and the HTTP method used.\n', + }, + { + name: 'status_code', + fieldType: 'u16', + description: "HTTP status code in the server's response", + }, + ], + }, + 'instance_network_interface:bytes_received': { + target: 'instance-network-interface', + description: 'Total number of bytes received on the network interface', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'instance_network_interface:bytes_sent': { + target: 'instance-network-interface', + description: 'Total number of bytes sent on the network interface', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'instance_network_interface:errors_received': { + target: 'instance-network-interface', + description: 'Number of errors encountered when receiving on the network interface', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'instance_network_interface:errors_sent': { + target: 'instance-network-interface', + description: 'Number of errors encountered when sending on the network interface', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'instance_network_interface:packets_dropped': { + target: 'instance-network-interface', + description: 'Number of packets dropped on the RX queue of the network interface', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'instance_network_interface:packets_received': { + target: 'instance-network-interface', + description: 'Total number of packets received on the network interface', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'instance_network_interface:packets_sent': { + target: 'instance-network-interface', + description: 'Total number of packets sent on the network interface', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'kstat_sampler:expired_targets': { + target: 'kstat-sampler', + description: + 'Total number of targets that have expired. Targets may expire after either a limited number of unsuccessful sampling attempts, or after a duration of unsuccessful sampling.', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'kstat_sampler:samples_dropped': { + target: 'kstat-sampler', + description: 'Total number of samples dropped for a single tracked target', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'target_id', + fieldType: 'u64', + description: 'The unique ID of the target being tracked', + }, + { + name: 'target_name', + fieldType: 'string', + description: 'The name of the target being tracked', + }, + ], + }, + 'management_network_data_link:bytes_received': { + target: 'management-network-data-link', + description: 'Number of bytes received on the link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'management_network_data_link:bytes_sent': { + target: 'management-network-data-link', + description: 'Number of bytes sent on the link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'management_network_data_link:errors_received': { + target: 'management-network-data-link', + description: 'Number of errors encountered when receiving on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'management_network_data_link:errors_sent': { + target: 'management-network-data-link', + description: 'Number of errors encountered when sending on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'management_network_data_link:packets_received': { + target: 'management-network-data-link', + description: 'Number of packets received on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'management_network_data_link:packets_sent': { + target: 'management-network-data-link', + description: 'Number of packets sent on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'mg_lower:routes_blocked_by_link_state': { + target: 'mg-lower', + description: + 'The current number of routes that cannot be used because the link through which they should be available is not in a usable state', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'opte_port:in_uft_evictions': { + target: 'opte-port', + description: 'Inbound Unified Flow Table (UFT) cache evictions', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:in_uft_flows': { + target: 'opte-port', + description: 'Number of cached inbound Unified Flow Table (UFT) flows', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'opte_port:in_uft_hits': { + target: 'opte-port', + description: 'Inbound Unified Flow Table (UFT) cache hits', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:in_uft_misses': { + target: 'opte-port', + description: 'Inbound Unified Flow Table (UFT) cache misses', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:out_uft_evictions': { + target: 'opte-port', + description: 'Outbound Unified Flow Table (UFT) cache evictions', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:out_uft_flows': { + target: 'opte-port', + description: 'Number of cached outbound Unified Flow Table (UFT) flows', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'opte_port:out_uft_hits': { + target: 'opte-port', + description: 'Outbound Unified Flow Table (UFT) cache hits', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:out_uft_misses': { + target: 'opte-port', + description: 'Outbound Unified Flow Table (UFT) cache misses', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:route_cache_hits': { + target: 'opte-port', + description: 'Outbound packets that reused a cached nexthop', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:route_cache_misses': { + target: 'opte-port', + description: 'Outbound packets that required a nexthop lookup from the OS', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'opte_port:route_cache_occupancy': { + target: 'opte-port', + description: 'Current number of cached nexthops', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'opte_port:route_cache_table_full': { + target: 'opte-port', + description: 'Nexthop lookups not cached because the cache was at capacity', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'oximeter_collector:collections': { + target: 'oximeter-collector', + description: 'Total number of successful collections from a producer', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'base_route', + fieldType: 'string', + description: 'Base HTTP route used to request data from the producer', + }, + { + name: 'producer_id', + fieldType: 'uuid', + description: 'UUID of the metric producer instance', + }, + { + name: 'producer_ip', + fieldType: 'ip_addr', + description: 'IP address of the metric producer instance', + }, + { + name: 'producer_port', + fieldType: 'u16', + description: 'Port of the metric producer instance', + }, + ], + }, + 'oximeter_collector:database_queue_depth': { + target: 'oximeter-collector', + description: 'Size of the database insertion queue, sampled at queue insert time', + units: 'count', + datumType: 'histogram_u64', + fields: [ + { + name: 'collector_sink', + fieldType: 'string', + description: 'Name of collector metrics destination', + }, + ], + }, + 'oximeter_collector:database_samples_dropped': { + target: 'oximeter-collector', + description: 'Total number of samples dropped from the database insertion queue', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'collector_sink', + fieldType: 'string', + description: 'Name of collector metrics destination', + }, + ], + }, + 'oximeter_collector:failed_collections': { + target: 'oximeter-collector', + description: 'Total number of failed collections from a producer', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'base_route', + fieldType: 'string', + description: 'Base HTTP route used to request data from the producer', + }, + { + name: 'producer_id', + fieldType: 'uuid', + description: 'UUID of the metric producer instance', + }, + { + name: 'producer_ip', + fieldType: 'ip_addr', + description: 'IP address of the metric producer instance', + }, + { + name: 'producer_port', + fieldType: 'u16', + description: 'Port of the metric producer instance', + }, + { name: 'reason', fieldType: 'string', description: 'Reason the collection failed' }, + ], + }, + 'oximeter_collector:samples_collected': { + target: 'oximeter-collector', + description: 'Total number of samples collected from a producer', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'base_route', + fieldType: 'string', + description: 'Base HTTP route used to request data from the producer', + }, + { + name: 'producer_id', + fieldType: 'uuid', + description: 'UUID of the metric producer instance', + }, + { + name: 'producer_ip', + fieldType: 'ip_addr', + description: 'IP address of the metric producer instance', + }, + { + name: 'producer_port', + fieldType: 'u16', + description: 'Port of the metric producer instance', + }, + ], + }, + 'sled_cpu:cpu_nsec': { + target: 'sled-cpu', + description: 'Cumulative nanoseconds spent in a CPU microstate', + units: 'nanoseconds', + datumType: 'cumulative_u64', + fields: [ + { name: 'cpu_id', fieldType: 'u32', description: 'The CPU core identifier' }, + { + name: 'state', + fieldType: 'string', + description: 'The CPU microstate (idle, user, kernel, dtrace, intr)', + }, + ], + }, + 'sled_data_link:bytes_received': { + target: 'sled-data-link', + description: 'Number of bytes received on the link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'sled_data_link:bytes_sent': { + target: 'sled-data-link', + description: 'Number of bytes sent on the link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'sled_data_link:errors_received': { + target: 'sled-data-link', + description: 'Number of errors encountered when receiving on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'sled_data_link:errors_sent': { + target: 'sled-data-link', + description: 'Number of errors encountered when sending on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'sled_data_link:packets_received': { + target: 'sled-data-link', + description: 'Number of packets received on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'sled_data_link:packets_sent': { + target: 'sled-data-link', + description: 'Number of packets sent on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'static_routing_config:static_nexthops': { + target: 'static-routing-config', + description: 'Current number of static next-hops in the router', + units: 'seconds', + datumType: 'cumulative_u64', + fields: [], + }, + 'static_routing_config:static_routes': { + target: 'static-routing-config', + description: 'Current number of static routes in the router', + units: 'seconds', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_data_link:bytes_received': { + target: 'switch-data-link', + description: 'Total number of bytes received on the data link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:bytes_sent': { + target: 'switch-data-link', + description: 'Total number of bytes sent on the data link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:errors_received': { + target: 'switch-data-link', + description: 'Total number of packets for the data link dropped due to any error', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:errors_sent': { + target: 'switch-data-link', + description: 'Total number of errors when sending on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:fec_corrected_blocks': { + target: 'switch-data-link', + description: 'Total number of FEC blocks that were corrected', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:fec_high_symbol_errors': { + target: 'switch-data-link', + description: 'FEC symbol error threshold exceeded', + units: 'none', + datumType: 'bool', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:fec_symbol_errors': { + target: 'switch-data-link', + description: 'Total number of FEC symbol errors', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'lane', + fieldType: 'u8', + description: 'Lane (Tx/Rx pair) within a single link', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:fec_sync_aligned': { + target: 'switch-data-link', + description: 'All lanes synchronized and aligned', + units: 'none', + datumType: 'bool', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:fec_uncorrected_blocks': { + target: 'switch-data-link', + description: 'Total number of FEC blocks that were uncorrected', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:link_enabled': { + target: 'switch-data-link', + description: 'Reports whether the link is currently enabled', + units: 'none', + datumType: 'bool', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:link_fsm': { + target: 'switch-data-link', + description: + 'Total entries into each state of the autonegotation / link-training finite state machine', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + { + name: 'state', + fieldType: 'string', + description: 'Name of the data link FSM state', + }, + ], + }, + 'switch_data_link:link_up': { + target: 'switch-data-link', + description: 'Reports whether the link is currently up', + units: 'none', + datumType: 'bool', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:packets_received': { + target: 'switch-data-link', + description: 'Total number of packets received on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:packets_sent': { + target: 'switch-data-link', + description: 'Total number of packets sent on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_bad_sync_headers': { + target: 'switch-data-link', + description: 'Total number of bad PCS sync headers on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_block_lock_loss': { + target: 'switch-data-link', + description: 'Total number of detected losses of block-lock on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_errored_blocks': { + target: 'switch-data-link', + description: 'Total number of PCS error blocks on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_high_ber': { + target: 'switch-data-link', + description: 'Total number of high bit-error-rate events on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_invalid_errors': { + target: 'switch-data-link', + description: 'Total number of invalid error events on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_sync_loss': { + target: 'switch-data-link', + description: 'Total number of times PCS sync was lost on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_unknown_errors': { + target: 'switch-data-link', + description: 'Total number of unknown error events on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:pcs_valid_errors': { + target: 'switch-data-link', + description: 'Total number of valid error events on the data link', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:receive_buffer_full_drops': { + target: 'switch-data-link', + description: + 'Total number of packets for the data link dropped due to ASIC buffer congestion', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_data_link:receive_crc_error_drops': { + target: 'switch-data-link', + description: 'Total number of packets for the data link dropped due to CRC errors', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'port_id', + fieldType: 'string', + description: 'Physical switch port the link is on', + }, + { + name: 'link_id', + fieldType: 'u8', + description: 'ID of the link within its switch port', + }, + ], + }, + 'switch_port_control_data_link:bytes_received': { + target: 'switch-port-control-data-link', + description: 'Number of bytes received on the link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_port_control_data_link:bytes_sent': { + target: 'switch-port-control-data-link', + description: 'Number of bytes sent on the link', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_port_control_data_link:errors_received': { + target: 'switch-port-control-data-link', + description: 'Number of errors encountered when receiving on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_port_control_data_link:errors_sent': { + target: 'switch-port-control-data-link', + description: 'Number of errors encountered when sending on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_port_control_data_link:packets_received': { + target: 'switch-port-control-data-link', + description: 'Number of packets received on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_port_control_data_link:packets_sent': { + target: 'switch-port-control-data-link', + description: 'Number of packets sent on the link', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_rib:active_routes': { + target: 'switch-rib', + description: 'The number of currently active routes', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'switch_table:capacity': { + target: 'switch-table', + description: 'Maximum number of entries in the table', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'switch_table:collisions': { + target: 'switch-table', + description: 'Total number of inserts failed due to a collision', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_table:delete_misses': { + target: 'switch-table', + description: 'Total number of deletes that failed due to a missing entry', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_table:deletes': { + target: 'switch-table', + description: 'Total number of entries deleted', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_table:exhaustion': { + target: 'switch-table', + description: 'Total number of inserts that failed due to space exhaustion', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_table:inserts': { + target: 'switch-table', + description: 'Total number of entries inserted', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_table:occupancy': { + target: 'switch-table', + description: 'Current number of entries in the table', + units: 'count', + datumType: 'u64', + fields: [], + }, + 'switch_table:update_misses': { + target: 'switch-table', + description: 'Total number of updates that failed due to a missing entry', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'switch_table:updates': { + target: 'switch-table', + description: 'Total number of entries updated in place', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_disk:bytes_discarded': { + target: 'virtual-disk', + description: 'Number of bytes discarded from the disk', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_disk:bytes_read': { + target: 'virtual-disk', + description: 'Number of bytes read from the disk', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_disk:bytes_written': { + target: 'virtual-disk', + description: 'Number of bytes written to the disk', + units: 'bytes', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_disk:discards': { + target: 'virtual-disk', + description: 'Total number of discard operations to the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_disk:failed_discards': { + target: 'virtual-disk', + description: 'Total number of failed discard operations to the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'failure_reason', + fieldType: 'string', + description: 'The reason an I/O operation failed', + }, + ], + }, + 'virtual_disk:failed_flushes': { + target: 'virtual-disk', + description: 'Total number of failed flush operations on the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'failure_reason', + fieldType: 'string', + description: 'The reason an I/O operation failed', + }, + ], + }, + 'virtual_disk:failed_reads': { + target: 'virtual-disk', + description: 'Total number of failed read operations from the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'failure_reason', + fieldType: 'string', + description: 'The reason an I/O operation failed', + }, + ], + }, + 'virtual_disk:failed_writes': { + target: 'virtual-disk', + description: 'Total number of failed write operations to the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'failure_reason', + fieldType: 'string', + description: 'The reason an I/O operation failed', + }, + ], + }, + 'virtual_disk:flushes': { + target: 'virtual-disk', + description: 'Total number of flush operations on the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_disk:io_latency': { + target: 'virtual-disk', + description: 'Histogram of latency for I/O operations by kind', + units: 'nanoseconds', + datumType: 'histogram_u64', + fields: [ + { name: 'io_kind', fieldType: 'string', description: 'The kind of I/O operation' }, + ], + }, + 'virtual_disk:io_size': { + target: 'virtual-disk', + description: 'Histogram of sizes for I/O operations by kind', + units: 'bytes', + datumType: 'histogram_u64', + fields: [ + { name: 'io_kind', fieldType: 'string', description: 'The kind of I/O operation' }, + ], + }, + 'virtual_disk:reads': { + target: 'virtual-disk', + description: 'Total number of read operations from the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_disk:writes': { + target: 'virtual-disk', + description: 'Total number of write operations to the disk', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_machine:check': { + target: 'vm-health-check', + description: "The number of successful checks of an instance's health", + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'state', + fieldType: 'string', + description: + 'The string representation of the instance\'s state as understood by the VMM. If the check failed, this will generally be "failed".', + }, + { + name: 'reason', + fieldType: 'string', + description: + 'Why the instance was marked as being in this state.\n\nIf an instance was marked as "failed" due to a check failure, this will be a string representation of the failure reason. Otherwise, if the check was successful, this will be "success". Note that this may be "success" even if the instance\'s state is "failed", which indicates that we successfully queried the instance\'s state from the sled-agent, and the *sled-agent* reported that the instance has failed -- which is distinct from the instance watcher marking an instance as failed due to a failed check.', + }, + ], + }, + 'virtual_machine:incomplete_check': { + target: 'vm-health-check', + description: "The number of unsuccessful checks of an instance's health", + units: 'count', + datumType: 'cumulative_u64', + fields: [ + { + name: 'failure_reason', + fieldType: 'string', + description: 'The reason why the instance healh check failed', + }, + ], + }, + 'virtual_machine:pv_panic_guest_handled': { + target: 'virtual-machine', + description: 'Cumulative number of times a PVPANIC event was handled by the guest', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_machine:pv_panic_host_handled': { + target: 'virtual-machine', + description: 'Cumulative number of times a PVPANIC event was handled by the host', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_machine:reset': { + target: 'virtual-machine', + description: 'Cumulative number of times the virtual machine has been reset', + units: 'count', + datumType: 'cumulative_u64', + fields: [], + }, + 'virtual_machine:vcpu_usage': { + target: 'virtual-machine', + description: 'Cumulative time each vCPU has spent in a state', + units: 'nanoseconds', + datumType: 'cumulative_u64', + fields: [ + { name: 'state', fieldType: 'string', description: 'The state of the vCPU' }, + { name: 'vcpu_id', fieldType: 'u32', description: 'The ID of the vCPU' }, + ], + }, + 'zfs_dataset:bytes_used': { + target: 'zfs_dataset', + description: 'Bytes used for the dataset', + units: 'bytes', + datumType: 'u64', + fields: [ + { name: 'dataset_name', fieldType: 'string', description: 'Name of the dataset' }, + { + name: 'pool_kind', + fieldType: 'string', + description: 'Control plane kind of the parent zpool', + }, + { + name: 'pool_id', + fieldType: 'uuid', + description: 'Control plane UUID of the parent zpool', + }, + { + name: 'dataset_kind', + fieldType: 'string', + description: 'Control plane kind of the dataset', + }, + { + name: 'dataset_id', + fieldType: 'uuid', + description: 'Control plane UUID of the dataset', + }, + { + name: 'zone_name', + fieldType: 'string', + description: 'Name of the associated zone', + }, + ], + }, + 'zfs_pool:bytes_allocated': { + target: 'zfs_pool', + description: 'Bytes allocated for the pool', + units: 'bytes', + datumType: 'u64', + fields: [ + { name: 'pool_name', fieldType: 'string', description: 'Name of the zpool' }, + { + name: 'pool_kind', + fieldType: 'string', + description: 'Control plane kind of the zpool', + }, + { + name: 'pool_id', + fieldType: 'uuid', + description: 'Control plane UUID of the zpool', + }, + ], + }, + 'zfs_pool:bytes_total': { + target: 'zfs_pool', + description: 'Total size for the pool', + units: 'bytes', + datumType: 'u64', + fields: [ + { name: 'pool_name', fieldType: 'string', description: 'Name of the zpool' }, + { + name: 'pool_kind', + fieldType: 'string', + description: 'Control plane kind of the zpool', + }, + { + name: 'pool_id', + fieldType: 'uuid', + description: 'Control plane UUID of the zpool', + }, + ], + }, + 'zone:cpu_nsec': { + target: 'zone', + description: + 'Cumulative CPU nanoseconds across all threads in a zone, by scheduling state', + units: 'nanoseconds', + datumType: 'cumulative_u64', + fields: [ + { name: 'zone_name', fieldType: 'string', description: 'Name of the host zone' }, + { + name: 'zone_type', + fieldType: 'string', + description: 'Service type of the zone (e.g. cockroachdb, nexus)', + }, + { name: 'zone_id', fieldType: 'uuid', description: 'UUID of the zone' }, + { + name: 'state', + fieldType: 'string', + description: 'The CPU state (user, sys, waitrq)', + }, + ], + }, +} diff --git a/app/api/__tests__/safety.spec.ts b/app/api/__tests__/safety.spec.ts index eee401a29..1a754193e 100644 --- a/app/api/__tests__/safety.spec.ts +++ b/app/api/__tests__/safety.spec.ts @@ -12,6 +12,7 @@ import path from 'path' import { expect, it } from 'vitest' import viteConfigFn from '../../../vite.config' +import { omicronVersion as timeseriesMetadataVersion } from '../__generated__/timeseries-metadata' it('Generated API client version matches API version specified for deployment', () => { const generatedVersion = fs @@ -26,6 +27,8 @@ it('Generated API client version matches API version specified for deployment', // if this test fails, most likely you have updated the API_VERSION in // console/OMICRON_VERSION without re-running `npm run gen-api` expect(generatedVersion).toEqual(pinnedVersion) + // same deal: re-run `npm run gen-api` + expect(timeseriesMetadataVersion).toEqual(pinnedVersion) }) // omicron releng reads API_VERSION at our pinned commit to check the console diff --git a/app/components/Heatmap.tsx b/app/components/Heatmap.tsx index 6156200e2..ef843c564 100644 --- a/app/components/Heatmap.tsx +++ b/app/components/Heatmap.tsx @@ -91,6 +91,8 @@ type HeatmapProps = { distributions: (HeatmapDistribution | null)[] yAxisTickFormatter?: (val: number) => string unit?: string + /** Drawn rotated alongside the y-axis tick labels, e.g. a unit */ + yAxisLabel?: string } const defaultYAxisTickFormatter = (val: number) => val.toLocaleString() @@ -102,6 +104,7 @@ export function Heatmap({ distributions, yAxisTickFormatter = defaultYAxisTickFormatter, unit, + yAxisLabel, }: HeatmapProps) { const theme = useChartTheme() const [hover, setHover] = useState(null) @@ -253,6 +256,7 @@ export function Heatmap({ xTimeAxis({ theme, formatTime }), yValueAxis({ theme, + label: yAxisLabel, grid: { show: false }, values: (_u, splits) => splits.map((v) => { @@ -277,6 +281,7 @@ export function Heatmap({ drawCells, tooltipPlugin, formatterRef, + yAxisLabel, ]) const data = useMemo( diff --git a/app/components/OxqlEditor.tsx b/app/components/OxqlEditor.tsx new file mode 100644 index 000000000..e0c59014d --- /dev/null +++ b/app/components/OxqlEditor.tsx @@ -0,0 +1,250 @@ +import { acceptCompletion } from '@codemirror/autocomplete' +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands' +import { bracketMatching } from '@codemirror/language' +import { + Compartment, + RangeSetBuilder, + StateEffect, + StateField, + type Text, +} from '@codemirror/state' +import { + Decoration, + drawSelection, + EditorView, + highlightActiveLine, + keymap, + placeholder, + ViewPlugin, + type DecorationSet, + type ViewUpdate, +} from '@codemirror/view' +import cn from 'classnames' +import { useEffect, useRef } from 'react' +import { createHighlighterCoreSync } from 'shiki/core' +import { createJavaScriptRegexEngine } from 'shiki/engine/javascript' + +import type { TimeseriesSchema } from '@oxide/api' +import { oxideTheme, oxqlGrammar } from '@oxide/design-system/syntax' + +import { oxqlAutocomplete } from '~/components/oxql-autocomplete' +import type { OxqlDiagnostic } from '~/components/oxql-error' + +// the --syntax-* vars in the theme come from the design system stylesheets +// already imported in app/ui/styles/index.css, so colors follow the theme +const highlighter = createHighlighterCoreSync({ + langs: [oxqlGrammar], + themes: [oxideTheme], + engine: createJavaScriptRegexEngine(), +}) + +/** + * Tokenize the whole doc with shiki and turn the tokens into CodeMirror mark + * decorations. Queries are small, so retokenizing everything on each change + * is cheap. + */ +const buildDecorations = (view: EditorView): DecorationSet => { + const builder = new RangeSetBuilder() + const code = view.state.doc.toString() + let pos = 0 + for (const line of highlighter.codeToTokensBase(code, { + lang: 'oxql', + theme: oxideTheme.name, + })) { + for (const token of line) { + const end = pos + token.content.length + // default-colored tokens don't need a decoration + if (token.color && token.color !== 'var(--syntax-fg)') { + builder.add( + pos, + end, + Decoration.mark({ attributes: { style: `color: ${token.color}` } }) + ) + } + pos = end + } + pos += 1 // newline + } + return builder.finish() +} + +const shikiPlugin = ViewPlugin.fromClass( + class { + decorations: DecorationSet + constructor(view: EditorView) { + this.decorations = buildDecorations(view) + } + update(update: ViewUpdate) { + if (update.docChanged) this.decorations = buildDecorations(update.view) + } + }, + { decorations: (v) => v.decorations } +) + +// Convert a 1-based line:column server error position into an editor range +// covering the offending token. Positions are clamped so a stale or +// out-of-range position can't crash the editor. +const toErrorRange = (doc: Text, { line, column }: OxqlDiagnostic) => { + const lineInfo = doc.line(Math.max(1, Math.min(line, doc.lines))) + let from = Math.min(lineInfo.from + column - 1, lineInfo.to) + // underline through the end of the token under the caret, or one char minimum + const token = /^[@\w:]+/.exec(doc.sliceString(from, lineInfo.to)) + const to = Math.min(from + (token?.[0].length || 1), lineInfo.to) + // at end of line there's nothing after the caret, so underline the char before + if (from === to) from = Math.max(lineInfo.from, to - 1) + // mark decorations may not be empty, so an empty line gets no underline + return from < to ? { from, to } : null +} + +const errorMark = Decoration.mark({ class: 'oxql-error-underline' }) + +const setErrorRange = StateEffect.define<{ from: number; to: number } | null>() + +// Underline the position a server-side parse error points at. The error +// message itself is shown below the editor, so no lint tooltip is needed. +// A StateField (rather than a plain decoration facet) so the range remaps +// when the user edits elsewhere in the doc. +const errorRangeField = StateField.define({ + create: () => Decoration.none, + update(deco, tr) { + let mapped = deco.map(tr.changes) + for (const effect of tr.effects) { + if (effect.is(setErrorRange)) { + mapped = effect.value + ? Decoration.set([errorMark.range(effect.value.from, effect.value.to)]) + : Decoration.none + } + } + return mapped + }, + provide: (f) => EditorView.decorations.from(f), +}) + +const contentAttrs = (ariaLabel: string, error: boolean) => + EditorView.contentAttributes.of({ + 'aria-label': ariaLabel, + 'aria-invalid': error ? 'true' : 'false', + }) + +type OxqlEditorProps = { + value: string + onChange: (value: string) => void + /** Called on cmd+enter / ctrl+enter */ + onSubmit: () => void + error?: boolean + /** Server-reported parse error position, underlined in the editor */ + diagnostic?: OxqlDiagnostic + /** Timeseries schemas backing name and field completions. May load after mount. */ + schemas?: TimeseriesSchema[] + 'aria-label': string +} + +/** A CodeMirror editor for OxQL queries with shiki syntax highlighting */ +export function OxqlEditor({ + value, + onChange, + onSubmit, + error = false, + diagnostic, + schemas, + 'aria-label': ariaLabel, +}: OxqlEditorProps) { + const containerRef = useRef(null) + const viewRef = useRef(null) + const attrsCompartment = useRef(new Compartment()) + + // let the mount-once extensions see the latest props without reconfiguring + const callbacks = useRef({ onChange, onSubmit }) + const schemasRef = useRef(schemas) + useEffect(() => { + callbacks.current = { onChange, onSubmit } + schemasRef.current = schemas + }) + + useEffect(() => { + const view = new EditorView({ + // container div is always mounted when this effect runs + parent: containerRef.current!, + doc: value, + extensions: [ + history(), + keymap.of([ + { + key: 'Mod-Enter', + run: () => { + callbacks.current.onSubmit() + return true + }, + }, + ...defaultKeymap, + ...historyKeymap, + // tab accepts/indents instead of moving focus. the standard escape + // hatch still works: Ctrl-m (from defaultKeymap) toggles tab focus + // mode + { key: 'Tab', run: acceptCompletion }, + indentWithTab, + ]), + EditorView.lineWrapping, + placeholder('get sled_data_link:bytes_sent | filter timestamp > @now() - 5m'), + // draw the cursor and selection ourselves. Firefox puts the native + // caret in the wrong spot when the doc is empty and the line contains + // only the placeholder widget + drawSelection(), + highlightActiveLine(), + bracketMatching(), + oxqlAutocomplete(() => schemasRef.current ?? []), + shikiPlugin, + errorRangeField, + attrsCompartment.current.of(contentAttrs(ariaLabel, error)), + EditorView.updateListener.of((update) => { + if (update.docChanged) callbacks.current.onChange(update.state.doc.toString()) + }), + ], + }) + viewRef.current = view + return () => view.destroy() + // value and the aria attrs are synced by the effects below + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + // sync external value changes (e.g., clicking an example) into the editor + useEffect(() => { + const view = viewRef.current + if (view && value !== view.state.doc.toString()) { + view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: value } }) + } + }, [value]) + + useEffect(() => { + viewRef.current?.dispatch({ + effects: attrsCompartment.current.reconfigure(contentAttrs(ariaLabel, error)), + }) + }, [ariaLabel, error]) + + useEffect(() => { + const view = viewRef.current + if (!view) return + const range = diagnostic ? toErrorRange(view.state.doc, diagnostic) : null + view.dispatch({ effects: setErrorRange.of(range) }) + }, [diagnostic]) + + return ( +
+ ) +} diff --git a/app/components/TimeSeriesChart.tsx b/app/components/TimeSeriesChart.tsx index 55ce19fb2..7e6a200b2 100644 --- a/app/components/TimeSeriesChart.tsx +++ b/app/components/TimeSeriesChart.tsx @@ -37,6 +37,8 @@ type TimeSeriesChartProps = { startTime: Date endTime: Date unit?: string + /** Drawn rotated alongside the y-axis tick labels, e.g. a unit */ + yAxisLabel?: string yAxisTickFormatter?: (val: number) => string hasError?: boolean loading: boolean @@ -68,7 +70,7 @@ export const SkeletonMetric = ({ className )} > -
+
{[...Array(4)].map((_e, i) => (
))} @@ -79,7 +81,7 @@ export const SkeletonMetric = ({ ))}
-
+
{children}
@@ -110,6 +112,7 @@ export function TimeSeriesChart({ startTime, endTime, unit, + yAxisLabel, yAxisTickFormatter = defaultYAxisTickFormatter, hasError = false, loading, @@ -213,6 +216,7 @@ export function TimeSeriesChart({ xTimeAxis({ theme, formatTime }), yValueAxis({ theme, + label: yAxisLabel, grid: { show: true, stroke: theme.axisLine, width: 1 }, values: (_u, yValues) => yValues.map((v) => (v === 0 ? '' : formatterRef.current(v))), @@ -236,7 +240,7 @@ export function TimeSeriesChart({ legend: { show: false }, plugins: [tooltipPlugin], }) satisfies UPlotOptions, - [dataLength, formatTime, tooltipPlugin, interpolation, theme, formatterRef] + [dataLength, formatTime, tooltipPlugin, interpolation, theme, formatterRef, yAxisLabel] ) const aligned = useMemo(() => { @@ -385,7 +389,7 @@ export const ChartContainer = classed.div`flex w-full grow flex-col rounded-lg b type ChartHeaderProps = { title: string label: string - description?: string + description?: ReactNode children?: ReactNode } @@ -394,7 +398,7 @@ export function ChartHeader({ title, label, description, children }: ChartHeader

-
{title}
+
{title}
{label}

{description}
@@ -422,9 +426,9 @@ function ChartLegend({ theme: ChartTheme }) { return ( -
    +
      {Array.from({ length: count }, (_, i) => ( -
    • +
    • void children: ReactNode @@ -39,6 +39,7 @@ export function ReadOnlySideModalForm({ title={title} subtitle={subtitle} animate={animate ?? animateDefault} + focusTitle >
      {children}
      diff --git a/app/components/form/fields/OxqlField.tsx b/app/components/form/fields/OxqlField.tsx deleted file mode 100644 index d663ece6a..000000000 --- a/app/components/form/fields/OxqlField.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * Copyright Oxide Computer Company - */ -import type { FieldPath, FieldValues } from 'react-hook-form' - -import type { TextAreaProps } from '~/ui/lib/TextInput' - -import { TextField, type TextFieldProps } from './TextField' - -export function OxqlField< - TFieldValues extends FieldValues, - TName extends FieldPath, ->( - props: Omit, 'validate'> & Omit -) { - return ( - - typeof value === 'string' && value.trim() ? undefined : 'Enter a query' - } - {...props} - /> - ) -} diff --git a/app/components/oxql-autocomplete.spec.ts b/app/components/oxql-autocomplete.spec.ts new file mode 100644 index 000000000..00774e0d3 --- /dev/null +++ b/app/components/oxql-autocomplete.spec.ts @@ -0,0 +1,249 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { CompletionContext, type CompletionResult } from '@codemirror/autocomplete' +import { EditorState } from '@codemirror/state' +import { expect, it } from 'vitest' + +import type { TimeseriesSchema } from '@oxide/api' + +import { oxqlCompletionSource } from './oxql-autocomplete' + +const schemas: TimeseriesSchema[] = [ + { + authzScope: 'fleet', + created: new Date(0), + datumType: 'f32', + description: { target: 'A hardware component', metric: 'A fan speed measurement' }, + fieldSchema: [ + { + name: 'chassis_kind', + fieldType: 'string', + source: 'target', + description: 'What kind of thing the component is a part of', + }, + { + name: 'sled_id', + fieldType: 'uuid', + source: 'target', + description: 'ID of the sled', + }, + ], + timeseriesName: 'hardware_component:fan_speed', + units: 'rpm', + version: 1, + }, + { + authzScope: 'fleet', + created: new Date(0), + datumType: 'cumulative_u64', + description: { target: 'A sled data link', metric: 'Bytes sent on the link' }, + fieldSchema: [ + { + name: 'sled_id', + fieldType: 'uuid', + source: 'target', + description: 'ID of the sled', + }, + { + name: 'link_name', + fieldType: 'string', + source: 'target', + description: 'Name of the link', + }, + ], + timeseriesName: 'sled_data_link:bytes_sent', + units: 'bytes', + version: 1, + }, + { + authzScope: 'fleet', + created: new Date(0), + datumType: 'f32', + description: { target: 'A hardware component', metric: 'Current draw' }, + fieldSchema: [ + { + name: 'chassis_kind', + fieldType: 'string', + source: 'target', + description: '', + }, + ], + timeseriesName: 'hardware_component:current', + units: 'none', + version: 1, + }, +] + +const complete = (doc: string): CompletionResult | null => + oxqlCompletionSource(() => schemas)( + new CompletionContext(EditorState.create({ doc }), doc.length, false) + ) + +const labels = (doc: string) => complete(doc)?.options.map((o) => o.label) + +/** Run the completion source with the cursor where the first `|` is */ +const completeAt = (docWithCursor: string): CompletionResult | null => { + const pos = docWithCursor.indexOf('|') + const doc = docWithCursor.replace('|', '') + return oxqlCompletionSource(() => schemas)( + new CompletionContext(EditorState.create({ doc }), pos, false) + ) +} + +it('completes table operations at the start of a clause', () => { + expect(labels('g')).toContain('get') + expect(labels('get hardware_component:fan_speed | f')).toContain('filter') + // after a pipe and a space, all ops are offered with an empty prefix + expect(labels('get hardware_component:fan_speed | ')).toContain('group_by') +}) + +it('completes all available targets after get', () => { + expect(labels('get ')).toEqual(['hardware_component', 'sled_data_link']) + expect(labels('get hardware_com')).toEqual(['hardware_component', 'sled_data_link']) +}) + +it('completes metrics of the chosen target after the colon', () => { + expect(labels('get hardware_component:')).toEqual(['fan_speed', 'current']) + expect(labels('get hardware_component:fan')).toEqual(['fan_speed', 'current']) + // from starts after the colon so the metric half filters against its own text + expect(complete('get hardware_component:fan')?.from).toBe( + 'get hardware_component:'.length + ) + expect(complete('get nonsense:')).toBeNull() +}) + +it('offers no name completions with the cursor mid-metric/target', () => { + expect(completeAt('get |hardware_component:fan_speed')).toBeNull() + expect(completeAt('get hardware_com|ponent:fan_speed')).toBeNull() + expect(completeAt('get hardware_component|:fan_speed')).toBeNull() + expect(completeAt('get hardware_component:|fan_speed')).toBeNull() + expect(completeAt('get hardware_component:fan|_speed')).toBeNull() + + expect(completeAt('get hardware_com| |')).not.toBeNull() +}) + +it('completes fields of the queried timeseries in filter', () => { + const result = labels('get hardware_component:fan_speed | filter ch') + expect(result).toContain('chassis_kind') + expect(result).toContain('sled_id') + expect(result).toContain('timestamp') + // @now() is a literal, not an identifier, so it's not offered here + expect(result).not.toContain('@now()') + // fields of timeseries the query doesn't get are not offered + expect(result).not.toContain('link_name') +}) + +it('dedupes fields across multiple gets in a subquery', () => { + const doc = + '{ get hardware_component:fan_speed; get sled_data_link:bytes_sent } | filter ' + const result = labels(doc) + expect(result).toContain('link_name') + expect(result?.filter((l) => l === 'sled_id')).toHaveLength(1) +}) + +it('still completes filter fields after a logical operator', () => { + const doc = "get hardware_component:fan_speed | filter chassis_kind == 'power' || sl" + expect(labels(doc)).toContain('sled_id') +}) + +it('completes fields inside group_by brackets and reducers after them', () => { + expect(labels('get hardware_component:fan_speed | group_by [sl')).toContain('sled_id') + expect(labels('get hardware_component:fan_speed | group_by [sled_id], ')).toEqual([ + 'mean', + 'sum', + ]) +}) + +it('offers only literals at literal positions, not fields', () => { + const literals = ['@now()', 'true', 'false'] + expect(labels('get hardware_component:fan_speed | filter chassis_kind == ')).toEqual( + literals + ) + expect(labels('get hardware_component:fan_speed | filter timestamp > @no')).toEqual( + literals + ) +}) + +it('offers only get at the start of a query branch', () => { + expect(labels('')).toEqual(['get']) + expect(labels('g')).toEqual(['get']) + expect(labels('{ get hardware_component:fan_speed; ')).toEqual(['get']) +}) + +it('does not offer get after a pipe', () => { + const result = labels('get hardware_component:fan_speed | ') + expect(result).not.toContain('get') + expect(result).toContain('filter') +}) + +it('offers nothing at positions expecting an operator', () => { + const filter = 'get hardware_component:fan_speed | filter ' + // after a complete literal of any kind, quoted or not, spaced or not + expect(complete(`${filter}timestamp > @now()`)).toBeNull() + expect(complete(`${filter}chassis_kind == 'power' `)).toBeNull() + expect(complete(`${filter}sled_id == 5 `)).toBeNull() + // duration arithmetic after @now() + expect(complete(`${filter}timestamp > @now() - `)).toBeNull() + // after an identifier, where a comparison operator is expected + expect(complete(`${filter}sled_id `)).toBeNull() + // after a closing paren + expect(complete(`${filter}(sled_id == 5) `)).toBeNull() +}) + +it('offers fields at the start of each boolean operand', () => { + const filter = 'get hardware_component:fan_speed | filter ' + expect(labels(`${filter}chassis_kind == 'power' && `)).toContain('sled_id') + expect(labels(`${filter}chassis_kind == 'power' ^ `)).toContain('sled_id') + expect(labels(`${filter}(`)).toContain('sled_id') + expect(labels(`${filter}!`)).toContain('sled_id') +}) + +it('ignores a get inside a string literal', () => { + const doc = + "get hardware_component:fan_speed | filter chassis_kind == 'get sled_data_link:bytes_sent' && " + const result = labels(doc) + expect(result).toContain('chassis_kind') + expect(result).not.toContain('link_name') +}) + +it('offers nothing after a complete quoted literal', () => { + expect( + complete("get hardware_component:fan_speed | filter chassis_kind == 'power'") + ).toBeNull() +}) + +it('offers nothing inside a string literal', () => { + expect( + complete("get hardware_component:fan_speed | filter chassis_kind == 'pow") + ).toBeNull() +}) + +it('ignores pipes and semicolons inside strings when finding the clause', () => { + const doc = "get hardware_component:fan_speed | filter chassis_kind == 'a | b; c' || sl" + expect(labels(doc)).toContain('sled_id') +}) + +it('scopes fields to the innermost subquery branch', () => { + const doc = + '{ get hardware_component:fan_speed; get sled_data_link:bytes_sent | filter li' + const result = labels(doc) + expect(result).toContain('link_name') + expect(result).not.toContain('chassis_kind') +}) + +it('offers datum alongside fields in filter', () => { + expect(labels('get hardware_component:fan_speed | filter ')).toContain('datum') +}) + +it('completes alignment functions after align', () => { + expect(labels('get hardware_component:fan_speed | align m')).toEqual(['mean_within']) +}) + +it('offers nothing after a complete get clause', () => { + expect(complete('get hardware_component:fan_speed ')).toBeNull() +}) diff --git a/app/components/oxql-autocomplete.ts b/app/components/oxql-autocomplete.ts new file mode 100644 index 000000000..d852a646f --- /dev/null +++ b/app/components/oxql-autocomplete.ts @@ -0,0 +1,270 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { + autocompletion, + closeBrackets, + closeBracketsKeymap, + insertCompletionText, + snippetCompletion, + startCompletion, + type Completion, + type CompletionContext, + type CompletionResult, +} from '@codemirror/autocomplete' +import type { Extension } from '@codemirror/state' +import { keymap, type EditorView } from '@codemirror/view' + +import type { TimeseriesSchema } from '@oxide/api' + +import { pluralize } from '~/util/str' + +// The OxQL language surface below comes from RFD 463 +// https://rfd.shared.oxide.computer/rfd/463 + +// every query/subquery starts with `get`, and `get` cannot appear again after +// a pipe, so it is offered separately from the other table operations +const getOp: Completion = { label: 'get', info: 'Retrieve a table by its timeseries name' } + +const pipeOps: Completion[] = [ + { label: 'filter', info: 'Filter timeseries by field values or timestamps' }, + { label: 'align', info: "Temporally align a table's samples" }, + { + label: 'group_by', + info: 'Group timeseries by the listed fields, reducing along the rest', + }, + { label: 'join', info: 'Natural inner join between two or more tables' }, + { label: 'first', info: 'Limit each timeseries to its first k samples' }, + { label: 'last', info: 'Limit each timeseries to its last k samples' }, +] + +const alignFns: Completion[] = [ + snippetCompletion('mean_within(${period})', { + label: 'mean_within', + info: 'Average samples within each period, e.g. mean_within(30s)', + }), +] + +const reducers: Completion[] = [ + { label: 'mean', info: 'Average the values in each group' }, + { label: 'sum', info: 'Sum the values in each group' }, +] + +const atNow: Completion = { + label: '@now()', + info: 'The current time, e.g. timestamp > @now() - 1m', +} + +// completable literals for the right-hand side of a filter comparison +const literals: Completion[] = [atNow, { label: 'true' }, { label: 'false' }] + +// identifiers that are valid in filter expressions alongside field names +const filterExtras: Completion[] = [ + { label: 'timestamp', info: 'The timestamp of each sample' }, + { label: 'start_time', info: 'The start time of each cumulative sample' }, + { label: 'datum', info: 'The value of each sample' }, +] + +/** + * Walk the document up to `pos`, skipping string literals, to find (1) whether + * the cursor is inside an unterminated string, (2) where the current clause + * starts (last `|`/`{`/`;`/`}` outside strings, with `||` ignored), and + * (3) where the innermost query branch containing the cursor starts: a `{` + * opens a subquery, `;` starts a sibling branch, and `}` returns to the + * enclosing query's scope. + */ +const scanQuery = (doc: string, pos: number) => { + let quote: string | null = null + let escaped = false + let clauseStart = 0 + let scopeStart = 0 + const enclosingScopes: number[] = [] + for (let i = 0; i < pos; i++) { + const c = doc[i] + if (escaped) { + escaped = false + continue + } + if (quote) { + if (c === '\\') escaped = true + else if (c === quote) quote = null + continue + } + switch (c) { + case "'": + case '"': + quote = c + break + case '|': + // logical || is not a clause boundary + if (doc[i + 1] === '|') i++ + else clauseStart = i + 1 + break + case '{': + enclosingScopes.push(scopeStart) + scopeStart = i + 1 + clauseStart = i + 1 + break + case ';': + scopeStart = i + 1 + clauseStart = i + 1 + break + case '}': + scopeStart = enclosingScopes.pop() ?? 0 + clauseStart = i + 1 + break + } + } + return { inString: quote !== null, clauseStart, scopeStart } +} + +const fieldCompletions = ( + context: CompletionContext, + scopeStart: number, + schemas: TimeseriesSchema[] +): Completion[] => { + // offer the fields of every timeseries the innermost query branch `get`s, + // deduped by name since subquery filters can apply across tables. Blank out + // string literals so quoted text can't contribute a phantom `get` + const scope = context.state + .sliceDoc(scopeStart, context.pos) + .replace(/'[^']*'|"[^"]*"/g, '') + const named = new Set(Array.from(scope.matchAll(/\bget\s+([\w:]+)/g), (m) => m[1])) + const seen = new Set() + const options: Completion[] = [] + for (const schema of schemas) { + if (!named.has(schema.timeseriesName)) continue + for (const field of schema.fieldSchema) { + if (seen.has(field.name)) continue + seen.add(field.name) + options.push({ label: field.name, detail: field.fieldType, info: field.description }) + } + } + return options +} + +const targetOf = (timeseriesName: string) => + timeseriesName.slice(0, timeseriesName.indexOf(':')) + +const targetCompletions = (schemas: TimeseriesSchema[]): Completion[] => { + const targets = new Map() + for (const schema of schemas) { + const target = targetOf(schema.timeseriesName) + targets.set(target, (targets.get(target) || 0) + 1) + } + + return Array.from(targets, ([label, count]) => ({ + label: label, + detail: `${count} ${pluralize('metric', count)}`, + apply: (view: EditorView, c: Completion, from: number, to: number) => { + view.dispatch(insertCompletionText(view.state, `${c.label}:`, from, to)) + startCompletion(view) + }, + })) +} + +const metricCompletions = (schemas: TimeseriesSchema[], target: string): Completion[] => { + const prefix = `${target}:` + return schemas + .filter((s) => s.timeseriesName.startsWith(prefix)) + .map((s) => ({ + label: s.timeseriesName.slice(prefix.length), + detail: s.units === 'none' ? s.datumType : `${s.datumType}, ${s.units}`, + info: s.description.metric, + })) +} + +/** + * Complete based on which clause the cursor is in, determined with regexes + * rather than a real parser: OxQL clauses are short and always start with a + * table operation, so "text since the last pipe" is nearly always enough. + * + * Exported for tests; use {@link oxqlAutocomplete} in the editor. + */ +export const oxqlCompletionSource = + (getSchemas: () => TimeseriesSchema[]) => + (context: CompletionContext): CompletionResult | null => { + // the token being completed: word chars plus ':' (timeseries names) and '@' (@now()) + const word = context.matchBefore(/[@\w:]*/) + if (!word) return null + + const doc = context.state.doc.toString() + const { inString, clauseStart, scopeStart } = scanQuery(doc, context.pos) + + // no completions inside a string literal + if (inString) return null + + const clause = doc.slice(clauseStart, context.pos) + + const result = (options: Completion[]): CompletionResult | null => + options.length > 0 ? { from: word.from, options, validFor: /^[@\w:]*$/ } : null + + const getTable = /^\s*get\s+(\w*)(:?)(\w*)$/.exec(clause) + if (getTable) { + // if we're in the middle of a target:metric, don't make a completion + if (/[\w:]/.test(doc[context.pos] ?? '')) return null + + const [, target, colon, metric] = getTable + const inMetric = colon === ':' + const options = inMetric + ? metricCompletions(getSchemas(), target) + : targetCompletions(getSchemas()) + if (options.length === 0) return null + return { + from: context.pos - (inMetric ? metric.length : target.length), + options, + validFor: /^\w*$/, + } + } + + if (/^\s*align\s+\w*$/.test(clause)) return result(alignFns) + + // inside group_by's bracket list → fields; after the list and a comma → reducers + if (/^\s*group_by\s*\[[^\]]*$/.test(clause)) { + return result(fieldCompletions(context, scopeStart, getSchemas())) + } + if (/^\s*group_by\s*\[[^\]]*\]\s*,\s*\w*$/.test(clause)) return result(reducers) + + if (/^\s*filter\b/.test(clause)) { + // comparisons are strictly `ident op literal`, so each cursor position + // allows exactly one kind of completion. Right after a comparison + // operator, only literals are legal + if (/(?:==|!=|>=|<=|<|>|~=)\s*[@\w:]*$/.test(clause)) return result(literals) + // identifiers are legal only at the start of a boolean operand: after + // `filter` itself, a logical operator, an open paren, or negation + if (/(?:\bfilter|&&|\|\||\^|\(|!)\s*[@\w:]*$/.test(clause)) { + return result([ + ...fieldCompletions(context, scopeStart, getSchemas()), + ...filterExtras, + ]) + } + // any other position (after a complete literal or identifier, closing + // paren, etc.) expects an operator, which we don't complete + return null + } + + // otherwise, at the start of a clause, offer `get` if this is the first + // clause of a query branch and the other table operations after a pipe. + // Known quirk: right after `}` only a pipe is legal, but we offer ops + // anyway — distinguishing that case means tracking boundary kind in the + // scanner, more state than this heuristic approach warrants + if (/^\s*\w*$/.test(clause)) { + return result(clauseStart === scopeStart ? [getOp] : pipeOps) + } + + return null + } + +/** + * OxQL completions plus bracket/quote auto-closing. `getSchemas` is called on + * each completion request, so the schema list can arrive after editor mount. + */ +export const oxqlAutocomplete = (getSchemas: () => TimeseriesSchema[]): Extension => [ + autocompletion({ override: [oxqlCompletionSource(getSchemas)], icons: false }), + closeBrackets(), + keymap.of(closeBracketsKeymap), +] diff --git a/app/components/oxql-error.spec.ts b/app/components/oxql-error.spec.ts new file mode 100644 index 000000000..086f9681b --- /dev/null +++ b/app/components/oxql-error.spec.ts @@ -0,0 +1,156 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { describe, expect, it } from 'vitest' + +import { errorMessageToSegments, parseOxqlQueryError, stripCaretLine } from './oxql-error' + +// realistic examples of omicron's fmt_parse_error output +const parseError = `Error at 1:1: .. junk junk junk! .. + ^ +Expected: error at 1:1: expected one of "get", "{" +` + +const multilineError = `Error at 2:5: .. :bytes_sent + | oops .. + ^ +Expected: error at 2:5: expected one of "align", "filter" +` + +describe('parseOxqlQueryError', () => { + it('extracts position and the expected clause', () => { + expect(parseOxqlQueryError(parseError)).toEqual({ + line: 1, + column: 1, + message: 'expected one of "get", "{"', + }) + }) + + it('handles positions past line 1', () => { + expect(parseOxqlQueryError(multilineError)).toEqual({ + line: 2, + column: 5, + message: 'expected one of "align", "filter"', + }) + }) + + it('falls back to the whole message when the Expected line is missing', () => { + const result = parseOxqlQueryError('Error at 3:7: something odd') + expect(result).toEqual({ + line: 3, + column: 7, + message: 'Error at 3:7: something odd', + }) + }) + + it('returns null for non-parse errors', () => { + expect(parseOxqlQueryError('Input tables to a `group_by` must be aligned')).toBeNull() + expect(parseOxqlQueryError('Internal Server Error')).toBeNull() + }) +}) + +describe('stripCaretLine', () => { + it('removes the caret line, leaving header and Expected intact', () => { + expect(stripCaretLine(parseError)).toEqual( + `Error at 1:1: .. junk junk junk! .. +Expected: error at 1:1: expected one of "get", "{" +` + ) + }) + + it('handles trailing spaces after the caret', () => { + expect(stripCaretLine('Error at 1:5: .. x ..\n ^ \nExpected: y\n')).toEqual( + 'Error at 1:5: .. x ..\nExpected: y\n' + ) + }) + + it('leaves messages without a caret line alone', () => { + const semantic = 'Input tables to a `group_by` must be aligned' + expect(stripCaretLine(semantic)).toEqual(semantic) + // a ^ used inside the query context is not a caret line + const withCaretChar = 'Error at 1:9: .. filter a ^ b ..\nExpected: y\n' + expect(stripCaretLine(withCaretChar)).toEqual(withCaretChar) + }) + + it('removes a caret line at the end of the message', () => { + expect(stripCaretLine('Error at 1:5: .. x ..\n ^')).toEqual('Error at 1:5: .. x ..') + }) +}) + +describe('errorMessageToSegments', () => { + const t = (text: string) => ({ type: 'text', text }) + const c = (raw: string, code: string, isTruncated = false) => ({ + type: 'code', + isTruncated, + code, + raw, + }) + + it('splits out excerpt markers, quoted tokens, and backticked names', () => { + expect( + errorMessageToSegments('Error at 1:1: .. junk junk! ..\nExpected: one of "get", "{"') + ).toEqual([ + t('Error at 1:1: '), + c('.. junk junk! ..', 'junk junk!', true), + t('\nExpected: one of '), + c('"get"', 'get'), + t(', '), + c('"{"', '{'), + t(''), + ]) + expect(errorMessageToSegments('Input tables to a `group_by` must be aligned')).toEqual([ + t('Input tables to a '), + c('`group_by`', 'group_by'), + t(' must be aligned'), + ]) + }) + + it('keeps a filter expression with nested quotes in one segment', () => { + // omicron interpolates the raw expression, so quotes inside it are unescaped + expect( + errorMessageToSegments( + 'The filter expression "kind == "power"" is not valid, because' + ) + ).toEqual([ + t('The filter expression '), + c('"kind == "power""', 'kind == "power"'), + t(' is not valid, because'), + ]) + // nested quotes mid-expression, where the inner closing quote is followed + // by a delimiter and could be mistaken for the end of the segment + expect( + errorMessageToSegments( + 'The filter expression "kind == "power" && sled == 1" is not valid, because' + ) + ).toEqual([ + t('The filter expression '), + c('"kind == "power" && sled == 1"', 'kind == "power" && sled == 1'), + t(' is not valid, because'), + ]) + }) + + it('splits identifier lists into one segment per name', () => { + expect( + errorMessageToSegments( + 'Invalid identifiers: ["chassis_kind"], valid: ["datum", "peer"]' + ) + ).toEqual([ + t('Invalid identifiers: ['), + c('"chassis_kind"', 'chassis_kind'), + t('], valid: ['), + c('"datum"', 'datum'), + t(', '), + c('"peer"', 'peer'), + t(']'), + ]) + }) + + it('leaves unbalanced quotes alone', () => { + const message = 'something with a stray " quote' + expect(errorMessageToSegments(message)).toEqual([t(message)]) + }) +}) diff --git a/app/components/oxql-error.ts b/app/components/oxql-error.ts new file mode 100644 index 000000000..022c05423 --- /dev/null +++ b/app/components/oxql-error.ts @@ -0,0 +1,81 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +export type OxqlDiagnostic = { + /** 1-based line in the query */ + line: number + /** 1-based column in the line */ + column: number + message: string +} + +export type Segment = + | { + type: 'code' + isTruncated: boolean + code: string + raw: string + } + | { type: 'text'; text: string } + +/** + * Drop the caret line (whitespace + `^`) from a parse error: its alignment + * assumes a monospace terminal, and the editor underline already points at + * the position. + */ +export const stripCaretLine = (message: string) => message.replace(/\n *\^ *(?=\n|$)/, '') + +/** + * Split pattern for the code-ish parts of an error message: the query excerpt + * between fmt_parse_error's `..` markers, peg's double-quoted expected tokens, + * and the backtick- or double-quoted names in semantic errors. Used with + * `String.split`, so the capture group puts code segments at odd indices. + * + * Quoted filter expressions can contain unescaped nested quotes (omicron + * interpolates the raw expression, e.g. `The filter expression "kind == + * "power"" is not valid`), so that known frame gets a greedy context-anchored + * alternative, and elsewhere a quote only closes a segment when followed by a + * delimiter rather than a word char or another quote. + * https://github.com/oxidecomputer/omicron/blob/6db4c7e/oximeter/db/src/oxql/plan/filter.rs + */ +const codeSegment = + /(\.\. [\s\S]*? \.\.|(?<=The filter expression )"[^\n]*"(?= is not valid)|(? { + if (i % 2 === 0) return { type: 'text', text: part } + + // code snippets are always wrapped in quotes, backticks, or `.. ..` + const isTruncated = part.startsWith('.. ') + const wrapperLength = isTruncated ? 3 : 1 + return { + type: 'code', + isTruncated, + code: part.slice(wrapperLength, -wrapperLength), + raw: part, + } + }) +} + +/** + * Pull the position and expectation out of an OxQL parse error so it can be + * shown as a diagnostic in the editor. The message format comes from + * omicron's `fmt_parse_error`: an `Error at :` header and an + * `Expected:` line whose peg Display redundantly repeats the position. + * Returns null for errors that aren't parse errors (e.g., semantic ones). + * https://github.com/oxidecomputer/omicron/blob/6db4c7e/oximeter/db/src/oxql/mod.rs + */ +export function parseOxqlQueryError(message: string): OxqlDiagnostic | null { + const position = /^Error at (\d+):(\d+)/.exec(message) + if (!position) return null + const expected = /^Expected: (?:error at \d+:\d+: )?(.+)$/m.exec(message)?.[1] + return { + line: parseInt(position[1], 10), + column: parseInt(position[2], 10), + message: expected ? expected.trim() : message, + } +} diff --git a/app/components/oxql-metrics/TimeseriesDocsSideModal.tsx b/app/components/oxql-metrics/TimeseriesDocsSideModal.tsx new file mode 100644 index 000000000..66ec776de --- /dev/null +++ b/app/components/oxql-metrics/TimeseriesDocsSideModal.tsx @@ -0,0 +1,221 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { useQuery } from '@tanstack/react-query' +import type { ReactNode } from 'react' +import * as R from 'remeda' + +import { + api, + q, + type DatumType, + type FieldSchema, + type TimeseriesSchema, + type Units, +} from '@oxide/api' +import { Monitoring16Icon } from '@oxide/design-system/icons/react' +import { Badge } from '@oxide/design-system/ui' + +import { targets, timeseries } from '~/api/__generated__/timeseries-metadata' +import { ReadOnlySideModalForm } from '~/components/form/ReadOnlySideModalForm' +import { FormDivider } from '~/ui/lib/Divider' +import { SideModalFormDocs } from '~/ui/lib/ModalLinks' +import { PropertiesTable } from '~/ui/lib/PropertiesTable' +import { ResourceLabel } from '~/ui/lib/SideModal' +import { ALL_ISH } from '~/util/consts' +import { docLinks } from '~/util/links' + +export const timeseriesSchemasQuery = q(api.systemTimeseriesSchemaList, { + query: { limit: ALL_ISH }, +}) + +type Field = Omit + +type TimeseriesDocs = { + description?: { target: string; metric: string } + unit?: Units + datumType?: DatumType + fields: Field[] + docsHref?: string +} + +// The schema endpoint returns empty descriptions and `none` units for +// everything because ClickHouse doesn't store them, so prefer the snapshot of +// omicron's schema files. The endpoint still covers timeseries defined +// outside omicron. +function getDocs(name: string, schemas: TimeseriesSchema[] | undefined): TimeseriesDocs { + const metric = timeseries[name] + const target = metric && targets[metric.target] + if (metric && target) { + return { + description: { target: target.description, metric: metric.description }, + unit: metric.units, + datumType: metric.datumType, + fields: [...target.fields, ...metric.fields], + // anchors on the schemas page are the timeseries name minus the colon + docsHref: `${docLinks.oxqlSchemas.href}#_${name.replace(':', '')}`, + } + } + const schema = schemas?.find((s) => s.timeseriesName === name) + if (schema) { + return { datumType: schema.datumType, fields: schema.fieldSchema } + } + return { fields: [] } +} + +const DocsList = ({ children }: { children: ReactNode }) => ( +
        + {children} +
      +) + +function DocsItem({ + name, + type, + description, +}: { + name: string + type?: string + description?: string +}) { + return ( +
    • +
      + {name} + {type && {type}} +
      + {description &&

      {description}

      } +
    • + ) +} + +/** Odd indices are the captured `code` and *emphasis* spans */ +const inlineMarkup = /(`[^`]+`|\*[^*]+\*)/ + +function Inline({ text }: { text: string }) { + return text.split(inlineMarkup).map((part, i) => + i % 2 === 0 ? ( + part + ) : part.startsWith('`') ? ( + + {part.slice(1, -1)} + + ) : ( + {part.slice(1, -1)} + ) + ) +} + +const listItem = /^\d+\. / + +/** + * Some descriptions in omicron's schema files use a little Markdown: + * paragraphs, a numbered list, `code`, and *emphasis*. Handle just those. + */ +function Description({ text }: { text: string }) { + return ( +
      + {text + .trim() + .split(/\n{2,}/) + .map((para) => { + const lines = para.split('\n') + return lines.every((line) => listItem.test(line)) ? ( +
        + {lines.map((line) => ( +
      1. + +
      2. + ))} +
      + ) : ( +

      + +

      + ) + })} +
      + ) +} + +export function TimeseriesDocsSideModal({ + name, + onDismiss, +}: { + name: string + onDismiss: () => void +}) { + // the page fetches the same query, so this is normally a cache hit + const schemas = useQuery(timeseriesSchemasQuery).data?.items + const docs = getDocs(name, schemas) + const [target, metric] = name.split(':') + return ( + lets long names wrap at the colon instead of mid-word. the + // span keeps it inline: as a direct flex child it would be blockified, + // which puts a space in the accessible name + subtitle={ + + + + {target}: + {metric} + + + } + onDismiss={onDismiss} + animate + > + + + {docs.datumType ?? '—'} + + {docs.unit ?? '—'} + + {docs.description?.metric && ( + <> + +
      +

      Description

      + +
      + + )} + +
      +

      Target

      + + + +
      + {docs.fields.length > 0 && ( + <> + +
      +

      Fields

      + + {R.sortBy(docs.fields, (f) => f.name).map((f) => ( + + ))} + +
      + + )} + {docs.docsHref && ( + + )} +
      + ) +} diff --git a/app/layouts/SystemLayout.tsx b/app/layouts/SystemLayout.tsx index 31f54d437..a6b079377 100644 --- a/app/layouts/SystemLayout.tsx +++ b/app/layouts/SystemLayout.tsx @@ -62,7 +62,7 @@ export default function SystemLayout() { { value: 'Alerts', path: pb.alerts() }, { value: 'System Update', path: pb.systemUpdate() }, { value: 'Fleet Access', path: pb.fleetAccess() }, - { value: 'OxQL Explorer', path: pb.systemOxql() }, + { value: 'Metrics Explorer', path: pb.systemOxql() }, { value: 'Audit Log', path: pb.auditLog() }, ] // filter out the entry for the path we're currently on @@ -118,7 +118,7 @@ export default function SystemLayout() { Fleet Access - OxQL Explorer + Metrics Explorer Audit Log diff --git a/app/pages/project/access/ProjectAccessPage.tsx b/app/pages/project/access/ProjectAccessPage.tsx index 644cc6638..4263fb7f5 100644 --- a/app/pages/project/access/ProjectAccessPage.tsx +++ b/app/pages/project/access/ProjectAccessPage.tsx @@ -104,7 +104,7 @@ export default function ProjectAccessPage() { const { data: projectPolicy } = usePrefetchedQuery(projectPolicyView(projectSelector)) const projectRows = useUserRows(projectPolicy.roleAssignments, 'project') - const rows = useMemo(() => { + const rows = useMemo((): UserRow[] => { return groupBy(siloRows.concat(projectRows), (u) => u.id) .map(([userId, userAssignments]) => { const { name, identityType } = userAssignments[0] diff --git a/app/pages/system/MetricsExplorer.tsx b/app/pages/system/MetricsExplorer.tsx new file mode 100644 index 000000000..8847166f3 --- /dev/null +++ b/app/pages/system/MetricsExplorer.tsx @@ -0,0 +1,1055 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import { useQuery } from '@tanstack/react-query' +import { useWindowVirtualizer } from '@tanstack/react-virtual' +import { Fragment, useLayoutEffect, useMemo, useRef, useState, type ReactNode } from 'react' +import { useController, useForm } from 'react-hook-form' +import { useSearchParams } from 'react-router' +import * as R from 'remeda' +import { match } from 'ts-pattern' + +import { + api, + useApiMutation, + camelToSnake, + snakeify, + type Distributiondouble, + type MetricType, + type OxqlQueryResult, + type OxqlTable, + type Points, + type Timeseries, + type TimeseriesQuery, + type ValueArray, + type FieldValue, + type TimeseriesSchema, + type Units, +} from '@oxide/api' +import { + Info12Icon, + Monitoring16Icon, + Monitoring24Icon, +} from '@oxide/design-system/icons/react' + +import { timeseries as timeseriesMetadata } from '~/api/__generated__/timeseries-metadata' +import { DocsPopover } from '~/components/DocsPopover' +import { Heatmap } from '~/components/Heatmap' +import { MoreActionsMenu } from '~/components/MoreActionsMenu' +import { + errorMessageToSegments, + parseOxqlQueryError, + stripCaretLine, +} from '~/components/oxql-error' +import { + TimeseriesDocsSideModal, + timeseriesSchemasQuery, +} from '~/components/oxql-metrics/TimeseriesDocsSideModal' +import { OxqlEditor } from '~/components/OxqlEditor' +import { + ChartContainer, + SkeletonMetric, + TimeSeriesChart, +} from '~/components/TimeSeriesChart' +import { useElementSize } from '~/hooks/use-element-size' +import { addToast } from '~/stores/toast' +import { Button } from '~/ui/lib/Button' +import { CardBlock } from '~/ui/lib/CardBlock' +import { Checkbox } from '~/ui/lib/Checkbox' +import { CopyToClipboard } from '~/ui/lib/CopyToClipboard' +import { Divider } from '~/ui/lib/Divider' +import * as Dropdown from '~/ui/lib/DropdownMenu' +import { EmptyMessage } from '~/ui/lib/EmptyMessage' +import { ErrorInlineCode } from '~/ui/lib/InlineCode' +import { Message } from '~/ui/lib/Message' +import { PageHeader, PageTitle } from '~/ui/lib/PageHeader' +import { TextInputError } from '~/ui/lib/TextInput' +import { TipIcon } from '~/ui/lib/TipIcon' +import { Tooltip } from '~/ui/lib/Tooltip' +import { truncate } from '~/ui/lib/Truncate' +import { docLinks } from '~/util/links' +import { formatTick } from '~/util/math' +import { pluralize } from '~/util/str' + +const exampleItems: { label: string; value: string }[] = [ + { + label: 'Power shelf fan speeds', + value: `get hardware_component:fan_speed + | filter chassis_kind == 'power' + | filter timestamp > @now() - 1m`, + }, + { + label: 'AMD CPU TCTL measurements per slot', + value: `get hardware_component:amd_cpu_tctl + | align mean_within(20s) + | group_by [slot] + | filter timestamp > @now() - 10m`, + }, + { + label: 'Bytes sent & received per sled', + value: `{ + get sled_data_link:bytes_sent + | align mean_within(30s) + | group_by [kind, sled_id]; + get sled_data_link:bytes_received + | align mean_within(30s) + | group_by [kind, sled_id] +} + | filter kind == 'physical' + | filter timestamp > @now() - 10m + | join`, + }, + { + label: 'Virtual disk write latencies', + value: `get virtual_disk:io_latency + | filter timestamp > @now() - 10m + | filter io_kind == 'write'`, + }, +] + +const defaultValues: TimeseriesQuery = { + query: '', +} + +export const handle = { crumb: 'Metrics Explorer' } + +const narrowToNumbers = (vs: ValueArray): (number | null)[] => + match(vs) + .with({ type: 'integer' }, ({ values }) => values) + .with({ type: 'double' }, ({ values }) => values) + .with({ type: 'boolean' }, ({ values }) => + values.map((b) => + match(b) + .with(true, () => 1) + .with(false, () => 0) + .with(null, () => null) + .exhaustive() + ) + ) + .with({ type: 'string' }, () => []) // these don't exist in practice + // by only calling this on non-distribution tables (distributions can't be + // aligned/joined), we know this is unreachable + .with({ type: 'integer_distribution' }, () => []) + .with({ type: 'double_distribution' }, () => []) // these don't exist in practice, and are also unreachable per above + .exhaustive() + +const narrowToDistributions = (vs: ValueArray): (Distributiondouble | null)[] => + match(vs) + .with( + { type: 'integer_distribution' }, + { type: 'double_distribution' }, + ({ values }) => values + ) + .otherwise(() => []) + +const leftPad = (items: T[], length: number): (T | null)[] => + items.length >= length ? items : [...Array(length - items.length).fill(null), ...items] + +// The generated client types timestamps as Date, but the wire format is actually ISO strings. Oops! +// `new Date` accepts both. +type OxqlTimestamp = Points['timestamps'][number] +const parseTs = (ts: OxqlTimestamp): number => new Date(ts).getTime() +const toPosix = (timestamps: OxqlTimestamp[]): number[] => timestamps.map(parseTs) + +// Distributions always carry start_times in practice, but this isn't a +// guaranteed invariant. But start times are generally "the timestamp +// preceding the current one", so we can derive that ourselves. +const fakeStartTimes = (timestamps: number[]): number[] => { + if (timestamps.length === 0) return [] + const interval = timestamps.length > 1 ? timestamps[1] - timestamps[0] : 0 + return [timestamps[0] - interval, ...timestamps.slice(0, -1)] +} + +type TimeseriesKind = 'joined' | 'aligned' | 'unaligned' + +/** + * When aligning a series, the timestamps are all on the same grid, but values at the beginning may + * be missing (e.g. [10,20,30] in one timestamp array, and [20,30] in another). As long as we can + * prove there's a regular grid all the way through, no big deal. + */ +const getAlignedTimestamps = ( + items: Timeseries[] +): { type: 'some'; timestamps: number[] } | { type: 'none' } => { + // aligned tables never have start times + if (!items[0] || items[0].points.startTimes) return { type: 'none' } + // similarly, aligned tables are always doubles (even if their inputs were integers!) + if (!items[0].points.values.every(({ values }) => values.type === 'double')) + return { type: 'none' } + + const longestSeries = R.firstBy(items, (i) => -i.points.timestamps.length) + if (!longestSeries || longestSeries.points.timestamps.length === 0) + return { type: 'none' } + + // converting to posix numbers knocks us down to millisecond precision, but uplot is going to + // plot by second anyways + const posixes = toPosix(longestSeries.points.timestamps) + + const end = R.last(posixes) + // aligned series may not share the same start time, but they will always have a common final + // timestamp + if ( + !items.every(({ points }) => { + const last = R.last(points.timestamps) + // no timestamps at all is fine; otherwise the final one must match the shared end + return last === undefined || parseTs(last) === end + }) + ) + return { type: 'none' } + + if (posixes.length === 1) return { type: 'some', timestamps: posixes } + + const [start, second] = posixes + + const step = second - start + // we'll assume all timestamp lists are aligned if every timestamp on our longest timestamp list + // is aligned, i.e. some `step` away from the first one we look at + if (!posixes.every((time) => (time - start) % step === 0)) return { type: 'none' } + + return { + type: 'some', + timestamps: posixes, + } +} + +type Chart = { + name: string + description?: ReactNode + timestamps: number[] + data: Data +} + +type Multiline = Chart<{ label: string; values: (number | null)[] }[]> +type LineChartData = Chart<(number | null)[]> & { metricType: MetricType } +type HeatmapChartData = Chart<(Distributiondouble | null)[]> & { + metricType: MetricType + startTimes: number[] +} + +type ChartGroup = + | 'empty-timeseries' + | ({ startTime: Date; endTime: Date } & ( + | { kind: 'unaligned'; charts: LineChartData[] } + | { kind: 'distributions'; charts: HeatmapChartData[] } + | { kind: 'aligned'; charts: Multiline[] } + | { kind: 'joined'; charts: Multiline[] } + )) + +const getFormattedFields = (t: Timeseries): string => + Object.entries(t.fields) + .map(([fieldName, x]) => `${camelToSnake(fieldName)}: ${x.value}`) + .join(' / ') + +const DEFAULT_FIELDS_SHOWN = 10 +// long enough for names/serials +const FIELD_VALUE_MAX_LEN = 24 +// 6 chars on either side of the ellipsis is enough to tell UUIDs apart +const UUID_MAX_LEN = 14 + +const FieldBadge = ({ fieldName, field }: { fieldName: string; field: FieldValue }) => { + const value = String(field.value) + const maxLen = field.type === 'uuid' ? UUID_MAX_LEN : FIELD_VALUE_MAX_LEN + const truncated = value.length > maxLen + const text = truncate(value, maxLen, 'middle') + const badge = ( + + {camelToSnake(fieldName)} + + {text} + + + ) + if (!truncated) return badge + return ( + + {badge} + + ) +} + +const FieldsList = ({ fields }: { fields: Record }) => { + const [showOverflow, setShowOverflow] = useState(false) + const entries = Object.entries(fields) + const toShow = showOverflow ? entries : entries.slice(0, DEFAULT_FIELDS_SHOWN) + + return ( +
      + {toShow.map(([fieldName, x]) => ( + + ))} + {!showOverflow && entries.length > DEFAULT_FIELDS_SHOWN && ( + + )} +
      + ) +} + +// In a joined table, the table name is component metric names, comma-joined. +// e.g. bfd_session:timeout_expired,hardware_component:current +const retrieveMetricNames = (tableName: string): string[] => + tableName.split(',').map((s) => s.trim()) + +type UnitLabels = { + /** Spelled out, for the y-axis */ + axis: string + /** After a value in the tooltip, so symbols where there's a standard one */ + tooltip?: string +} + +const unitLabels: Record, UnitLabels> = { + // "12 count" reads oddly + count: { axis: 'Count' }, + bytes: { axis: 'Bytes', tooltip: 'bytes' }, + seconds: { axis: 'Seconds', tooltip: 's' }, + nanoseconds: { axis: 'Nanoseconds', tooltip: 'ns' }, + volts: { axis: 'Volts', tooltip: 'V' }, + amps: { axis: 'Amps', tooltip: 'A' }, + watts: { axis: 'Watts', tooltip: 'W' }, + joules: { axis: 'Joules', tooltip: 'J' }, + degrees_celsius: { axis: 'Degrees Celsius', tooltip: '°C' }, + rpm: { axis: 'RPM', tooltip: 'RPM' }, +} + +/** + * Units come from the snapshot of omicron's schema files because the schema + * endpoint returns `none` for everything. A joined table only gets labels if + * all its timeseries share a unit. + */ +const tableUnitLabels = (tableName: string): UnitLabels | undefined => { + const units = R.unique( + retrieveMetricNames(tableName).map((name) => timeseriesMetadata[name]?.units) + ) + return units.length === 1 && units[0] && units[0] !== 'none' + ? unitLabels[units[0]] + : undefined +} + +const tableToGroup = (table: OxqlTable): ChartGroup => { + const { name, timeseries } = table + if (timeseries.length === 0) return 'empty-timeseries' + const kind: + | Exclude + | { kind: 'aligned'; timestamps: number[] } = + // we expect all values arrays to be the same length, so if the first isn't longer than 1, we + // expect singletons across the board + timeseries[0]?.points.values.length > 1 + ? ('joined' as const) + : match(getAlignedTimestamps(timeseries)) + .with({ type: 'none' }, () => 'unaligned' as const) + .with({ type: 'some' }, ({ timestamps }) => ({ + kind: 'aligned' as const, + timestamps, + })) + .exhaustive() + + const chart = match(kind) + .with('joined', (kind) => { + const metricNames = retrieveMetricNames(name) + + return { + kind, + // when joined, each timeseries is _also_ aligned, but we assume that users want to focus on + // cross-referencing between metrics, so we join the values within a given timeseries, going + // no further + charts: timeseries.map((series) => ({ + name, + description: , + timestamps: toPosix(series.points.timestamps), + data: series.points.values.map((v, i) => ({ + label: + metricNames[i] || + // should be unreachable + `${getFormattedFields(series)} #${i + 1}`, + values: narrowToNumbers(v.values), + })), + })), + } + }) + .with({ kind: 'aligned' }, ({ kind, timestamps }) => ({ + kind, + charts: [ + { + name, + timestamps, + data: timeseries + .filter((s) => s.points.values.length > 0) + .map((series) => ({ + label: getFormattedFields(series), + values: leftPad( + narrowToNumbers(series.points.values[0].values), + timestamps.length + ), + })), + }, + ], + })) + .with('unaligned', () => { + const seriesList = timeseries.filter((s) => s.points.values.length > 0) + // all schemas in a table are the same, so we can just check the first + // https://github.com/oxidecomputer/omicron/blob/3de7e909b196c07811025bbf41aaa8a35e6fa3cf/oximeter/oxql-types/src/table.rs#L280 + const valueType = seriesList[0]?.points.values[0]?.values.type + // if no series had any values, there's nothing to chart + if (valueType === undefined) return { kind: 'unaligned' as const, charts: [] } + + return match(valueType) + .with('integer_distribution', 'double_distribution', () => ({ + kind: 'distributions' as const, + charts: seriesList.map((series): HeatmapChartData => { + const timestamps = toPosix(series.points.timestamps) + return { + name, + description: , + timestamps, + metricType: series.points.values[0].metricType, + startTimes: + series.points.startTimes?.map(parseTs) ?? fakeStartTimes(timestamps), + data: narrowToDistributions(series.points.values[0].values), + } + }), + })) + .with('integer', 'double', 'boolean', 'string', () => ({ + kind: 'unaligned' as const, + charts: seriesList.map( + (series): LineChartData => ({ + name, + description: , + timestamps: toPosix(series.points.timestamps), + metricType: series.points.values[0].metricType, + data: narrowToNumbers(series.points.values[0].values), + }) + ), + })) + .exhaustive() + }) + .exhaustive() + const timestamps = chart.charts.flatMap(({ timestamps }) => timestamps) + const min = R.firstBy(timestamps, (t) => t) + const max = R.firstBy(timestamps, (t) => -t) + + return { + ...chart, + // i figure any chart collection probably benefits from sharing their X-axis, even if they're + // rendered in sequence + startTime: new Date(min ?? 0), + endTime: new Date(max ?? 0), + } +} + +// Drops (or keeps, without copying) the first sample of a series. +const dropFirst = + (drop: boolean) => + (xs: T[]): T[] => + drop ? xs.slice(1) : xs + +// We trim timestamps and data at the same time to be confident they're in sync. +const trimSeries = ( + trim: boolean, + { timestamps, data }: { timestamps: number[]; data: T[][] } +) => { + const d = dropFirst(trim) + return { timestamps: d(timestamps), data: data.map(d) } +} +const trimHeatmap = ( + trim: boolean, + { + timestamps, + startTimes, + data, + }: { timestamps: number[]; startTimes: number[]; data: T[] } +) => { + const d = dropFirst(trim) + return { timestamps: d(timestamps), startTimes: d(startTimes), data: d(data) } +} + +// The first aligned point of a cumulative counter is diffed against the counter's start_time, +// collapsing all pre-window history into one giant bucket. It's not "erroneous" but it's usually +// not useful, and you'd want to hide it to get a more useful y-axis for the rest of your data. +const queryHasCumulativeData = ( + queryResult: OxqlQueryResult, + schemas: TimeseriesSchema[] +): boolean => { + const metricNames = new Set( + queryResult.tables.flatMap((t) => retrieveMetricNames(t.name)) + ) + return schemas.some( + (schema) => + metricNames.has(schema.timeseriesName) && + match(schema.datumType) + .with( + 'bool', + 'i8', + 'u8', + 'i16', + 'u16', + 'i32', + 'u32', + 'i64', + 'u64', + 'f32', + 'f64', + 'string', + 'bytes', + () => false + ) + .with( + 'cumulative_i64', + 'cumulative_u64', + 'cumulative_f32', + 'cumulative_f64', + // histogram data is cumulative by definition + 'histogram_i8', + 'histogram_u8', + 'histogram_i16', + 'histogram_u16', + 'histogram_i32', + 'histogram_u32', + 'histogram_i64', + 'histogram_u64', + 'histogram_f32', + 'histogram_f64', + () => true + ) + .exhaustive() + ) +} + +// If the schemas haven't loaded, this is a decent heuristic +const groupHasPointWorthDropping = (g: ChartGroup): boolean => + match(g) + .with('empty-timeseries', () => false) + // Aligned/joined tables may be derived from cumulatives, so we assume it's worth offering + .with({ kind: 'joined' }, { kind: 'aligned' }, () => true) + // Gauges are, by definition, not cumulative, so you'll never see a giant first point + .with({ kind: 'unaligned' }, { kind: 'distributions' }, ({ charts }) => + charts.some((c) => c.metricType !== 'gauge') + ) + .exhaustive() + +type ChartDisplay = { key: string } & ( + | { kind: 'empty' } + | { + kind: 'chart' + startTime: Date + endTime: Date + name: string + description?: ReactNode + timestamps: number[] + data: (number | null)[][] + seriesLabels?: string[] + } + | { + kind: 'heatmap' + name: string + description?: ReactNode + timestamps: number[] + startTimes: number[] + data: (Distributiondouble | null)[] + } +) + +// Virtualization relies on a list of near-same-size items, so we flatten out all the groups +const toDisplays = (groups: ChartGroup[], trim: boolean): ChartDisplay[] => + groups.flatMap((g, t): ChartDisplay[] => { + if (g === 'empty-timeseries') return [{ kind: 'empty', key: `t${t}` }] + const { startTime, endTime } = g + return match(g) + .with({ kind: 'distributions' }, ({ charts }) => + charts.map( + (chart, i): ChartDisplay => ({ + kind: 'heatmap', + key: `t${t}.${i}`, + name: chart.name, + description: chart.description, + ...trimHeatmap(trim, { + timestamps: chart.timestamps, + startTimes: chart.startTimes, + data: chart.data, + }), + }) + ) + ) + .with({ kind: 'unaligned' }, ({ charts }) => + charts.map( + (chart, i): ChartDisplay => ({ + kind: 'chart', + key: `t${t}.${i}`, + startTime, + endTime, + name: chart.name, + description: chart.description, + ...trimSeries(trim, { + timestamps: chart.timestamps, + data: [chart.data], + }), + }) + ) + ) + .with({ kind: 'joined' }, { kind: 'aligned' }, ({ charts }) => + charts.map( + (chart, i): ChartDisplay => ({ + kind: 'chart', + key: `t${t}.${i}`, + startTime, + endTime, + name: chart.name, + description: chart.description, + seriesLabels: chart.data.map((l) => l.label), + ...trimSeries(trim, { + timestamps: chart.timestamps, + data: chart.data.map((d) => d.values), + }), + }) + ) + ) + .exhaustive() + }) + +function TimeseriesDocsButton({ name }: { name: string }) { + const [showDocs, setShowDocs] = useState(false) + return ( + <> + + {showDocs && ( + setShowDocs(false)} /> + )} + + ) +} + +/** + * The colon's sidebearings in a proportional font are so narrow that, with + * underscores running each half together, it's the tightest spot in the name. + * Give it a little room on both sides. Margin rather than inserted spaces so + * copying and the heading's accessible name still give the real name. + */ +function TimeseriesName({ name }: { name: string }) { + const i = name.indexOf(':') + if (i === -1) return name + return ( + <> + {name.slice(0, i)} + : + {name.slice(i + 1)} + + ) +} + +/** + * Like `ChartHeader`, but each timeseries in the table name (more than one for + * a joined table) gets its own heading and docs button. The buttons sit + * outside the headings so they don't end up in the headings' accessible names. + */ +function TimeseriesChartHeader({ + tableName, + description, +}: { + tableName: string + description: ReactNode +}) { + const names = retrieveMetricNames(tableName) + return ( +
      +
      + {names.map((name, i) => ( + + {i > 0 && } +
      +

      + +

      + +
      +
      + ))} +
      +
      {description}
      +
      + ) +} + +function ChartCard({ display }: { display: Extract }) { + const units = tableUnitLabels(display.name) + return ( + + + + + ) +} + +function HeatmapCard({ display }: { display: Extract }) { + const units = tableUnitLabels(display.name) + return ( + + + + + ) +} + +function ChartEntry({ display }: { display: ChartDisplay }) { + return ( + <> + {match(display) + .with({ kind: 'empty' }, () => ( + + +
      +
      + +
      + + + )) + .with({ kind: 'chart' }, (r) => ) + .with({ kind: 'heatmap' }, (r) => ) + .exhaustive()} + + ) +} + +const copyText = (text: string, toastMessage: string) => { + window.navigator.clipboard.writeText(text).then(() => addToast(toastMessage)) +} + +function ResultsMenu({ data }: { data?: OxqlQueryResult }) { + // the menu is always visible so the header doesn't jump around, but the + // actions only make sense once a query has succeeded + const noResults = data === undefined ? 'Run a query first' : undefined + return ( + + + data && + copyText(JSON.stringify(snakeify(data), null, 2), 'Results copied as JSON') + } + label="Copy as JSON" + /> + + ) +} + +function ResultsSummary({ tables }: { tables: OxqlTable[] }) { + const timeseries = tables.flatMap((t) => t.timeseries) + const nPoints = R.sumBy(timeseries, (t) => t.points.timestamps.length) + return ( +
      + {timeseries.length} timeseries /{' '} + + {nPoints.toLocaleString()} {pluralize('point', nPoints)} + +
      + ) +} + +// Server-side query errors render below the editor in the same Message box we +// use for API errors elsewhere (e.g., side modal forms). role=alert announces +// the failure to screen readers on arrival; mono + pre-wrap preserve the parse +// errors' caret alignment. +// The code-ish parts of an error message get inline code styling via +// codeSegment (see oxql-error.ts). The `..` excerpt markers stay outside the +// chip, reading as ellipses. +const ErrorMessage = ({ message }: { message: string }) => ( + + {errorMessageToSegments(message).map((segment, i) => + match(segment) + .with({ type: 'text' }, ({ text }) => text) + .with({ type: 'code' }, ({ isTruncated, code, raw }) => { + // an empty chip is just visual noise; show the raw text instead + if (!code) return raw + return ( + + {isTruncated && '.. '} + {code} + {isTruncated && ' ..'} + + ) + }) + .exhaustive() + )} + +) + +const QueryError = ({ message }: { message: string }) => ( +
      + } + /> +
      +) + +// Rendered in every query state so the layout doesn't shift when results arrive +const ResultsSection = ({ children }: { children: ReactNode }) => ( + <> + + {children} + +) + +export default function MetricsExplorer() { + const query = useApiMutation(api.systemTimeseriesQuery) + + // powers editor autocomplete. no loading state needed: completions are a + // progressive enhancement + const schemas = useQuery(timeseriesSchemasQuery) + + const [searchParams, setSearchParams] = useSearchParams() + + const defaultQuery = searchParams.get('query') ?? defaultValues.query + + const form = useForm({ + defaultValues: { query: defaultQuery }, + }) + const { field, fieldState } = useController({ + name: 'query', + control: form.control, + rules: { + validate: (value) => (value.trim() ? undefined : 'Enter a query'), + }, + }) + + const [dropFirstPoint, setDropFirstPoint] = useState(true) + + const onSubmit = (body: TimeseriesQuery) => { + query.mutate( + { body }, + { + onSuccess: () => { + setSearchParams( + (params) => { + params.set('query', body.query) + return params + }, + { replace: true, preventScrollReset: true, state: { skipLoadingBar: true } } + ) + }, + } + ) + } + + // Parse errors carry a line:column position we can point at in the editor. + // Only show the diagnostic while the editor still holds the exact query that + // failed; as soon as the user edits, the position no longer applies. + const oxqlError = query.error ? parseOxqlQueryError(query.error.message) : null + const diagnostic = + oxqlError && field.value === query.variables?.body.query ? oxqlError : undefined + + const chartGroups: ChartGroup[] | null = useMemo( + () => (query.data ? query.data.tables.map(tableToGroup) : null), + [query.data] + ) + + const hasTrimmableCharts = + schemas.data && query.data + ? queryHasCumulativeData(query.data, schemas.data.items) + : (chartGroups?.some(groupHasPointWorthDropping) ?? false) + const trim = dropFirstPoint && hasTrimmableCharts + + const charts = useMemo( + () => (chartGroups ? toDisplays(chartGroups, trim) : []), + [chartGroups, trim] + ) + + // Since the whole window is the scroll container, the virtualizer needs to + // know the offset from the top. By reacting to height changes in everything + // prior to the virtualized area, we can keep the list's offset height in sync. + const [preChartsSize, preChartsRef] = useElementSize() + const chartsRef = useRef(null) + const [scrollMargin, setScrollMargin] = useState(0) + useLayoutEffect(() => { + if (chartsRef.current) { + setScrollMargin(chartsRef.current.getBoundingClientRect().top + window.scrollY) + } + }, [preChartsSize?.height, charts.length]) + + const virtualizer = useWindowVirtualizer({ + count: charts.length, + estimateSize: () => 500, + overscan: 4, + scrollMargin, + getItemKey: (i) => charts[i].key, + }) + + const errorMessage = fieldState.error?.message ? ( + {fieldState.error.message} + ) : query.error ? ( + + ) : null + + return ( + <> +
      + + }>Metrics Explorer + } + summary="The Oximeter Query Language is a domain-specific language for interrogating telemetry data from software and hardware components across the rack." + links={[docLinks.oxql, docLinks.oxqlSchemas]} + /> + +
      + + +
      + {query.status === 'success' && ( + + )} + + +
      +
      + +
      + form.handleSubmit(onSubmit)()} + schemas={schemas.data?.items} + /> + {errorMessage} +
      +
      + Examples + {exampleItems.map(({ label, value }) => ( + + ))} +
      +
      +
      +
      +
      + + {match(query) + // on error the message renders below the editor, so the results + // section just shows the same empty chart as the idle state + .with({ status: 'idle' }, { status: 'error' }, () => ( + + + {null} + + + )) + .with({ status: 'pending' }, () => ( + + + + + + )) + .with({ status: 'success' }, () => ( + + {hasTrimmableCharts && ( +
      + setDropFirstPoint(e.target.checked)} + > + Drop first data point + + + With deltas and cumulative counters, the initial point is a delta from the + earliest observed value. It's therefore typically much larger, and not + worth comparing to the rest of your data. + +
      + )} +
      + {virtualizer.getVirtualItems().map((item) => ( +
      + +
      + ))} +
      +
      + )) + .exhaustive()} + + ) +} diff --git a/app/pages/system/OxqlPage.tsx b/app/pages/system/OxqlPage.tsx deleted file mode 100644 index f82a68de5..000000000 --- a/app/pages/system/OxqlPage.tsx +++ /dev/null @@ -1,719 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * Copyright Oxide Computer Company - */ -import { useWindowVirtualizer } from '@tanstack/react-virtual' -import { useLayoutEffect, useMemo, useRef, useState } from 'react' -import { useForm } from 'react-hook-form' -import { useSearchParams } from 'react-router' -import * as R from 'remeda' -import { match } from 'ts-pattern' - -import { - api, - useApiMutation, - camelToSnake, - type Distributiondouble, - type MetricType, - type OxqlTable, - type Points, - type Timeseries, - type TimeseriesQuery, - type ValueArray, -} from '@oxide/api' -import { Monitoring16Icon, Monitoring24Icon } from '@oxide/design-system/icons/react' - -import { DocsPopover } from '~/components/DocsPopover' -import { OxqlField } from '~/components/form/fields/OxqlField' -import { Heatmap } from '~/components/Heatmap' -import { - ChartContainer, - ChartHeader, - SkeletonMetric, - MetricsEmpty, - TimeSeriesChart, -} from '~/components/TimeSeriesChart' -import { useElementSize } from '~/hooks/use-element-size' -import { Button } from '~/ui/lib/Button' -import { Divider } from '~/ui/lib/Divider' -import * as DropdownMenu from '~/ui/lib/DropdownMenu' -import { Message } from '~/ui/lib/Message' -import { PageHeader, PageTitle } from '~/ui/lib/PageHeader' -import { docLinks } from '~/util/links' - -const exampleItems: { label: string; value: string }[] = [ - { - label: 'Power shelf fan speeds', - value: `get hardware_component:fan_speed - | filter chassis_kind == 'power' - | filter timestamp > @now() - 1m`, - }, - { - label: 'AMD CPU TCTL measurements per slot', - value: `get hardware_component:amd_cpu_tctl - | align mean_within(20s) - | group_by [slot] - | filter timestamp > @now() - 10m`, - }, - { - label: 'Bytes sent & received per sled', - value: `{ - get sled_data_link:bytes_sent - | align mean_within(30s) - | group_by [kind, sled_id]; - get sled_data_link:bytes_received - | align mean_within(30s) - | group_by [kind, sled_id] -} - | filter kind == 'physical' - | filter timestamp > @now() - 10m - | join`, - }, - { - label: 'Virtual disk write latencies', - value: `get virtual_disk:io_latency - | filter timestamp > @now() - 10m - | filter io_kind == 'write'`, - }, -] - -const defaultValues: TimeseriesQuery = { - query: '', -} - -export const handle = { crumb: 'OxQL Explorer' } - -const narrowToNumbers = (vs: ValueArray): (number | null)[] => - match(vs) - .with({ type: 'integer' }, ({ values }) => values) - .with({ type: 'double' }, ({ values }) => values) - .with({ type: 'boolean' }, ({ values }) => - values.map((b) => - match(b) - .with(true, () => 1) - .with(false, () => 0) - .with(null, () => null) - .exhaustive() - ) - ) - .with({ type: 'string' }, () => []) // these don't exist in practice - // by only calling this on non-distribution tables (distributions can't be - // aligned/joined), we know this is unreachable - .with({ type: 'integer_distribution' }, () => []) - .with({ type: 'double_distribution' }, () => []) // these don't exist in practice, and are also unreachable per above - .exhaustive() - -const narrowToDistributions = (vs: ValueArray): (Distributiondouble | null)[] => - match(vs) - .with( - { type: 'integer_distribution' }, - { type: 'double_distribution' }, - ({ values }) => values - ) - .otherwise(() => []) - -const leftPad = (items: T[], length: number): (T | null)[] => - items.length >= length ? items : [...Array(length - items.length).fill(null), ...items] - -// The generated client types timestamps as Date, but the wire format is actually ISO strings. Oops! -// `new Date` accepts both. -type OxqlTimestamp = Points['timestamps'][number] -const parseTs = (ts: OxqlTimestamp): number => new Date(ts).getTime() -const toPosix = (timestamps: OxqlTimestamp[]): number[] => timestamps.map(parseTs) - -// Distributions always carry start_times in practice, but this isn't a -// guaranteed invariant. But start times are generally "the timestamp -// preceding the current one", so we can derive that ourselves. -const fakeStartTimes = (timestamps: number[]): number[] => { - if (timestamps.length === 0) return [] - const interval = timestamps.length > 1 ? timestamps[1] - timestamps[0] : 0 - return [timestamps[0] - interval, ...timestamps.slice(0, -1)] -} - -type TimeseriesKind = 'joined' | 'aligned' | 'unaligned' - -/** - * When aligning a series, the timestamps are all on the same grid, but values at the beginning may - * be missing (e.g. [10,20,30] in one timestamp array, and [20,30] in another). As long as we can - * prove there's a regular grid all the way through, no big deal. - */ -const getAlignedTimestamps = ( - items: Timeseries[] -): { type: 'some'; timestamps: number[] } | { type: 'none' } => { - // aligned tables never have start times - if (!items[0] || items[0].points.startTimes) return { type: 'none' } - // similarly, aligned tables are always doubles (even if their inputs were integers!) - if (!items[0].points.values.every(({ values }) => values.type === 'double')) - return { type: 'none' } - - const longestSeries = R.firstBy(items, (i) => -i.points.timestamps.length) - if (!longestSeries || longestSeries.points.timestamps.length === 0) - return { type: 'none' } - - // converting to posix numbers knocks us down to millisecond precision, but uplot is going to - // plot by second anyways - const posixes = toPosix(longestSeries.points.timestamps) - - const end = R.last(posixes) - // aligned series may not share the same start time, but they will always have a common final - // timestamp - if ( - !items.every(({ points }) => { - const last = R.last(points.timestamps) - // no timestamps at all is fine; otherwise the final one must match the shared end - return last === undefined || parseTs(last) === end - }) - ) - return { type: 'none' } - - if (posixes.length === 1) return { type: 'some', timestamps: posixes } - - const [start, second] = posixes - - const step = second - start - // we'll assume all timestamp lists are aligned if every timestamp on our longest timestamp list - // is aligned, i.e. some `step` away from the first one we look at - if (!posixes.every((time) => (time - start) % step === 0)) return { type: 'none' } - - return { - type: 'some', - timestamps: posixes, - } -} - -type Chart = { - name: string - description?: string - timestamps: number[] - data: Data -} - -type Multiline = Chart<{ label: string; values: (number | null)[] }[]> -type Line = Chart<(number | null)[]> & { metricType: MetricType } -type Heatmap = Chart<(Distributiondouble | null)[]> & { - metricType: MetricType - startTimes: number[] -} - -type ChartGroup = - | 'empty-timeseries' - | ({ startTime: Date; endTime: Date } & ( - | { kind: 'unaligned'; charts: Line[] } - | { kind: 'distributions'; charts: Heatmap[] } - | { kind: 'aligned'; charts: Multiline[] } - | { kind: 'joined'; charts: Multiline[] } - )) - -const getFormattedFields = (t: Timeseries): string => - Object.entries(t.fields) - // hello my evil friend. - .map(([fieldName, x]) => `${camelToSnake(fieldName)}: ${x.value}`) - .join(' \u2022 ') - -const tableToGroup = (table: OxqlTable): ChartGroup => { - const { name, timeseries } = table - if (timeseries.length === 0) return 'empty-timeseries' - const kind: - | Exclude - | { kind: 'aligned'; timestamps: number[] } = - // we expect all values arrays to be the same length, so if the first isn't longer than 1, we - // expect singletons across the board - timeseries[0]?.points.values.length > 1 - ? ('joined' as const) - : match(getAlignedTimestamps(timeseries)) - .with({ type: 'none' }, () => 'unaligned' as const) - .with({ type: 'some' }, ({ timestamps }) => ({ - kind: 'aligned' as const, - timestamps, - })) - .exhaustive() - - const chart = match(kind) - .with('joined', (kind) => { - // In a joined table, each Values item is a distinct metric:target and the - // table name is those metric names comma-joined, index-aligned to the Values. - // So the line labels come from the table name, not the (identical-per-line) - // joined field. - const metricNames = name.split(',').map((s) => s.trim()) - - return { - kind, - // when joined, each timeseries is _also_ aligned, but we assume that users want to focus on - // cross-referencing between metrics, so we join the values within a given timeseries, going - // no further - charts: timeseries.map((series) => ({ - name, - description: getFormattedFields(series), - timestamps: toPosix(series.points.timestamps), - data: series.points.values.map((v, i) => ({ - label: - metricNames[i] || - // should be unreachable - `${getFormattedFields(series)} #${i + 1}`, - values: narrowToNumbers(v.values), - })), - })), - } - }) - .with({ kind: 'aligned' }, ({ kind, timestamps }) => ({ - kind, - charts: [ - { - name, - timestamps, - data: timeseries - .filter((s) => s.points.values.length > 0) - .map((series) => ({ - label: getFormattedFields(series), - values: leftPad( - narrowToNumbers(series.points.values[0].values), - timestamps.length - ), - })), - }, - ], - })) - .with('unaligned', () => { - const seriesList = timeseries.filter((s) => s.points.values.length > 0) - // all schemas in a table are the same, so we can just check the first - // https://github.com/oxidecomputer/omicron/blob/3de7e909b196c07811025bbf41aaa8a35e6fa3cf/oximeter/oxql-types/src/table.rs#L280 - const valueType = seriesList[0]?.points.values[0]?.values.type - // if no series had any values, there's nothing to chart - if (valueType === undefined) return { kind: 'unaligned' as const, charts: [] } - - return match(valueType) - .with('integer_distribution', 'double_distribution', () => ({ - kind: 'distributions' as const, - charts: seriesList.map((series): Heatmap => { - const timestamps = toPosix(series.points.timestamps) - return { - name, - description: getFormattedFields(series), - timestamps, - metricType: series.points.values[0].metricType, - startTimes: - series.points.startTimes?.map(parseTs) ?? fakeStartTimes(timestamps), - data: narrowToDistributions(series.points.values[0].values), - } - }), - })) - .with('integer', 'double', 'boolean', 'string', () => ({ - kind: 'unaligned' as const, - charts: seriesList.map( - (series): Line => ({ - name, - description: getFormattedFields(series), - timestamps: toPosix(series.points.timestamps), - metricType: series.points.values[0].metricType, - data: narrowToNumbers(series.points.values[0].values), - }) - ), - })) - .exhaustive() - }) - .exhaustive() - const timestamps = chart.charts.flatMap(({ timestamps }) => timestamps) - const min = R.firstBy(timestamps, (t) => t) - const max = R.firstBy(timestamps, (t) => -t) - - return { - ...chart, - // i figure any chart collection probably benefits from sharing their X-axis, even if they're - // rendered in sequence - startTime: new Date(min ?? 0), - endTime: new Date(max ?? 0), - } -} - -const TICK_UNITS = [ - // TODO: this doesn't quite match the suffixes in the oxql-metrics util, but i'm leaving it - // because i don't understand those - [1e12, 't'], - [1e9, 'b'], - [1e6, 'm'], - [1e3, 'k'], -] as const -const formatTick = (n: number): string => { - const [divisor, suffix] = TICK_UNITS.find(([min]) => Math.abs(n) >= min) ?? [1, ''] - return (n / divisor).toLocaleString() + suffix -} - -// Drops (or keeps, without copying) the first sample of a series. -const dropFirst = - (drop: boolean) => - (xs: T[]): T[] => - drop ? xs.slice(1) : xs - -// We trim timestamps and data at the same time to be confident they're in sync. -const trimSeries = ( - trim: boolean, - { timestamps, data }: { timestamps: number[]; data: T[][] } -) => { - const d = dropFirst(trim) - return { timestamps: d(timestamps), data: data.map(d) } -} -const trimHeatmap = ( - trim: boolean, - { - timestamps, - startTimes, - data, - }: { timestamps: number[]; startTimes: number[]; data: T[] } -) => { - const d = dropFirst(trim) - return { timestamps: d(timestamps), startTimes: d(startTimes), data: d(data) } -} - -// The first aligned point of a cumulative counter is diffed against the counter's start_time, -// collapsing all pre-window history into one giant bucket. It's not "erroneous" but it's usually -// not useful, and you'd want to hide it to get a more useful y-axis for the rest of your data. -const groupHasPointWorthDropping = (g: ChartGroup): boolean => - match(g) - .with('empty-timeseries', () => false) - // Aligned/joined tables may be derived from cumulatives, so we assume it's worth offering - .with({ kind: 'joined' }, { kind: 'aligned' }, () => true) - // Gauges are, by definition, not cumulative, so you'll never see a giant first point - .with({ kind: 'unaligned' }, { kind: 'distributions' }, ({ charts }) => - charts.some((c) => c.metricType !== 'gauge') - ) - .exhaustive() - -// A flattened representation of a single chart. -type ChartDisplay = { key: string; showDivider: boolean } & ( - | { kind: 'empty' } - | { kind: 'multiline'; startTime: Date; endTime: Date; chart: Multiline } - | { kind: 'line'; startTime: Date; endTime: Date; chart: Line } - | { kind: 'heatmap'; chart: Heatmap } -) - -// Virtualization relies on a list of near-same-size items, so we flatten out all the groups -const toDisplays = (groups: ChartGroup[]): ChartDisplay[] => - groups.flatMap((g, t): ChartDisplay[] => { - if (g === 'empty-timeseries') - return [{ kind: 'empty', key: `t${t}`, showDivider: true }] - const { startTime, endTime } = g - return match(g) - .with({ kind: 'distributions' }, ({ charts }) => - charts.map( - (chart, i): ChartDisplay => ({ - kind: 'heatmap', - key: `t${t}.${i}`, - showDivider: i === 0, - chart, - }) - ) - ) - .with({ kind: 'unaligned' }, ({ charts }) => - charts.map( - (chart, i): ChartDisplay => ({ - kind: 'line', - key: `t${t}.${i}`, - showDivider: i === 0, - startTime, - endTime, - chart, - }) - ) - ) - .with({ kind: 'joined' }, { kind: 'aligned' }, ({ charts }) => - charts.map( - (chart, i): ChartDisplay => ({ - kind: 'multiline', - key: `t${t}.${i}`, - showDivider: i === 0, - startTime, - endTime, - chart, - }) - ) - ) - .exhaustive() - }) - -function MultilineChart({ - display, - trim, -}: { - display: Extract - trim: boolean -}) { - const { chart, startTime, endTime } = display - const trimmed = trimSeries(trim, { - timestamps: chart.timestamps, - data: chart.data.map((d) => d.values), - }) - const seriesLabels = chart.data.map((l) => l.label) - return ( - - - - - ) -} - -function LineChart({ - display, - trim, -}: { - display: Extract - trim: boolean -}) { - const { chart, startTime, endTime } = display - const trimmed = trimSeries(trim, { data: [chart.data], timestamps: chart.timestamps }) - return ( - - - - - ) -} - -function HeatmapChart({ - display, - trim, -}: { - display: Extract - trim: boolean -}) { - const { chart } = display - const trimmed = trimHeatmap(trim, { - timestamps: chart.timestamps, - startTimes: chart.startTimes, - data: chart.data, - }) - return ( - - - - - ) -} - -function ChartEntry({ display, trim }: { display: ChartDisplay; trim: boolean }) { - return ( - <> - {display.showDivider ? ( - // Use padding for spacing so the virtualizer can measure the bounding box properly -
      - -
      - ) : ( -
      - )} - {match(display) - .with({ kind: 'empty' }, () => ( - - - - )) - .with({ kind: 'multiline' }, (r) => ) - .with({ kind: 'line' }, (r) => ) - .with({ kind: 'heatmap' }, (r) => ) - .exhaustive()} - - ) -} - -const getTextareaHeightForQuery = (q: string): number => Math.max(q.split('\n').length, 4) - -export default function OxqlPage() { - const query = useApiMutation(api.systemTimeseriesQuery) - - const [searchParams, setSearchParams] = useSearchParams() - - const defaultQuery = searchParams.get('query') ?? defaultValues.query - - const [textareaRowCount, setTextareaRowCount] = useState( - getTextareaHeightForQuery(defaultQuery) - ) - - const form = useForm({ - defaultValues: { query: defaultQuery }, - }) - const control = form.control - - const [dropFirstPoint, setDropFirstPoint] = useState(true) - - const onSubmit = (body: TimeseriesQuery) => { - query.mutate( - { body }, - { - onSuccess: () => { - setSearchParams( - (params) => { - params.set('query', body.query) - return params - }, - { replace: true, preventScrollReset: true, state: { skipLoadingBar: true } } - ) - }, - } - ) - } - - const chartGroups: ChartGroup[] | null = useMemo( - () => (query.data ? query.data.tables.map(tableToGroup) : null), - [query.data] - ) - - const hasTrimmableCharts = chartGroups?.some(groupHasPointWorthDropping) ?? false - const trim = dropFirstPoint && hasTrimmableCharts - - const charts = useMemo(() => (chartGroups ? toDisplays(chartGroups) : []), [chartGroups]) - - // Since the whole window is the scroll container, the virtualizer needs to - // know the offset from the top. By reacting to height changes in everything - // prior to the virtualized area, we can keep the list's offset height in sync. - const [preChartsSize, preChartsRef] = useElementSize() - const chartsRef = useRef(null) - const [scrollMargin, setScrollMargin] = useState(0) - useLayoutEffect(() => { - if (chartsRef.current) { - setScrollMargin(chartsRef.current.getBoundingClientRect().top + window.scrollY) - } - }, [preChartsSize?.height, charts.length]) - - const virtualizer = useWindowVirtualizer({ - count: charts.length, - estimateSize: () => 500, - overscan: 4, - scrollMargin, - getItemKey: (i) => charts[i].key, - }) - - return ( - <> -
      - - }>OxQL Explorer - } - summary="The Oximeter Query Language is a domain-specific language for interrogating telemetry data from software and hardware components across the rack." - links={[docLinks.oxql, docLinks.oxqlSchemas]} - /> - -
      -
      - - - Try an example - - } - /> - - {exampleItems.map(({ label, value }) => ( - { - setTextareaRowCount(getTextareaHeightForQuery(value)) - form.setValue('query', value) - }} - /> - ))} - - -
      - - - - {match(query) - .with( - { status: 'success' }, - () => - hasTrimmableCharts && ( -
      - -
      - ) - ) - .otherwise(() => '')} -
      - - {match(query) - .with({ status: 'idle' }, () => null) - .with({ status: 'pending' }, () => ( - - - - )) - .with({ status: 'error' }, (q) => ( - {q.error.message}} - /> - )) - .with({ status: 'success' }, () => ( -
      - {virtualizer.getVirtualItems().map((item) => ( -
      - -
      - ))} -
      - )) - .exhaustive()} - - ) -} diff --git a/app/routes.tsx b/app/routes.tsx index 63affa364..d890ade12 100644 --- a/app/routes.tsx +++ b/app/routes.tsx @@ -176,7 +176,10 @@ export const routes = createRoutesFromElements( path="utilization" lazy={() => import('./pages/system/UtilizationPage').then(convert)} /> - import('./pages/system/OxqlPage').then(convert)} /> + import('./pages/system/MetricsExplorer.tsx').then(convert)} + /> import('./pages/system/inventory/InventoryPage.tsx').then(convert)} diff --git a/app/ui/lib/InlineCode.tsx b/app/ui/lib/InlineCode.tsx index 4d6d28649..97394b314 100644 --- a/app/ui/lib/InlineCode.tsx +++ b/app/ui/lib/InlineCode.tsx @@ -9,3 +9,4 @@ import { classed } from '~/util/classed' export const InlineCode = classed.code`whitespace-nowrap rounded-sm px-[3px] py-px text-mono-sm normal-case! bg-raise border border-secondary mx-px` +export const ErrorInlineCode = classed.code`inline-code font-mono whitespace-nowrap` diff --git a/app/ui/lib/SideModal.tsx b/app/ui/lib/SideModal.tsx index 8c193f508..4ad8b97c3 100644 --- a/app/ui/lib/SideModal.tsx +++ b/app/ui/lib/SideModal.tsx @@ -7,7 +7,7 @@ */ import { Dialog as BaseDialog } from '@base-ui/react/dialog' import * as m from 'motion/react-m' -import type { ReactNode } from 'react' +import { useRef, type ReactNode } from 'react' import { Close12Icon, Error12Icon } from '@oxide/design-system/icons/react' @@ -28,12 +28,19 @@ export function usePopoverZIndex() { } export type SideModalProps = { - title: string + title: ReactNode subtitle?: ReactNode onDismiss: () => void isOpen: boolean children?: React.ReactNode errors?: string[] + /** + * Focus the title on open instead of the first tabbable element. For + * read-only content, where jumping to (and scrolling down to) the first link + * or button isn't useful. See the note on long content in + * https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/#keyboardinteraction + */ + focusTitle?: boolean /** * Whether the modal should animate in. It never animates out. Default `true`. * Used to prevent animation from firing when we show the modal directly on a @@ -56,7 +63,9 @@ export function SideModal({ subtitle, animate = true, errors, + focusTitle, }: SideModalProps) { + const titleRef = useRef(null) return (
      - + {title} {subtitle} @@ -121,7 +137,7 @@ export function SideModal({ ) } -export const ResourceLabel = classed.h3`mt-2 flex items-center gap-1.5 text-sans-md text-accent` +export const ResourceLabel = classed.h3`mt-1.5 flex items-center gap-1.5 text-sans-lg text-accent [&>svg]:text-accent-tertiary` SideModal.Body = ({ children }: { children?: ReactNode }) => (
      tags at mount time. The doubled .cm-editor + * keeps every rule here above that. + */ + +.oxql-editor .cm-editor.cm-editor { + background-color: var(--syntax-bg); + color: var(--syntax-fg); + min-height: 7.5rem; + max-height: 15rem; + + &.cm-focused { + outline: none; + } + + .cm-scroller { + flex-grow: 1; + overflow: auto; + font-family: inherit; + } + + .cm-content { + font-family: inherit; + padding: 10px 0; + } + + .cm-line { + padding: 0 12px; + text-transform: none !important; + letter-spacing: 0 !important; + @apply text-mono-sm; + } + + /* drawSelection() hides the native caret and selection and draws its own */ + .cm-cursor, + .cm-dropCursor { + border-left-color: var(--syntax-fg); + } + + /* + * Matches the global ::selection color in index.css. CodeMirror's own + * focused-selection rule is unusually specific, hence the repeated class. + */ + .cm-scroller .cm-selectionLayer .cm-selectionBackground.cm-selectionBackground { + @apply bg-accent-inverse/30; + } + + /* + * drawSelection sets z-index: -2 on the selection layer as an inline style, + * rendering it invisible. But we actually want to see it! + */ + .cm-selectionLayer { + z-index: unset !important; + pointer-events: none; /* without making it interactive, that is */ + } + + .cm-activeLine { + background-color: transparent; + } + + &.cm-focused .cm-activeLine { + background-color: var(--surface-secondary); + } + + .cm-matchingBracket, + .cm-nonmatchingBracket { + background-color: var(--surface-hover); + outline: none; + } + + .cm-matchingBracket { + color: var(--syntax-fg); + } + + .cm-nonmatchingBracket { + color: var(--content-destructive); + } + + .cm-tooltip { + background-color: var(--surface-raise); + border: 1px solid var(--stroke-secondary); + border-radius: 0.125rem; + overflow: hidden; + font-family: inherit; + } + + .cm-tooltip.cm-tooltip-autocomplete > ul { + font-family: inherit; + } + + .cm-tooltip.cm-tooltip-autocomplete > ul > li { + padding: 2px 8px; + } + + .cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected] { + background-color: var(--surface-hover); + color: inherit; + } + + .cm-completionMatchedText { + text-decoration: none; + color: var(--content-accent-secondary); + } + + .cm-completionDetail { + color: var(--content-tertiary); + font-style: normal; + margin-left: 1rem; + } + + .cm-tooltip.cm-completionInfo { + padding: 4px 8px; + max-width: 22rem; + } + + /* wavy underline under the token a server-side parse error points at */ + .oxql-error-underline { + text-decoration: underline wavy var(--content-destructive); + text-decoration-skip-ink: none; + text-underline-offset: 3px; + } + + /* match the placeholder color of the regular text inputs */ + .cm-placeholder { + color: var(--content-tertiary); + } + + /* placeholder region of an accepted snippet, e.g. mean_within(period) */ + .cm-snippetField { + background-color: var(--surface-secondary); + } +} diff --git a/app/ui/styles/index.css b/app/ui/styles/index.css index d20107423..8449fa324 100644 --- a/app/ui/styles/index.css +++ b/app/ui/styles/index.css @@ -53,6 +53,9 @@ /* layer(components) on this one results in visual changes, holding off for now */ @import './components/table.css'; +/* deliberately unlayered: must beat CodeMirror's injected unlayered styles */ +@import './components/oxql-editor.css'; + @import '@xterm/xterm/css/xterm.css' layer(components); @source '../../../node_modules/@oxide/design-system/dist'; @custom-variant light (&:where([data-theme=light], [data-theme=light] *)); @@ -106,6 +109,19 @@ margin-right: var(--content-gutter); } +/* Inline code chip that takes its tint from the surrounding text color, so it + works on any background (e.g., inside an error message) */ +@utility inline-code { + font-size: 0.825em; + letter-spacing: 0; + vertical-align: 1px; + margin: 0 1px; + padding: 0 0.125rem; + background-color: color-mix(in srgb, currentColor 8%, transparent); + border: 1px solid color-mix(in srgb, currentColor 10%, transparent); + border-radius: var(--radius-md); +} + @utility link-with-underline { @apply text-raise; text-decoration: underline; diff --git a/app/util/__snapshots__/path-builder.spec.ts.snap b/app/util/__snapshots__/path-builder.spec.ts.snap index 9f9b151d2..d3e8bcf7c 100644 --- a/app/util/__snapshots__/path-builder.spec.ts.snap +++ b/app/util/__snapshots__/path-builder.spec.ts.snap @@ -957,10 +957,10 @@ exports[`breadcrumbs 2`] = ` "path": "/system/networking/subnet-pools", }, ], - "systemOxql (/system/oxql)": [ + "systemOxql (/system/metrics-explorer)": [ { - "label": "OxQL Explorer", - "path": "/system/oxql", + "label": "Metrics Explorer", + "path": "/system/metrics-explorer", }, ], "systemUpdate (/system/update)": [ diff --git a/app/util/charts.ts b/app/util/charts.ts index 6d5f00c51..f2d73b097 100644 --- a/app/util/charts.ts +++ b/app/util/charts.ts @@ -58,6 +58,7 @@ export const measureTextWidth = (text: string, font: string) => { export const AXIS_FONT_REM_XS = 0.6875 export const AXIS_TICK_LENGTH = 6 export const AXIS_TICK_GAP = 8 +const AXIS_LABEL_GAP = 12 export type ChartTheme = { fontFamily: string @@ -85,7 +86,7 @@ export function getChartTheme(): ChartTheme { hoverPoint: v('--content-accent'), fill: withAlpha(v('--surface-accent-secondary'), 0.6), axisLine: v('--stroke-secondary'), - axisText: v('--content-quaternary'), + axisText: v('--content-tertiary'), lineColors: [ '--color-green-800', '--color-blue-800', @@ -177,13 +178,20 @@ export function yValueAxis({ theme, grid, values, + label, }: { theme: ChartTheme grid: uPlot.Axis.Grid values: uPlot.Axis.Values + /** Drawn rotated alongside the tick labels, e.g. a unit */ + label?: string }): uPlot.Axis { - const { axisFont } = chartAxisFont(theme) + const { fontPx, axisFont } = chartAxisFont(theme) return { + label, + labelFont: axisFont, + labelGap: AXIS_LABEL_GAP, + labelSize: fontPx + AXIS_LABEL_GAP, stroke: theme.axisText, font: axisFont, side: 1, diff --git a/app/util/math.spec.ts b/app/util/math.spec.ts index c7fdfe9b7..c34832a20 100644 --- a/app/util/math.spec.ts +++ b/app/util/math.spec.ts @@ -7,7 +7,14 @@ */ import { describe, expect, it } from 'vitest' -import { diskSizeNearest10, displayBigNum, percentage, round, splitDecimal } from './math' +import { + diskSizeNearest10, + displayBigNum, + formatTick, + percentage, + round, + splitDecimal, +} from './math' import { GiB } from './units' it('round', () => { @@ -122,6 +129,20 @@ describe('with default locale', () => { ])('displayBigNum %d -> %s', (input, output) => { expect(displayBigNum(input)).toEqual(output) }) + + it.each([ + [0, '0'], + [0.125, '0.125'], + [250, '250'], + [1250, '1.25K'], + [1750, '1.75K'], + [12500, '12.5K'], + [1_250_000, '1.25M'], + [2.5e9, '2.5B'], + [-3e6, '-3M'], + ])('formatTick %d -> %s', (input, output) => { + expect(formatTick(input)).toEqual(output) + }) }) describe('with de-DE locale', () => { diff --git a/app/util/math.ts b/app/util/math.ts index d240fa9ad..40a14f456 100644 --- a/app/util/math.ts +++ b/app/util/math.ts @@ -103,6 +103,17 @@ export function displayBigNum( return [result, abbreviated] } +/** + * Short y-axis tick labels like 1.25K. Compact notation rounds to 2 + * significant digits by default, which turns ticks like 1.25K into 1.3K. + */ +export function formatTick(num: number, locale?: string) { + return Intl.NumberFormat(locale, { + notation: 'compact', + maximumSignificantDigits: 3, + }).format(num) +} + /** * Calculate disk size based on image or snapshot size. We round up to the * nearest 10, but also cap it at the max disk size so that, for example, a 1023 diff --git a/app/util/path-builder.spec.ts b/app/util/path-builder.spec.ts index e5fac9cc9..d81be2f65 100644 --- a/app/util/path-builder.spec.ts +++ b/app/util/path-builder.spec.ts @@ -121,7 +121,7 @@ test('path builder', () => { "subnetPoolMemberAdd": "/system/networking/subnet-pools/sp/members-add", "subnetPools": "/system/networking/subnet-pools", "subnetPoolsNew": "/system/networking/subnet-pools-new", - "systemOxql": "/system/oxql", + "systemOxql": "/system/metrics-explorer", "systemUpdate": "/system/update", "systemUtilization": "/system/utilization", "vpc": "/projects/p/vpcs/v/firewall-rules", diff --git a/app/util/path-builder.ts b/app/util/path-builder.ts index ab147dac5..458e003fd 100644 --- a/app/util/path-builder.ts +++ b/app/util/path-builder.ts @@ -116,7 +116,7 @@ export const pb = { siloImage: (params: PP.SiloImage) => `${pb.siloImages()}/${params.image}`, fleetAccess: () => '/system/access', - systemOxql: () => '/system/oxql', + systemOxql: () => '/system/metrics-explorer', systemUtilization: () => '/system/utilization', ipPools: () => '/system/networking/ip-pools', diff --git a/docs/update-pinned-api.md b/docs/update-pinned-api.md index 31295957b..cf410dff4 100644 --- a/docs/update-pinned-api.md +++ b/docs/update-pinned-api.md @@ -3,7 +3,7 @@ ## Instructions 1. Update [`OMICRON_VERSION`](/OMICRON_VERSION) with new Omicron commit hash -1. Update the generated API client by running `npm run gen-api`. This will automatically check out the omicron commit specified in `OMICRON_VERSION`. If you forget this step, a safety test in `app/api` will fail. +1. Update the generated API client by running `npm run gen-api`. This will automatically check out the omicron commit specified in `OMICRON_VERSION`. It also snapshots timeseries descriptions and units from omicron's oximeter schema files, which the API doesn't return. If you forget this step, a safety test in `app/api` will fail. 1. Run `npm run tsc` and fix any type errors introduced by changes to the generated code. New endpoints must be added to the handler map in `mock-api/msw/handlers.ts`; use `NotImplemented` unless the UI needs them. 1. Commit and push to a branch diff --git a/mock-api/index.ts b/mock-api/index.ts index 0e10f59cc..4ac70bcbf 100644 --- a/mock-api/index.ts +++ b/mock-api/index.ts @@ -29,6 +29,7 @@ export * from './sshKeys' export * from './subnet-pool' export * from './switch' export * from './system-update' +export * from './timeseries-schema' export * from './token' export * from './user' export * from './user-group' diff --git a/mock-api/msw/handlers.ts b/mock-api/msw/handlers.ts index 7db23c6f6..3dca6858b 100644 --- a/mock-api/msw/handlers.ts +++ b/mock-api/msw/handlers.ts @@ -38,6 +38,7 @@ import { GiB } from '~/util/units' import { alertClasses, PROBE_ALERT_ID } from '../alert' import { defaultSilo, toIdp } from '../silo' +import { timeseriesSchemas } from '../timeseries-schema' import { getTimestamps } from '../util' import { defaultFirewallRules } from '../vpc' import { resendableAlerts, retryPendingDeliveries, validateSubscription } from './alert' @@ -2115,6 +2116,10 @@ export const handlers = makeHandlers({ await delay(1000) return handleOxqlMetrics(body) }, + systemTimeseriesSchemaList({ cookies }) { + requireFleetViewer(cookies) + return { items: timeseriesSchemas } + }, siloMetric: handleMetrics, systemUpdateRepositoryList: ({ cookies }) => { requireFleetViewer(cookies) @@ -3006,7 +3011,6 @@ export const handlers = makeHandlers({ systemNetworkingSettingsUpdate: NotImplemented, systemNetworkingSettingsView: NotImplemented, systemQuotasList: NotImplemented, - systemTimeseriesSchemaList: NotImplemented, systemUpdateRecoveryFinish: NotImplemented, systemUpdateRepositoryView: NotImplemented, systemUpdateTrustRootCreate: NotImplemented, diff --git a/mock-api/msw/util.ts b/mock-api/msw/util.ts index d6aa115d6..82e507d85 100644 --- a/mock-api/msw/util.ts +++ b/mock-api/msw/util.ts @@ -596,7 +596,8 @@ const getVibe = (query: string): OxqlVibe => { const [firstTable, ...moreTables] = [...query.matchAll(/get ([a-z_]+:[a-z_]+)/g)].map( (m) => m[1] as OxqlMetricName ) - if (!firstTable) throw new Error(`no "get " found in query: ${query}`) + // a query with no `get` can't parse, and the caret goes at the very start + if (!firstTable) throw fmtOxqlParseError(query, 0, 'one of "get", "{"') const alignment = query.match(/\bjoin\b/) ? 'joined' @@ -675,6 +676,31 @@ function getMultipleTables(vibe: OxqlVibe) { .exhaustive() } +/** + * Faithful port of omicron's `fmt_parse_error` so the mock's OxQL parse errors + * look exactly like real ones: an `Error at :` header with a + * context excerpt, a caret line pointing at the failure, and an `Expected:` + * line (whose peg Display repeats the position). Thrown as a string so the + * handler wrapper turns it into a 400 like Nexus's `invalid_request`. + * https://github.com/oxidecomputer/omicron/blob/6db4c7e/oximeter/db/src/oxql/mod.rs + */ +export function fmtOxqlParseError(source: string, offset: number, expected: string) { + const before = source.slice(0, offset) + const line = before.split('\n').length + const column = offset - before.lastIndexOf('\n') + let out = `Error at ${line}:${column}` + const context = 24 + const start = Math.max(0, offset - context) + const end = Math.min(source.length, offset + context) + const prefixLen = out.length + 2 + out += `: .. ${source.slice(start, end)} ..\n` + const leftPad = offset - start + 3 + prefixLen + const rightPad = end - offset + 3 + prefixLen + out += `${' '.repeat(leftPad)}^${' '.repeat(rightPad)}\n` + out += `Expected: error at ${line}:${column}: expected ${expected}\n` + return out +} + const histogramTables = new Set([ 'virtual_disk:io_latency', 'virtual_disk:io_size', @@ -683,6 +709,17 @@ const histogramTables = new Set([ ]) export function handleOxqlMetrics({ query }: TimeseriesQuery): Json { + // Sentinel for exercising the console's parse error handling: `oops` + // anywhere in a query fails with a realistic parse error pointing at it + const oops = query.indexOf('oops') + if (oops !== -1) { + throw fmtOxqlParseError( + query, + oops, + 'one of "align", "filter", "first", "get", "group_by", "join", "last"' + ) + } + const vibe = getVibe(query) if (histogramTables.has(vibe.firstTable)) diff --git a/mock-api/oxql-metrics.ts b/mock-api/oxql-metrics.ts index 73b6666f3..224b1f07b 100644 --- a/mock-api/oxql-metrics.ts +++ b/mock-api/oxql-metrics.ts @@ -66,7 +66,7 @@ export const pointsFrom = ( export const timeseriesFrom = (id: string, points: Json): Json => ({ fields: { - instanceId: { + instance_id: { type: 'uuid', value: id, }, diff --git a/mock-api/timeseries-schema.ts b/mock-api/timeseries-schema.ts new file mode 100644 index 000000000..8fa8b1934 --- /dev/null +++ b/mock-api/timeseries-schema.ts @@ -0,0 +1,903 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ +import type { TimeseriesSchema } from '@oxide/api' + +import type { Json } from './json-type' + +/** + * Snapshot from dogfood, as schemas are pretty darn stable. Trimmed down to a + * smaller set to represent the variety of datum_type. + */ +export const timeseriesSchemas: Json[] = [ + { + timeseries_name: 'collection_target:cpus_provisioned', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'id', + field_type: 'uuid', + source: 'target', + description: '', + }, + ], + datum_type: 'i64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2023-10-25T23:05:04.909050887Z', + }, + { + timeseries_name: 'crucible_upstairs:activated', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'upstairs_uuid', + field_type: 'uuid', + source: 'target', + description: '', + }, + ], + datum_type: 'cumulative_i64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2023-10-25T23:04:34.899663499Z', + }, + { + timeseries_name: 'database_transaction:retry_data', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'attempt', + field_type: 'u32', + source: 'metric', + description: '', + }, + { + name: 'name', + field_type: 'string', + source: 'target', + description: '', + }, + ], + datum_type: 'f64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2023-12-09T05:05:12.777325080Z', + }, + { + timeseries_name: 'ddm_router:originated_tunnel_endpoints', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'hostname', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + ], + datum_type: 'u64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-03-22T06:41:04.468869678Z', + }, + { + timeseries_name: 'hardware_component:amd_cpu_tctl', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'chassis_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'chassis_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'description', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'gateway_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'hubris_archive_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sensor', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'slot', + field_type: 'u32', + source: 'target', + description: '', + }, + ], + datum_type: 'f32', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-09-26T20:54:40.780650780Z', + }, + { + timeseries_name: 'hardware_component:fan_speed', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'chassis_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'chassis_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'description', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'gateway_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'hubris_archive_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sensor', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'slot', + field_type: 'u32', + source: 'target', + description: '', + }, + ], + datum_type: 'f32', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-08-27T02:18:06.071093138Z', + }, + { + timeseries_name: 'hardware_component:sensor_error_count', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'chassis_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'chassis_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'description', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'error', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'gateway_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'hubris_archive_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sensor', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'sensor_kind', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'slot', + field_type: 'u32', + source: 'target', + description: '', + }, + ], + datum_type: 'cumulative_u64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-08-27T02:18:06.038148045Z', + }, + { + timeseries_name: 'hardware_component:temperature', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'chassis_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'chassis_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'chassis_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'component_kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'description', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'gateway_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'hubris_archive_id', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sensor', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'slot', + field_type: 'u32', + source: 'target', + description: '', + }, + ], + datum_type: 'f32', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-08-27T02:18:06.044202257Z', + }, + { + timeseries_name: 'sled_data_link:bytes_received', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'link_name', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'sled_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'sled_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'zone_name', + field_type: 'string', + source: 'target', + description: '', + }, + ], + datum_type: 'cumulative_u64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-08-14T03:24:34.149372848Z', + }, + { + timeseries_name: 'sled_data_link:bytes_sent', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'link_name', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'sled_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'sled_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'zone_name', + field_type: 'string', + source: 'target', + description: '', + }, + ], + datum_type: 'cumulative_u64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-08-14T03:24:34.232414065Z', + }, + { + timeseries_name: 'sled_data_link:errors_received', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'link_name', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'sled_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'sled_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'zone_name', + field_type: 'string', + source: 'target', + description: '', + }, + ], + datum_type: 'cumulative_u64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-08-14T03:24:34.050086881Z', + }, + { + timeseries_name: 'sled_data_link:errors_sent', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'link_name', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'sled_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'sled_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'zone_name', + field_type: 'string', + source: 'target', + description: '', + }, + ], + datum_type: 'cumulative_u64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-08-14T03:24:34.092318117Z', + }, + { + timeseries_name: 'switch_data_link:fec_high_symbol_errors', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'asic_fab', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'asic_lot', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'asic_wafer', + field_type: 'u8', + source: 'target', + description: '', + }, + { + name: 'asic_wafer_loc_x', + field_type: 'i16', + source: 'target', + description: '', + }, + { + name: 'asic_wafer_loc_y', + field_type: 'i16', + source: 'target', + description: '', + }, + { + name: 'kind', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'link_id', + field_type: 'u8', + source: 'metric', + description: '', + }, + { + name: 'model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'network', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'port_id', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'rack_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'sled_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'sled_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'sled_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'switch_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'switch_model', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'switch_revision', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'switch_serial', + field_type: 'string', + source: 'target', + description: '', + }, + { + name: 'switch_slot', + field_type: 'u16', + source: 'target', + description: '', + }, + ], + datum_type: 'bool', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2025-02-14T22:29:39.720562272Z', + }, + { + timeseries_name: 'virtual_disk:io_latency', + description: { + target: '', + metric: '', + }, + field_schema: [ + { + name: 'attached_instance_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'block_size', + field_type: 'u32', + source: 'target', + description: '', + }, + { + name: 'disk_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'io_kind', + field_type: 'string', + source: 'metric', + description: '', + }, + { + name: 'project_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + { + name: 'silo_id', + field_type: 'uuid', + source: 'target', + description: '', + }, + ], + datum_type: 'histogram_u64', + version: 1, + authz_scope: 'fleet', + units: 'none', + created: '2024-09-12T18:07:20.754569807Z', + }, +] diff --git a/package-lock.json b/package-lock.json index 29293cccd..91a0b1943 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,11 @@ "license": "MPL-2.0", "dependencies": { "@base-ui/react": "^1.1.0", + "@codemirror/autocomplete": "^6.20.3", + "@codemirror/commands": "^6.11.0", + "@codemirror/language": "^6.12.4", + "@codemirror/state": "^6.7.1", + "@codemirror/view": "^6.43.9", "@floating-ui/react": "^0.26.23", "@headlessui/react": "^2.2.9", "@oxide/design-system": "^6.7.1", @@ -45,6 +50,7 @@ "react-stately": "^3.32.2", "remeda": "^2.30.0", "semver": "^7.7.3", + "shiki": "^4.5.0", "simplebar-react": "^3.2.6", "ts-pattern": "^5.8.0", "tslib": "^2.7.0", @@ -80,6 +86,7 @@ "oxlint": "^1.70.0", "oxlint-tsgolint": "^0.23.0", "patch-package": "^8.0.0", + "smol-toml": "^1.9.0", "tailwindcss": "^4.3.3", "type-fest": "^5.2.0", "typescript": "^7.0.2", @@ -94,8 +101,6 @@ }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", - "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", "dev": true, "license": "MIT", "dependencies": { @@ -107,8 +112,6 @@ }, "node_modules/@apidevtools/openapi-schemas": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", - "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", "dev": true, "license": "MIT", "engines": { @@ -117,15 +120,11 @@ }, "node_modules/@apidevtools/swagger-methods": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", - "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", "dev": true, "license": "MIT" }, "node_modules/@apidevtools/swagger-parser": { "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", "dev": true, "license": "MIT", "dependencies": { @@ -142,8 +141,6 @@ }, "node_modules/@asciidoctor/core": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-3.0.4.tgz", - "integrity": "sha512-41SDMi7iRRBViPe0L6VWFTe55bv6HEOJeRqMj5+E5wB1YPdUPuTucL4UAESPZM6OWmn4t/5qM5LusXomFUVwVQ==", "license": "MIT", "peer": true, "dependencies": { @@ -157,8 +154,6 @@ }, "node_modules/@asciidoctor/opal-runtime": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@asciidoctor/opal-runtime/-/opal-runtime-3.0.1.tgz", - "integrity": "sha512-iW7ACahOG0zZft4A/4CqDcc7JX+fWRNjV5tFAVkNCzwZD+EnFolPaUOPYt8jzadc0+Bgd80cQTtRMQnaaV1kkg==", "license": "MIT", "peer": true, "dependencies": { @@ -171,8 +166,6 @@ }, "node_modules/@babel/runtime": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -180,8 +173,6 @@ }, "node_modules/@base-ui/react": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@base-ui/react/-/react-1.1.0.tgz", - "integrity": "sha512-ikcJRNj1mOiF2HZ5jQHrXoVoHcNHdBU5ejJljcBl+VTLoYXR6FidjTN86GjO6hyshi6TZFuNvv0dEOgaOFv6Lw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", @@ -212,8 +203,6 @@ }, "node_modules/@base-ui/utils": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@base-ui/utils/-/utils-0.2.4.tgz", - "integrity": "sha512-smZwpMhjO29v+jrZusBSc5T+IJ3vBb9cjIiBjtKcvWmRj9Z4DWGVR3efr1eHR56/bqY5a4qyY9ElkOY5ljo3ng==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.28.4", @@ -234,15 +223,11 @@ }, "node_modules/@blazediff/core": { "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@blazediff/core/-/core-1.10.0.tgz", - "integrity": "sha512-AOQff0zgR7cGsZL+4E7hVkmujoPUpm0J9xzWGWZj5wCjd3gmxESXAPfKyuzs93VdpQNFhHlBhfOjrcZ+XTERtQ==", "dev": true, "license": "MIT" }, "node_modules/@bundled-es-modules/cookie": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", - "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", "dev": true, "license": "ISC", "dependencies": { @@ -251,8 +236,6 @@ }, "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { @@ -261,8 +244,6 @@ }, "node_modules/@bundled-es-modules/statuses": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", - "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", "dev": true, "license": "ISC", "dependencies": { @@ -271,8 +252,6 @@ }, "node_modules/@bundled-es-modules/tough-cookie": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", - "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", "dev": true, "license": "ISC", "dependencies": { @@ -280,10 +259,57 @@ "tough-cookie": "^4.1.4" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.3", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.11.0", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.7.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.4", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/state": { + "version": "6.7.4", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.43.11", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.7.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@commander-js/extra-typings": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@commander-js/extra-typings/-/extra-typings-14.0.0.tgz", - "integrity": "sha512-hIn0ncNaJRLkZrxBIp5AsW/eXEHNKYQBh0aPdoUqNgD+Io3NIykQqpKFyKcuasZhicGaEZJX/JBSIkZ4e5x8Dg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -323,8 +349,6 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "peer": true, @@ -343,8 +367,6 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -357,8 +379,6 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "peer": true, @@ -368,8 +388,6 @@ }, "node_modules/@eslint/config-array": { "version": "0.23.5", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", - "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -384,8 +402,6 @@ }, "node_modules/@eslint/config-helpers": { "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", - "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -398,8 +414,6 @@ }, "node_modules/@eslint/core": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", - "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -412,8 +426,6 @@ }, "node_modules/@eslint/object-schema": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", - "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -423,8 +435,6 @@ }, "node_modules/@eslint/plugin-kit": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", - "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -438,8 +448,6 @@ }, "node_modules/@floating-ui/core": { "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", - "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", "license": "MIT", "dependencies": { "@floating-ui/utils": "^0.2.11" @@ -447,8 +455,6 @@ }, "node_modules/@floating-ui/dom": { "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", - "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", "license": "MIT", "dependencies": { "@floating-ui/core": "^1.7.5", @@ -457,8 +463,6 @@ }, "node_modules/@floating-ui/react": { "version": "0.26.28", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", - "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.1.2", @@ -472,8 +476,6 @@ }, "node_modules/@floating-ui/react-dom": { "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", - "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.7.6" @@ -485,14 +487,10 @@ }, "node_modules/@floating-ui/utils": { "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", - "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", "license": "MIT" }, "node_modules/@formatjs/ecma402-abstract": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.5.tgz", - "integrity": "sha512-1HTESOq1IUa23g1lFZEGIXsfZKZOwWmB9RROwGn+xariiQnd++wwTMvlRAbZ8wtXRHFUamJPxsKcxpSzeCvFWQ==", "license": "MIT", "dependencies": { "@formatjs/fast-memoize": "2.2.7", @@ -503,8 +501,6 @@ }, "node_modules/@formatjs/fast-memoize": { "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", - "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", "license": "MIT", "dependencies": { "tslib": "^2.8.0" @@ -512,8 +508,6 @@ }, "node_modules/@formatjs/icu-messageformat-parser": { "version": "2.11.3", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.3.tgz", - "integrity": "sha512-H/KfWSosaiDiOaW4nHe1Fn4Cgzm+oFQ8giTmB5RJzTBNSMmd+j2NVrvvZHAmlxJHcuOelzKBLjQ2EDcyH4NSWw==", "license": "MIT", "dependencies": { "@formatjs/ecma402-abstract": "2.3.5", @@ -523,8 +517,6 @@ }, "node_modules/@formatjs/icu-skeleton-parser": { "version": "1.8.15", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.15.tgz", - "integrity": "sha512-qNrKxWJmnWxin5U4A4Evy7C0rgRiNw3IqXu9OGuT31B8lDxBGl+OgT8kcq0ZVKK0gqA4l4SQB9x+SFAvLT5hcQ==", "license": "MIT", "dependencies": { "@formatjs/ecma402-abstract": "2.3.5", @@ -533,8 +525,6 @@ }, "node_modules/@formatjs/intl-localematcher": { "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz", - "integrity": "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==", "license": "MIT", "dependencies": { "tslib": "^2.8.0" @@ -542,8 +532,6 @@ }, "node_modules/@headlessui/react": { "version": "2.2.9", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.9.tgz", - "integrity": "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.26.16", @@ -562,8 +550,6 @@ }, "node_modules/@humanfs/core": { "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", - "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -576,8 +562,6 @@ }, "node_modules/@humanfs/node": { "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", - "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -592,8 +576,6 @@ }, "node_modules/@humanfs/types": { "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", - "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -603,8 +585,6 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -618,8 +598,6 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -633,8 +611,6 @@ }, "node_modules/@inquirer/confirm": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.1.tgz", - "integrity": "sha512-6ycMm7k7NUApiMGfVc32yIPp28iPKxhGRMqoNDiUjq2RyTAkbs5Fx0TdzBqhabcKvniDdAAvHCmsRjnNfTsogw==", "dev": true, "license": "MIT", "dependencies": { @@ -650,8 +626,6 @@ }, "node_modules/@inquirer/core": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.0.1.tgz", - "integrity": "sha512-KKTgjViBQUi3AAssqjUFMnMO3CM3qwCHvePV9EW+zTKGKafFGFF01sc1yOIYjLJ7QU52G/FbzKc+c01WLzXmVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -671,8 +645,6 @@ }, "node_modules/@inquirer/core/node_modules/ansi-escapes": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -687,8 +659,6 @@ }, "node_modules/@inquirer/core/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -703,8 +673,6 @@ }, "node_modules/@inquirer/core/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -716,22 +684,16 @@ }, "node_modules/@inquirer/core/node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/@inquirer/core/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { @@ -740,8 +702,6 @@ }, "node_modules/@inquirer/core/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -755,8 +715,6 @@ }, "node_modules/@inquirer/core/node_modules/type-fest": { "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -768,8 +726,6 @@ }, "node_modules/@inquirer/core/node_modules/wrap-ansi": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "license": "MIT", "dependencies": { @@ -783,8 +739,6 @@ }, "node_modules/@inquirer/figures": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.7.tgz", - "integrity": "sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==", "dev": true, "license": "MIT", "engines": { @@ -793,8 +747,6 @@ }, "node_modules/@inquirer/type": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.0.tgz", - "integrity": "sha512-YYykfbw/lefC7yKj7nanzQXILM7r3suIvyFlCcMskc99axmsSewXWkAfXKwMbgxL76iAFVmRwmYdwNZNc8gjog==", "dev": true, "license": "MIT", "engines": { @@ -806,8 +758,6 @@ }, "node_modules/@internationalized/date": { "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.10.0.tgz", - "integrity": "sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -815,8 +765,6 @@ }, "node_modules/@internationalized/message": { "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.8.tgz", - "integrity": "sha512-Rwk3j/TlYZhn3HQ6PyXUV0XP9Uv42jqZGNegt0BXlxjE6G3+LwHjbQZAGHhCnCPdaA6Tvd3ma/7QzLlLkJxAWA==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0", @@ -825,8 +773,6 @@ }, "node_modules/@internationalized/number": { "version": "3.6.5", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.5.tgz", - "integrity": "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -834,8 +780,6 @@ }, "node_modules/@internationalized/string": { "version": "3.2.7", - "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.7.tgz", - "integrity": "sha512-D4OHBjrinH+PFZPvfCXvG28n2LSykWcJ7GIioQL+ok0LON15SdfoUssoHzzOUmVZLbRoREsQXVzA6r8JKsbP6A==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -843,8 +787,6 @@ }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -853,8 +795,6 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -863,8 +803,6 @@ }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { "node": ">=6.0.0" @@ -872,14 +810,10 @@ }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -888,15 +822,33 @@ }, "node_modules/@jsdevtools/ono": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "dev": true, "license": "MIT" }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "license": "MIT" + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.4", + "license": "MIT" + }, "node_modules/@mswjs/http-middleware": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@mswjs/http-middleware/-/http-middleware-0.10.3.tgz", - "integrity": "sha512-6CoX9IivDF7hggORdA4vX6uz+pkY1urGQMhmviHmYya/0b4EXwmhaXlGLQG3G29heqb3qdjp61V0+E2xRtyR5A==", "dev": true, "license": "MIT", "dependencies": { @@ -912,8 +864,6 @@ }, "node_modules/@mswjs/interceptors": { "version": "0.37.5", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.37.5.tgz", - "integrity": "sha512-AAwRb5vXFcY4L+FvZ7LZusDuZ0vEe0Zm8ohn1FM6/X7A3bj4mqmkAcGRWuvC2JwSygNwHAAmMnAI73vPHeqsHA==", "dev": true, "license": "MIT", "dependencies": { @@ -929,34 +879,33 @@ } }, "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.4.tgz", + "integrity": "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==", "license": "MIT", "optional": true, "dependencies": { - "@tybys/wasm-util": "^0.10.1" + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "node_modules/@open-draft/deferred-promise": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", "dev": true, "license": "MIT" }, "node_modules/@open-draft/logger": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", "dev": true, "license": "MIT", "dependencies": { @@ -966,15 +915,11 @@ }, "node_modules/@open-draft/until": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", "dev": true, "license": "MIT" }, "node_modules/@oxc-project/types": { "version": "0.133.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", - "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" @@ -1107,6 +1052,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1124,6 +1072,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1141,6 +1092,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1158,6 +1112,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1175,6 +1132,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1192,6 +1152,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1203,12 +1166,13 @@ }, "node_modules/@oxfmt/binding-linux-x64-gnu": { "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.55.0.tgz", - "integrity": "sha512-MihqiPziJNoWy4MqNSV+jVA1g+07iQDjZiR0vaCaDoPgFEiJpCMsxamktzLV07cEeQsSJ04vQaU4CzCQwIvtDA==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1220,12 +1184,13 @@ }, "node_modules/@oxfmt/binding-linux-x64-musl": { "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.55.0.tgz", - "integrity": "sha512-Yqghym7KYAVjP9MmSrNZiDeerMuoejNjo0r3ox5H3GDKk8eAfl8VyJm9i+pWCLDCTnAbcTUMMN2ZKjUYXH1v3g==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1305,8 +1270,6 @@ }, "node_modules/@oxide/design-system": { "version": "6.7.1", - "resolved": "https://registry.npmjs.org/@oxide/design-system/-/design-system-6.7.1.tgz", - "integrity": "sha512-ghOOWy15Sx8XFa2akrZOk6+YnPTmPel5NQW2H3Sp5C1KmLO2lzBE4fJ5bghr82PRaj4mIpSsz5U2nv8pXOrd7Q==", "license": "MPL 2.0", "dependencies": { "@floating-ui/react": "^0.27.16", @@ -1326,8 +1289,6 @@ }, "node_modules/@oxide/design-system/node_modules/@floating-ui/react": { "version": "0.27.19", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.19.tgz", - "integrity": "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.1.8", @@ -1341,8 +1302,6 @@ }, "node_modules/@oxide/openapi-gen-ts": { "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@oxide/openapi-gen-ts/-/openapi-gen-ts-0.14.0.tgz", - "integrity": "sha512-L7n/3Ox8UTgDwdDvqCr+PekXcTboq5HQhdEawZWD8ct9QkycCciZoClLWApz/B5T9eiQjZq/5nqyE5JJqqw6nw==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -1360,8 +1319,6 @@ }, "node_modules/@oxide/openapi-gen-ts/node_modules/prettier": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true, "license": "MIT", "bin": { @@ -1376,8 +1333,6 @@ }, "node_modules/@oxide/react-asciidoc": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@oxide/react-asciidoc/-/react-asciidoc-2.2.1.tgz", - "integrity": "sha512-X8DDHIxY/13GlxaoVxXg/hypzd3vT8IcU6MohPKA1hw7Dxyx0WdeFVlKLtDqWGNI8ld+wyaJpWscIx7chELQzQ==", "license": "MPL 2.0", "peer": true, "dependencies": { @@ -1434,8 +1389,6 @@ }, "node_modules/@oxlint-tsgolint/linux-x64": { "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-3bdilnyA7kmSTjK27rvjIjSxL5SIg3wt7vwNiRkouWB83ytssyKnuGvxSYJxgMEmFpSutzaBzcCUM2jDtPGcgA==", "cpu": [ "x64" ], @@ -1601,6 +1554,9 @@ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1618,6 +1574,9 @@ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1635,6 +1594,9 @@ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1652,6 +1614,9 @@ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1669,6 +1634,9 @@ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1686,6 +1654,9 @@ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1697,12 +1668,13 @@ }, "node_modules/@oxlint/binding-linux-x64-gnu": { "version": "1.70.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.70.0.tgz", - "integrity": "sha512-tap04CsHYOl0nSAQJfPNIuBxqEPB2HnhQqwaOXLg1jnp2XfRo8Fa814dA4QC4zpvTWXCjAAaCY1W5LOORkEQuQ==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1714,12 +1686,13 @@ }, "node_modules/@oxlint/binding-linux-x64-musl": { "version": "1.70.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.70.0.tgz", - "integrity": "sha512-hzJa/WgvtJpbBD9rgfy0qe+MjbxOXNUT0bfR1S6EQQzfTtBFA9xg5q8KSwRrQ2QfSS+TaP4j+4mVPQrfNc6UNg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1799,8 +1772,6 @@ }, "node_modules/@peculiar/asn1-cms": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.8.0.tgz", - "integrity": "sha512-NgekZOrSJFSBFLFoLfwePguAWAx7z1+f2TEsWFUMyiqqfntZ4+S/S5hzqME3q4pCA0iOsFKdwiQ35dwY24eVqA==", "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.8.0", @@ -1812,8 +1783,6 @@ }, "node_modules/@peculiar/asn1-csr": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.8.0.tgz", - "integrity": "sha512-akbF8+uvleHs8sejNPQxwmVFuInAg6FMNHOwMILXfP518YfFJwdR3jr6oNUPOaEJfuEhn/vkNOCIT6ASUd4mbg==", "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.8.0", @@ -1824,8 +1793,6 @@ }, "node_modules/@peculiar/asn1-ecc": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.8.0.tgz", - "integrity": "sha512-ohwlk+u9Rv2NOAY1c6MfHj45ATVF8R1DUN/WCgABiRtLi2ZftlZWZX7KvpAbU8v9xPcmoILfELeEABj/rn18AQ==", "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.8.0", @@ -1836,8 +1803,6 @@ }, "node_modules/@peculiar/asn1-pfx": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.8.0.tgz", - "integrity": "sha512-5yof1ytoB++RQtaFbqSUJ8pxDJtZT6vbVqZ8XoJ61ph7UjNVvfFwAilnCodqkNsAodpy13gDhoxZXw00pghnyg==", "license": "MIT", "dependencies": { "@peculiar/asn1-cms": "^2.8.0", @@ -1850,8 +1815,6 @@ }, "node_modules/@peculiar/asn1-pkcs8": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.8.0.tgz", - "integrity": "sha512-qAKXtLpBEw9LqhKpjw3ajZSXlBur+ipW+y2ivVBQAG6F6qRx94yO+1ZR4mvw+YaCfKSaOzLeYEzsPaBp4SJELA==", "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.8.0", @@ -1862,8 +1825,6 @@ }, "node_modules/@peculiar/asn1-pkcs9": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.8.0.tgz", - "integrity": "sha512-b5nDWCnkV60+cQ141D6sVVwK9nz64R5n3zSVnklGd+ECdkW2Ol3U1a6yYFlalpSOaD557yuJB64A+q42jG7lUQ==", "license": "MIT", "dependencies": { "@peculiar/asn1-cms": "^2.8.0", @@ -1878,8 +1839,6 @@ }, "node_modules/@peculiar/asn1-rsa": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.8.0.tgz", - "integrity": "sha512-zHEUlCqB2mk7x2lxDwHHJy7hWZOPdGHVlsmITWKB5/PbQo61atbu9PJ/0r9dQNMwFzbKPXZ8uK8/91eUhRznSg==", "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.8.0", @@ -1890,8 +1849,6 @@ }, "node_modules/@peculiar/asn1-schema": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", - "integrity": "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==", "license": "MIT", "dependencies": { "@peculiar/utils": "^2.0.2", @@ -1901,8 +1858,6 @@ }, "node_modules/@peculiar/asn1-x509": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.8.0.tgz", - "integrity": "sha512-N0CMuhWUzsWEVq6F1q9X6+VKUnWzSW+cSVg+aPaGGwDdbFoFWTYgin5MHwXgpWd6y9COMBxnfy/Qc+Xc7F0Zwg==", "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.8.0", @@ -1913,8 +1868,6 @@ }, "node_modules/@peculiar/asn1-x509-attr": { "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.8.0.tgz", - "integrity": "sha512-tHjkfS/qhMnmrlB2J9NhflQlQ7In3khO3CfmVrriOlpTeErY9ZIKOso1hQ5JQiyrJ7ShvqVPk7E5fQmbclkSKA==", "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.8.0", @@ -1925,8 +1878,6 @@ }, "node_modules/@peculiar/utils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", - "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", "license": "MIT", "dependencies": { "tslib": "^2.8.1" @@ -1934,8 +1885,6 @@ }, "node_modules/@peculiar/x509": { "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", - "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", "license": "MIT", "dependencies": { "@peculiar/asn1-cms": "^2.6.0", @@ -1956,8 +1905,6 @@ }, "node_modules/@playwright/test": { "version": "1.61.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.0.tgz", - "integrity": "sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1972,15 +1919,11 @@ }, "node_modules/@polka/url": { "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, "license": "MIT" }, "node_modules/@radix-ui/react-accordion": { "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", - "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2010,14 +1953,10 @@ }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/primitive": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2031,8 +1970,6 @@ }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-context": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2046,8 +1983,6 @@ }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-id": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -2064,8 +1999,6 @@ }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-primitive": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { "@radix-ui/react-slot": "1.2.3" @@ -2087,8 +2020,6 @@ }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-slot": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" @@ -2105,8 +2036,6 @@ }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-use-controllable-state": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", @@ -2124,8 +2053,6 @@ }, "node_modules/@radix-ui/react-accordion/node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2139,8 +2066,6 @@ }, "node_modules/@radix-ui/react-collapsible": { "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", - "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2169,14 +2094,10 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/primitive": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2190,8 +2111,6 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-context": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2205,8 +2124,6 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-id": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -2223,8 +2140,6 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-presence": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", - "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", @@ -2247,8 +2162,6 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-primitive": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { "@radix-ui/react-slot": "1.2.3" @@ -2270,8 +2183,6 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-slot": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" @@ -2288,8 +2199,6 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-use-controllable-state": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", @@ -2307,8 +2216,6 @@ }, "node_modules/@radix-ui/react-collapsible/node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2322,8 +2229,6 @@ }, "node_modules/@radix-ui/react-collection": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", @@ -2348,8 +2253,6 @@ }, "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2363,8 +2266,6 @@ }, "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2378,8 +2279,6 @@ }, "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-primitive": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { "@radix-ui/react-slot": "1.2.3" @@ -2401,8 +2300,6 @@ }, "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" @@ -2419,8 +2316,6 @@ }, "node_modules/@radix-ui/react-direction": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2434,8 +2329,6 @@ }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", - "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2465,14 +2358,10 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/primitive": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2486,8 +2375,6 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2501,8 +2388,6 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-id": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -2519,8 +2404,6 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-primitive": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { "@radix-ui/react-slot": "1.2.3" @@ -2542,8 +2425,6 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-slot": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" @@ -2560,8 +2441,6 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2575,8 +2454,6 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-controllable-state": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", @@ -2594,8 +2471,6 @@ }, "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2609,8 +2484,6 @@ }, "node_modules/@radix-ui/react-tabs": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", - "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -2639,14 +2512,10 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/primitive": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2660,8 +2529,6 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-context": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2675,8 +2542,6 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-id": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -2693,8 +2558,6 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-presence": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", - "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", @@ -2717,8 +2580,6 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-primitive": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { "@radix-ui/react-slot": "1.2.3" @@ -2740,8 +2601,6 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-slot": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" @@ -2758,8 +2617,6 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-controllable-state": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", @@ -2777,8 +2634,6 @@ }, "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2792,8 +2647,6 @@ }, "node_modules/@radix-ui/react-use-effect-event": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -2810,8 +2663,6 @@ }, "node_modules/@radix-ui/react-use-effect-event/node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -2825,8 +2676,6 @@ }, "node_modules/@react-aria/breadcrumbs": { "version": "3.5.29", - "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.29.tgz", - "integrity": "sha512-rKS0dryllaZJqrr3f/EAf2liz8CBEfmL5XACj+Z1TAig6GIYe1QuA3BtkX0cV9OkMugXdX8e3cbA7nD10ORRqg==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -2843,8 +2692,6 @@ }, "node_modules/@react-aria/button": { "version": "3.14.2", - "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.14.2.tgz", - "integrity": "sha512-VbLIA+Kd6f/MDjd+TJBUg2+vNDw66pnvsj2E4RLomjI9dfBuN7d+Yo2UnsqKVyhePjCUZ6xxa2yDuD63IOSIYA==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -2862,8 +2709,6 @@ }, "node_modules/@react-aria/calendar": { "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.9.2.tgz", - "integrity": "sha512-uSLxLgOPRnEU4Jg59lAhUVA+uDx/55NBg4lpfsP2ynazyiJ5LCXmYceJi+VuOqMml7d9W0dB87OldOeLdIxYVA==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.10.0", @@ -2884,8 +2729,6 @@ }, "node_modules/@react-aria/checkbox": { "version": "3.16.2", - "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.16.2.tgz", - "integrity": "sha512-29Mj9ZqXioJ0bcMnNGooHztnTau5pikZqX3qCRj5bYR3by/ZFFavYoMroh9F7s/MbFm/tsKX+Sf02lYFEdXRjA==", "license": "Apache-2.0", "dependencies": { "@react-aria/form": "^3.1.2", @@ -2907,8 +2750,6 @@ }, "node_modules/@react-aria/color": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@react-aria/color/-/color-3.1.2.tgz", - "integrity": "sha512-jCC+Q7rAQGLQBkHjkPAeDuGYuMbc4neifjlNRiyZ9as1z4gg63H8MteoWYYk6K4vCKKxSixgt8MfI29XWMOWPQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -2932,8 +2773,6 @@ }, "node_modules/@react-aria/combobox": { "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.14.0.tgz", - "integrity": "sha512-z4ro0Hma//p4nL2IJx5iUa7NwxeXbzSoZ0se5uTYjG1rUUMszg+wqQh/AQoL+eiULn7rs18JY9wwNbVIkRNKWA==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -2960,8 +2799,6 @@ }, "node_modules/@react-aria/datepicker": { "version": "3.15.2", - "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.15.2.tgz", - "integrity": "sha512-th078hyNqPf4P2K10su/y32zPDjs3lOYVdHvsL9/+5K1dnTvLHCK5vgUyLuyn8FchhF7cmHV49D+LZVv65PEpQ==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.10.0", @@ -2990,8 +2827,6 @@ }, "node_modules/@react-aria/dialog": { "version": "3.5.31", - "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.31.tgz", - "integrity": "sha512-inxQMyrzX0UBW9Mhraq0nZ4HjHdygQvllzloT1E/RlDd61lr3RbmJR6pLsrbKOTtSvDIBJpCso1xEdHCFNmA0Q==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3008,8 +2843,6 @@ }, "node_modules/@react-aria/disclosure": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@react-aria/disclosure/-/disclosure-3.1.0.tgz", - "integrity": "sha512-5996BeBpnj+yKXYysz+UuhFQxGFPvaZZ3zNBd052wz/i+TVFVGSqqYJ6cwZyO1AfBR8zOT0ZIiK4EC3ETwSvtQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.10", @@ -3025,8 +2858,6 @@ }, "node_modules/@react-aria/dnd": { "version": "3.11.3", - "resolved": "https://registry.npmjs.org/@react-aria/dnd/-/dnd-3.11.3.tgz", - "integrity": "sha512-MyTziciik1Owz3rqDghu0K3ZtTFvmj/R2ZsLDwbU9N4hKqGX/BKnrI8SytTn8RDqVv5LmA/GhApLngiupTAsXw==", "license": "Apache-2.0", "dependencies": { "@internationalized/string": "^3.2.7", @@ -3048,8 +2879,6 @@ }, "node_modules/@react-aria/focus": { "version": "3.21.2", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.2.tgz", - "integrity": "sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3065,8 +2894,6 @@ }, "node_modules/@react-aria/form": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.1.2.tgz", - "integrity": "sha512-R3i7L7Ci61PqZQvOrnL9xJeWEbh28UkTVgkj72EvBBn39y4h7ReH++0stv7rRs8p5ozETSKezBbGfu4UsBewWw==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3082,8 +2909,6 @@ }, "node_modules/@react-aria/grid": { "version": "3.14.5", - "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.14.5.tgz", - "integrity": "sha512-XHw6rgjlTqc85e3zjsWo3U0EVwjN5MOYtrolCKc/lc2ItNdcY3OlMhpsU9+6jHwg/U3VCSWkGvwAz9hg7krd8Q==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3107,8 +2932,6 @@ }, "node_modules/@react-aria/gridlist": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/@react-aria/gridlist/-/gridlist-3.14.1.tgz", - "integrity": "sha512-keS03Am07aOn7RuNaRsMOyh0jscyhDn95asCVy4lxhl9A9TFk1Jw0o2L6q6cWRj1gFiKeacj/otG5H8ZKQQ2Wg==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3129,8 +2952,6 @@ }, "node_modules/@react-aria/i18n": { "version": "3.12.13", - "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.13.tgz", - "integrity": "sha512-YTM2BPg0v1RvmP8keHenJBmlx8FXUKsdYIEX7x6QWRd1hKlcDwphfjzvt0InX9wiLiPHsT5EoBTpuUk8SXc0Mg==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.10.0", @@ -3149,8 +2970,6 @@ }, "node_modules/@react-aria/interactions": { "version": "3.25.6", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.6.tgz", - "integrity": "sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.10", @@ -3166,8 +2985,6 @@ }, "node_modules/@react-aria/label": { "version": "3.7.22", - "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.22.tgz", - "integrity": "sha512-jLquJeA5ZNqDT64UpTc9XJ7kQYltUlNcgxZ37/v4mHe0UZ7QohCKdKQhXHONb0h2jjNUpp2HOZI8J9++jOpzxA==", "license": "Apache-2.0", "dependencies": { "@react-aria/utils": "^3.31.0", @@ -3181,8 +2998,6 @@ }, "node_modules/@react-aria/landmark": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@react-aria/landmark/-/landmark-3.0.7.tgz", - "integrity": "sha512-t8c610b8hPLS6Vwv+rbuSyljZosI1s5+Tosfa0Fk4q7d+Ex6Yj7hLfUFy59GxZAufhUYfGX396fT0gPqAbU1tg==", "license": "Apache-2.0", "dependencies": { "@react-aria/utils": "^3.31.0", @@ -3197,8 +3012,6 @@ }, "node_modules/@react-aria/link": { "version": "3.8.6", - "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.8.6.tgz", - "integrity": "sha512-7F7UDJnwbU9IjfoAdl6f3Hho5/WB7rwcydUOjUux0p7YVWh/fTjIFjfAGyIir7MJhPapun1D0t97QQ3+8jXVcg==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3214,8 +3027,6 @@ }, "node_modules/@react-aria/listbox": { "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.15.0.tgz", - "integrity": "sha512-Ub1Wu79R9sgxM7h4HeEdjOgOKDHwduvYcnDqsSddGXgpkL8ADjsy2YUQ0hHY5VnzA4BxK36bLp4mzSna8Qvj1w==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3235,8 +3046,6 @@ }, "node_modules/@react-aria/live-announcer": { "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@react-aria/live-announcer/-/live-announcer-3.4.4.tgz", - "integrity": "sha512-PTTBIjNRnrdJOIRTDGNifY2d//kA7GUAwRFJNOEwSNG4FW+Bq9awqLiflw0JkpyB0VNIwou6lqKPHZVLsGWOXA==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -3244,8 +3053,6 @@ }, "node_modules/@react-aria/menu": { "version": "3.19.3", - "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.19.3.tgz", - "integrity": "sha512-52fh8y8b2776R2VrfZPpUBJYC9oTP7XDy+zZuZTxPEd7Ywk0JNUl5F92y6ru22yPkS13sdhrNM/Op+V/KulmAg==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3270,8 +3077,6 @@ }, "node_modules/@react-aria/meter": { "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@react-aria/meter/-/meter-3.4.27.tgz", - "integrity": "sha512-andOOdJkgRJF9vBi5VWRmFodK+GT+5X1lLeNUmb4qOX8/MVfX/RbK72LDeIhd7xC7rSCFHj3WvZ198rK4q0k3w==", "license": "Apache-2.0", "dependencies": { "@react-aria/progress": "^3.4.27", @@ -3286,8 +3091,6 @@ }, "node_modules/@react-aria/numberfield": { "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.12.2.tgz", - "integrity": "sha512-M2b+z0HIXiXpGAWOQkO2kpIjaLNUXJ5Q3/GMa3Fkr+B1piFX0VuOynYrtddKVrmXCe+r5t+XcGb0KS29uqv7nQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -3309,8 +3112,6 @@ }, "node_modules/@react-aria/overlays": { "version": "3.30.0", - "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.30.0.tgz", - "integrity": "sha512-UpjqSjYZx5FAhceWCRVsW6fX1sEwya1fQ/TKkL53FAlLFR8QKuoKqFlmiL43YUFTcGK3UdEOy3cWTleLQwdSmQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3332,8 +3133,6 @@ }, "node_modules/@react-aria/progress": { "version": "3.4.27", - "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.27.tgz", - "integrity": "sha512-0OA1shs1575g1zmO8+rWozdbTnxThFFhOfuoL1m7UV5Dley6FHpueoKB1ECv7B+Qm4dQt6DoEqLg7wsbbQDhmg==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -3350,8 +3149,6 @@ }, "node_modules/@react-aria/radio": { "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.12.2.tgz", - "integrity": "sha512-I11f6I90neCh56rT/6ieAs3XyDKvEfbj/QmbU5cX3p+SJpRRPN0vxQi5D1hkh0uxDpeClxygSr31NmZsd4sqfg==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3372,8 +3169,6 @@ }, "node_modules/@react-aria/searchfield": { "version": "3.8.9", - "resolved": "https://registry.npmjs.org/@react-aria/searchfield/-/searchfield-3.8.9.tgz", - "integrity": "sha512-Yt2pj8Wb5/XsUr2T0DQqFv+DlFpzzWIWnNr9cJATUcWV/xw6ok7YFEg9+7EHtBmsCQxFFJtock1QfZzBw6qLtQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -3392,8 +3187,6 @@ }, "node_modules/@react-aria/select": { "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@react-aria/select/-/select-3.17.0.tgz", - "integrity": "sha512-q5ZuyAn5jSOeI0Ys99951TaGcF4O7u1SSBVxPMwVVXOU8ZhToCNx+WG3n/JDYHEjqdo7sbsVRaPA7LkBzBGf5w==", "license": "Apache-2.0", "dependencies": { "@react-aria/form": "^3.1.2", @@ -3418,8 +3211,6 @@ }, "node_modules/@react-aria/selection": { "version": "3.26.0", - "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.26.0.tgz", - "integrity": "sha512-ZBH3EfWZ+RfhTj01dH8L17uT7iNbXWS8u77/fUpHgtrm0pwNVhx0TYVnLU1YpazQ/3WVpvWhmBB8sWwD1FlD/g==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3437,8 +3228,6 @@ }, "node_modules/@react-aria/separator": { "version": "3.4.13", - "resolved": "https://registry.npmjs.org/@react-aria/separator/-/separator-3.4.13.tgz", - "integrity": "sha512-0NlcrdBfQbcjWEXdHl3+uSY1272n2ljT1gWL2RIf6aQsQWTZ0gz0rTgRHy0MTXN+y+tICItUERJT4vmTLtIzVg==", "license": "Apache-2.0", "dependencies": { "@react-aria/utils": "^3.31.0", @@ -3452,8 +3241,6 @@ }, "node_modules/@react-aria/slider": { "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.8.2.tgz", - "integrity": "sha512-6KyUGaVzRE4xAz1LKHbNh1q5wzxe58pdTHFSnxNe6nk1SCoHw7NfI4h2s2m6LgJ0megFxsT0Ir8aHaFyyxmbgg==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -3472,8 +3259,6 @@ }, "node_modules/@react-aria/spinbutton": { "version": "3.6.19", - "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.19.tgz", - "integrity": "sha512-xOIXegDpts9t3RSHdIN0iYQpdts0FZ3LbpYJIYVvdEHo9OpDS+ElnDzCGtwZLguvZlwc5s1LAKuKopDUsAEMkw==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -3490,8 +3275,6 @@ }, "node_modules/@react-aria/ssr": { "version": "3.9.10", - "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", - "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -3505,8 +3288,6 @@ }, "node_modules/@react-aria/switch": { "version": "3.7.8", - "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.7.8.tgz", - "integrity": "sha512-AfsUq1/YiuoprhcBUD9vDPyWaigAwctQNW1fMb8dROL+i/12B+Zekj8Ml+jbU69/kIVtfL0Jl7/0Bo9KK3X0xQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/toggle": "^3.12.2", @@ -3522,8 +3303,6 @@ }, "node_modules/@react-aria/table": { "version": "3.17.8", - "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.17.8.tgz", - "integrity": "sha512-bXiZoxTMbsqUJsYDhHPzKc3jw0HFJ/xMsJ49a0f7mp5r9zACxNLeIU0wJ4Uvx37dnYOHKzGliG+rj5l4sph7MA==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3549,8 +3328,6 @@ }, "node_modules/@react-aria/tabs": { "version": "3.10.8", - "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.10.8.tgz", - "integrity": "sha512-sPPJyTyoAqsBh76JinBAxStOcbjZvyWFYKpJ9Uqw+XT0ObshAPPFSGeh8DiQemPs02RwJdrfARPMhyqiX8t59A==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3569,8 +3346,6 @@ }, "node_modules/@react-aria/tag": { "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@react-aria/tag/-/tag-3.7.2.tgz", - "integrity": "sha512-JV679P5r4DftbqyNBRt7Nw9mP7dxaKPfikjyQuvUoEOa06wBLbM/hU9RJUPRvqK+Un6lgBDAmXD9NNf4N2xpdw==", "license": "Apache-2.0", "dependencies": { "@react-aria/gridlist": "^3.14.1", @@ -3591,8 +3366,6 @@ }, "node_modules/@react-aria/textfield": { "version": "3.18.2", - "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.18.2.tgz", - "integrity": "sha512-G+lM8VYSor6g9Yptc6hLZ6BF+0cq0pYol1z6wdQUQgJN8tg4HPtzq75lsZtlCSIznL3amgRAxJtd0dUrsAnvaQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/form": "^3.1.2", @@ -3612,8 +3385,6 @@ }, "node_modules/@react-aria/toast": { "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@react-aria/toast/-/toast-3.0.8.tgz", - "integrity": "sha512-rfJIms6AkMyQ7ZgKrMZgGfPwGcB/t1JoEwbc1PAmXcAvFI/hzF6YF7ZFDXiq38ucFsP9PnHmbXIzM9w4ccl18A==", "license": "Apache-2.0", "dependencies": { "@react-aria/i18n": "^3.12.13", @@ -3632,8 +3403,6 @@ }, "node_modules/@react-aria/toggle": { "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.12.2.tgz", - "integrity": "sha512-g25XLYqJuJpt0/YoYz2Rab8ax+hBfbssllcEFh0v0jiwfk2gwTWfRU9KAZUvxIqbV8Nm8EBmrYychDpDcvW1kw==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3650,8 +3419,6 @@ }, "node_modules/@react-aria/toolbar": { "version": "3.0.0-beta.21", - "resolved": "https://registry.npmjs.org/@react-aria/toolbar/-/toolbar-3.0.0-beta.21.tgz", - "integrity": "sha512-yRCk/GD8g+BhdDgxd3I0a0c8Ni4Wyo6ERzfSoBkPkwQ4X2E2nkopmraM9D0fXw4UcIr4bnmvADzkHXtBN0XrBg==", "license": "Apache-2.0", "dependencies": { "@react-aria/focus": "^3.21.2", @@ -3667,8 +3434,6 @@ }, "node_modules/@react-aria/tooltip": { "version": "3.8.8", - "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.8.8.tgz", - "integrity": "sha512-CmHUqtXtFWmG4AHMEr9hIVex+oscK6xcM2V47gq9ijNInxe3M6UBu/dBdkgGP/jYv9N7tzCAjTR8nNIHQXwvWw==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3685,8 +3450,6 @@ }, "node_modules/@react-aria/tree": { "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@react-aria/tree/-/tree-3.1.4.tgz", - "integrity": "sha512-6pbFeN0dAsCOrFGUKU39CNjft20zCAjLfMqfkRWisL+JkUHI2nq6odUJF5jJTsU1C+1951+3oFOmVxPX+K+akQ==", "license": "Apache-2.0", "dependencies": { "@react-aria/gridlist": "^3.14.1", @@ -3705,8 +3468,6 @@ }, "node_modules/@react-aria/utils": { "version": "3.31.0", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.31.0.tgz", - "integrity": "sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.10", @@ -3723,8 +3484,6 @@ }, "node_modules/@react-aria/visually-hidden": { "version": "3.8.28", - "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.28.tgz", - "integrity": "sha512-KRRjbVVob2CeBidF24dzufMxBveEUtUu7IM+hpdZKB+gxVROoh4XRLPv9SFmaH89Z7D9To3QoykVZoWD0lan6Q==", "license": "Apache-2.0", "dependencies": { "@react-aria/interactions": "^3.25.6", @@ -3739,8 +3498,6 @@ }, "node_modules/@react-stately/calendar": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.9.0.tgz", - "integrity": "sha512-U5Nf2kx9gDhJRxdDUm5gjfyUlt/uUfOvM1vDW2UA62cA6+2k2cavMLc2wNlXOb/twFtl6p0joYKHG7T4xnEFkg==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.10.0", @@ -3755,8 +3512,6 @@ }, "node_modules/@react-stately/checkbox": { "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.7.2.tgz", - "integrity": "sha512-j1ycUVz5JmqhaL6mDZgDNZqBilOB8PBW096sDPFaTtuYreDx2HOd1igxiIvwlvPESZwsJP7FVM3mYnaoXtpKPA==", "license": "Apache-2.0", "dependencies": { "@react-stately/form": "^3.2.2", @@ -3771,8 +3526,6 @@ }, "node_modules/@react-stately/collections": { "version": "3.12.8", - "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.8.tgz", - "integrity": "sha512-AceJYLLXt1Y2XIcOPi6LEJSs4G/ubeYW3LqOCQbhfIgMaNqKfQMIfagDnPeJX9FVmPFSlgoCBxb1pTJW2vjCAQ==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1", @@ -3784,8 +3537,6 @@ }, "node_modules/@react-stately/color": { "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-stately/color/-/color-3.9.2.tgz", - "integrity": "sha512-F+6Do8W3yu/4n7MpzZtbXwVukcLTFYYDIUtpoR+Jl52UmAr9Hf1CQgkyTI2azv1ZMzj1mVrTBhpBL0q27kFZig==", "license": "Apache-2.0", "dependencies": { "@internationalized/number": "^3.6.5", @@ -3804,8 +3555,6 @@ }, "node_modules/@react-stately/combobox": { "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.12.0.tgz", - "integrity": "sha512-A6q9R/7cEa/qoQsBkdslXWvD7ztNLLQ9AhBhVN9QvzrmrH5B4ymUwcTU8lWl22ykH7RRwfonLeLXJL4C+/L2oQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/collections": "^3.12.8", @@ -3823,8 +3572,6 @@ }, "node_modules/@react-stately/data": { "version": "3.11.6", - "resolved": "https://registry.npmjs.org/@react-stately/data/-/data-3.11.6.tgz", - "integrity": "sha512-S8q1Ejuhijl8SnyVOdDNFrMrWWnLk/Oh1ZT3KHSbTdpfMRtvhi5HukoiP06jlzz75phnpSPQL40npDtUB/kk3Q==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.24.1", @@ -3836,8 +3583,6 @@ }, "node_modules/@react-stately/datepicker": { "version": "3.15.2", - "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.15.2.tgz", - "integrity": "sha512-S5GL+W37chvV8knv9v0JRv0L6hKo732qqabCCHXzOpYxkLIkV4f/y3cHdEzFWzpZ0O0Gkg7WgeYo160xOdBKYg==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.10.0", @@ -3855,8 +3600,6 @@ }, "node_modules/@react-stately/disclosure": { "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@react-stately/disclosure/-/disclosure-3.0.8.tgz", - "integrity": "sha512-/Ce/Z76y85eSBZiemfU/uEyXkBBa1RdfLRaKD13rnfUV7/nS3ae1VtNlsXgmwQjWv2pmAiSuEKYMbZfVL7q/lQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.8", @@ -3869,8 +3612,6 @@ }, "node_modules/@react-stately/dnd": { "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@react-stately/dnd/-/dnd-3.7.1.tgz", - "integrity": "sha512-O1JBJ4HI1rVNKuoa5NXiC5FCrCEkr9KVBoKNlTZU8/cnQselhbEsUfMglAakO2EuwIaM1tIXoNF5J/N5P+6lTA==", "license": "Apache-2.0", "dependencies": { "@react-stately/selection": "^3.20.6", @@ -3883,8 +3624,6 @@ }, "node_modules/@react-stately/flags": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", - "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -3892,8 +3631,6 @@ }, "node_modules/@react-stately/form": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.2.2.tgz", - "integrity": "sha512-soAheOd7oaTO6eNs6LXnfn0tTqvOoe3zN9FvtIhhrErKz9XPc5sUmh3QWwR45+zKbitOi1HOjfA/gifKhZcfWw==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1", @@ -3905,8 +3642,6 @@ }, "node_modules/@react-stately/grid": { "version": "3.11.6", - "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.11.6.tgz", - "integrity": "sha512-vWPAkzpeTIsrurHfMubzMuqEw7vKzFhIJeEK5sEcLunyr1rlADwTzeWrHNbPMl66NAIAi70Dr1yNq+kahQyvMA==", "license": "Apache-2.0", "dependencies": { "@react-stately/collections": "^3.12.8", @@ -3921,8 +3656,6 @@ }, "node_modules/@react-stately/list": { "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.13.1.tgz", - "integrity": "sha512-eHaoauh21twbcl0kkwULhVJ+CzYcy1jUjMikNVMHOQdhr4WIBdExf7PmSgKHKqsSPhpGg6IpTCY2dUX3RycjDg==", "license": "Apache-2.0", "dependencies": { "@react-stately/collections": "^3.12.8", @@ -3937,8 +3670,6 @@ }, "node_modules/@react-stately/menu": { "version": "3.9.8", - "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.9.8.tgz", - "integrity": "sha512-bo0NOhofnTHLESiYfsSSw6gyXiPVJJ0UlN2igUXtJk5PmyhWjFzUzTzcnd7B028OB0si9w3LIWM3stqz5271Eg==", "license": "Apache-2.0", "dependencies": { "@react-stately/overlays": "^3.6.20", @@ -3952,8 +3683,6 @@ }, "node_modules/@react-stately/numberfield": { "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.10.2.tgz", - "integrity": "sha512-jlKVFYaH3RX5KvQ7a+SAMQuPccZCzxLkeYkBE64u1Zvi7YhJ8hkTMHG/fmZMbk1rHlseE2wfBdk0Rlya3MvoNQ==", "license": "Apache-2.0", "dependencies": { "@internationalized/number": "^3.6.5", @@ -3968,8 +3697,6 @@ }, "node_modules/@react-stately/overlays": { "version": "3.6.20", - "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.20.tgz", - "integrity": "sha512-YAIe+uI8GUXX8F/0Pzr53YeC5c/bjqbzDFlV8NKfdlCPa6+Jp4B/IlYVjIooBj9+94QvbQdjylegvYWK/iPwlg==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.8", @@ -3982,8 +3709,6 @@ }, "node_modules/@react-stately/radio": { "version": "3.11.2", - "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.11.2.tgz", - "integrity": "sha512-UM7L6AW+k8edhSBUEPZAqiWNRNadfOKK7BrCXyBiG79zTz0zPcXRR+N+gzkDn7EMSawDeyK1SHYUuoSltTactg==", "license": "Apache-2.0", "dependencies": { "@react-stately/form": "^3.2.2", @@ -3998,8 +3723,6 @@ }, "node_modules/@react-stately/searchfield": { "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@react-stately/searchfield/-/searchfield-3.5.16.tgz", - "integrity": "sha512-MRfqT1lZ24r94GuFNcGJXsfijZoWjSMySCT60T6NXtbOzVPuAF3K+pL70Rayq/EWLJjS2NPHND11VTs0VdcE0Q==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.8", @@ -4012,8 +3735,6 @@ }, "node_modules/@react-stately/select": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.8.0.tgz", - "integrity": "sha512-A721nlt0DSCDit0wKvhcrXFTG5Vv1qkEVkeKvobmETZy6piKvwh0aaN8iQno5AFuZaj1iOZeNjZ/20TsDJR/4A==", "license": "Apache-2.0", "dependencies": { "@react-stately/form": "^3.2.2", @@ -4030,8 +3751,6 @@ }, "node_modules/@react-stately/selection": { "version": "3.20.6", - "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.20.6.tgz", - "integrity": "sha512-a0bjuP2pJYPKEiedz2Us1W1aSz0iHRuyeQEdBOyL6Z6VUa6hIMq9H60kvseir2T85cOa4QggizuRV7mcO6bU5w==", "license": "Apache-2.0", "dependencies": { "@react-stately/collections": "^3.12.8", @@ -4045,8 +3764,6 @@ }, "node_modules/@react-stately/slider": { "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.7.2.tgz", - "integrity": "sha512-EVBHUdUYwj++XqAEiQg2fGi8Reccznba0uyQ3gPejF0pAc390Q/J5aqiTEDfiCM7uJ6WHxTM6lcCqHQBISk2dQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.8", @@ -4060,8 +3777,6 @@ }, "node_modules/@react-stately/table": { "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.15.1.tgz", - "integrity": "sha512-MhMAgE/LgAzHcAn1P3p/nQErzJ6DiixSJ1AOt2JlnAKEb5YJg4ATKWCb2IjBLwywt9ZCzfm3KMUzkctZqAoxwA==", "license": "Apache-2.0", "dependencies": { "@react-stately/collections": "^3.12.8", @@ -4080,8 +3795,6 @@ }, "node_modules/@react-stately/tabs": { "version": "3.8.6", - "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.8.6.tgz", - "integrity": "sha512-9RYxmgjVIxUpIsGKPIF7uRoHWOEz8muwaYiStCVeyiYBPmarvZoIYtTXcwSMN/vEs7heVN5uGCL6/bfdY4+WiA==", "license": "Apache-2.0", "dependencies": { "@react-stately/list": "^3.13.1", @@ -4095,8 +3808,6 @@ }, "node_modules/@react-stately/toast": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@react-stately/toast/-/toast-3.1.2.tgz", - "integrity": "sha512-HiInm7bck32khFBHZThTQaAF6e6/qm57F4mYRWdTq8IVeGDzpkbUYibnLxRhk0UZ5ybc6me+nqqPkG/lVmM42Q==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0", @@ -4108,8 +3819,6 @@ }, "node_modules/@react-stately/toggle": { "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.9.2.tgz", - "integrity": "sha512-dOxs9wrVXHUmA7lc8l+N9NbTJMAaXcYsnNGsMwfXIXQ3rdq+IjWGNYJ52UmNQyRYFcg0jrzRrU16TyGbNjOdNQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.8", @@ -4123,8 +3832,6 @@ }, "node_modules/@react-stately/tooltip": { "version": "3.5.8", - "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.5.8.tgz", - "integrity": "sha512-gkcUx2ROhCiGNAYd2BaTejakXUUNLPnnoJ5+V/mN480pN+OrO8/2V9pqb/IQmpqxLsso93zkM3A4wFHHLBBmPQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/overlays": "^3.6.20", @@ -4137,8 +3844,6 @@ }, "node_modules/@react-stately/tree": { "version": "3.9.3", - "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.9.3.tgz", - "integrity": "sha512-ZngG79nLFxE/GYmpwX6E/Rma2MMkzdoJPRI3iWk3dgqnGMMzpPnUp/cvjDsU3UHF7xDVusC5BT6pjWN0uxCIFQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/collections": "^3.12.8", @@ -4153,8 +3858,6 @@ }, "node_modules/@react-stately/utils": { "version": "3.10.8", - "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.8.tgz", - "integrity": "sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -4165,8 +3868,6 @@ }, "node_modules/@react-types/breadcrumbs": { "version": "3.7.17", - "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.17.tgz", - "integrity": "sha512-IhvVTcfli5o/UDlGACXxjlor2afGlMQA8pNR3faH0bBUay1Fmm3IWktVw9Xwmk+KraV2RTAg9e+E6p8DOQZfiw==", "license": "Apache-2.0", "dependencies": { "@react-types/link": "^3.6.5", @@ -4178,8 +3879,6 @@ }, "node_modules/@react-types/button": { "version": "3.14.1", - "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.14.1.tgz", - "integrity": "sha512-D8C4IEwKB7zEtiWYVJ3WE/5HDcWlze9mLWQ5hfsBfpePyWCgO3bT/+wjb/7pJvcAocrkXo90QrMm85LcpBtrpg==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4190,8 +3889,6 @@ }, "node_modules/@react-types/calendar": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.8.0.tgz", - "integrity": "sha512-ZDZgfZgbz1ydWOFs1mH7QFfX3ioJrmb3Y/lkoubQE0HWXLZzyYNvhhKyFJRS1QJ40IofLSBHriwbQb/tsUnGlw==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.10.0", @@ -4203,8 +3900,6 @@ }, "node_modules/@react-types/checkbox": { "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.10.2.tgz", - "integrity": "sha512-ktPkl6ZfIdGS1tIaGSU/2S5Agf2NvXI9qAgtdMDNva0oLyAZ4RLQb6WecPvofw1J7YKXu0VA5Mu7nlX+FM2weQ==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4215,8 +3910,6 @@ }, "node_modules/@react-types/color": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@react-types/color/-/color-3.1.2.tgz", - "integrity": "sha512-NP0TAY3j4tlMztOp/bBfMlPwC9AQKTjSiTFmc2oQNkx5M4sl3QpPqFPosdt7jZ8M4nItvfCWZrlZGjST4SB83A==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1", @@ -4228,8 +3921,6 @@ }, "node_modules/@react-types/combobox": { "version": "3.13.9", - "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.13.9.tgz", - "integrity": "sha512-G6GmLbzVkLW6VScxPAr/RtliEyPhBClfYaIllK1IZv+Z42SVnOpKzhnoe79BpmiFqy1AaC3+LjZX783mrsHCwA==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4240,8 +3931,6 @@ }, "node_modules/@react-types/datepicker": { "version": "3.13.2", - "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.13.2.tgz", - "integrity": "sha512-+M6UZxJnejYY8kz0spbY/hP08QJ5rsZ3aNarRQQHc48xV2oelFLX5MhAqizfLEsvyfb0JYrhWoh4z1xZtAmYCg==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.10.0", @@ -4255,8 +3944,6 @@ }, "node_modules/@react-types/dialog": { "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.22.tgz", - "integrity": "sha512-smSvzOcqKE196rWk0oqJDnz+ox5JM5+OT0PmmJXiUD4q7P5g32O6W5Bg7hMIFUI9clBtngo8kLaX2iMg+GqAzg==", "license": "Apache-2.0", "dependencies": { "@react-types/overlays": "^3.9.2", @@ -4268,8 +3955,6 @@ }, "node_modules/@react-types/grid": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.3.6.tgz", - "integrity": "sha512-vIZJlYTii2n1We9nAugXwM2wpcpsC6JigJFBd6vGhStRdRWRoU4yv1Gc98Usbx0FQ/J7GLVIgeG8+1VMTKBdxw==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4280,8 +3965,6 @@ }, "node_modules/@react-types/link": { "version": "3.6.5", - "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.6.5.tgz", - "integrity": "sha512-+I2s3XWBEvLrzts0GnNeA84mUkwo+a7kLUWoaJkW0TOBDG7my95HFYxF9WnqKye7NgpOkCqz4s3oW96xPdIniQ==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4292,8 +3975,6 @@ }, "node_modules/@react-types/listbox": { "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.7.4.tgz", - "integrity": "sha512-p4YEpTl/VQGrqVE8GIfqTS5LkT5jtjDTbVeZgrkPnX/fiPhsfbTPiZ6g0FNap4+aOGJFGEEZUv2q4vx+rCORww==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4304,8 +3985,6 @@ }, "node_modules/@react-types/menu": { "version": "3.10.5", - "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.10.5.tgz", - "integrity": "sha512-HBTrKll2hm0VKJNM4ubIv1L9MNo8JuOnm2G3M+wXvb6EYIyDNxxJkhjsqsGpUXJdAOSkacHBDcNh2HsZABNX4A==", "license": "Apache-2.0", "dependencies": { "@react-types/overlays": "^3.9.2", @@ -4317,8 +3996,6 @@ }, "node_modules/@react-types/meter": { "version": "3.4.13", - "resolved": "https://registry.npmjs.org/@react-types/meter/-/meter-3.4.13.tgz", - "integrity": "sha512-EiarfbpHcvmeyXvXcr6XLaHkNHuGc4g7fBVEiDPwssFJKKfbUzqnnknDxPjyspqUVRcXC08CokS98J1jYobqDg==", "license": "Apache-2.0", "dependencies": { "@react-types/progress": "^3.5.16" @@ -4329,8 +4006,6 @@ }, "node_modules/@react-types/numberfield": { "version": "3.8.15", - "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.15.tgz", - "integrity": "sha512-97r92D23GKCOjGIGMeW9nt+/KlfM3GeWH39Czcmd2/D5y3k6z4j0avbsfx2OttCtJszrnENjw3GraYGYI2KosQ==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4341,8 +4016,6 @@ }, "node_modules/@react-types/overlays": { "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.9.2.tgz", - "integrity": "sha512-Q0cRPcBGzNGmC8dBuHyoPR7N3057KTS5g+vZfQ53k8WwmilXBtemFJPLsogJbspuewQ/QJ3o2HYsp2pne7/iNw==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4353,8 +4026,6 @@ }, "node_modules/@react-types/progress": { "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.16.tgz", - "integrity": "sha512-I9tSdCFfvQ7gHJtm90VAKgwdTWXQgVNvLRStEc0z9h+bXBxdvZb+QuiRPERChwFQ9VkK4p4rDqaFo69nDqWkpw==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4365,8 +4036,6 @@ }, "node_modules/@react-types/radio": { "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.9.2.tgz", - "integrity": "sha512-3UcJXu37JrTkRyP4GJPDBU7NmDTInrEdOe+bVzA1j4EegzdkJmLBkLg5cLDAbpiEHB+xIsvbJdx6dxeMuc+H3g==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4377,8 +4046,6 @@ }, "node_modules/@react-types/searchfield": { "version": "3.6.6", - "resolved": "https://registry.npmjs.org/@react-types/searchfield/-/searchfield-3.6.6.tgz", - "integrity": "sha512-cl3itr/fk7wbIQc2Gz5Ie8aVeUmPjVX/mRGS5/EXlmzycAKNYTvqf2mlxwObLndtLISmt7IgNjRRhbUUDI8Ang==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1", @@ -4390,8 +4057,6 @@ }, "node_modules/@react-types/select": { "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.11.0.tgz", - "integrity": "sha512-SzIsMFVPCbXE1Z1TLfpdfiwJ1xnIkcL1/CjGilmUKkNk5uT7rYX1xCJqWCjXI0vAU1xM4Qn+T3n8de4fw6HRBg==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4402,8 +4067,6 @@ }, "node_modules/@react-types/shared": { "version": "3.32.1", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", - "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -4411,8 +4074,6 @@ }, "node_modules/@react-types/slider": { "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.8.2.tgz", - "integrity": "sha512-MQYZP76OEOYe7/yA2To+Dl0LNb0cKKnvh5JtvNvDnAvEprn1RuLiay8Oi/rTtXmc2KmBa4VdTcsXsmkbbkeN2Q==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4423,8 +4084,6 @@ }, "node_modules/@react-types/switch": { "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.15.tgz", - "integrity": "sha512-r/ouGWQmIeHyYSP1e5luET+oiR7N7cLrAlWsrAfYRWHxqXOSNQloQnZJ3PLHrKFT02fsrQhx2rHaK2LfKeyN3A==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4435,8 +4094,6 @@ }, "node_modules/@react-types/table": { "version": "3.13.4", - "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.13.4.tgz", - "integrity": "sha512-I/DYiZQl6aNbMmjk90J9SOhkzVDZvyA3Vn3wMWCiajkMNjvubFhTfda5DDf2SgFP5l0Yh6TGGH5XumRv9LqL5Q==", "license": "Apache-2.0", "dependencies": { "@react-types/grid": "^3.3.6", @@ -4448,8 +4105,6 @@ }, "node_modules/@react-types/tabs": { "version": "3.3.19", - "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.19.tgz", - "integrity": "sha512-fE+qI43yR5pAMpeqPxGqQq9jDHXEPqXskuxNHERMW0PYMdPyem2Cw6goc5F4qeZO3Hf6uPZgHkvJz2OAq7TbBw==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4460,8 +4115,6 @@ }, "node_modules/@react-types/textfield": { "version": "3.12.6", - "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.12.6.tgz", - "integrity": "sha512-hpEVKE+M3uUkTjw2WrX1NrH/B3rqDJFUa+ViNK2eVranLY4ZwFqbqaYXSzHupOF3ecSjJJv2C103JrwFvx6TPQ==", "license": "Apache-2.0", "dependencies": { "@react-types/shared": "^3.32.1" @@ -4472,8 +4125,6 @@ }, "node_modules/@react-types/tooltip": { "version": "3.4.21", - "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.21.tgz", - "integrity": "sha512-ugGHOZU6WbOdeTdbjnaEc+Ms7/WhsUCg+T3PCOIeOT9FG02Ce189yJ/+hd7oqL/tVwIhEMYJIqSCgSELFox+QA==", "license": "Apache-2.0", "dependencies": { "@react-types/overlays": "^3.9.2", @@ -4570,6 +4221,9 @@ "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4586,6 +4240,9 @@ "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4602,6 +4259,9 @@ "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4618,6 +4278,9 @@ "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4629,11 +4292,12 @@ }, "node_modules/@rolldown/binding-linux-x64-gnu": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", - "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -4645,11 +4309,12 @@ }, "node_modules/@rolldown/binding-linux-x64-musl": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", - "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -4727,18 +4392,16 @@ }, "node_modules/@rolldown/pluginutils": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", - "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.5.0.tgz", + "integrity": "sha512-6CIgwq+bt2JZ3OSjb/nBkkwEf/CfpHcbam+Mg5Pllco7HAGRQ2/EFhZrrJtbyNTgKwknfVS+llsXGygiDGwJWw==", "license": "MIT", "dependencies": { - "@shikijs/primitive": "4.4.3", - "@shikijs/types": "4.4.3", + "@shikijs/primitive": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" @@ -4748,12 +4411,12 @@ } }, "node_modules/@shikijs/engine-javascript": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", - "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.5.0.tgz", + "integrity": "sha512-Ed6UdEj84LyYkwnxM5CvSMWAD+id9ExTYri0/+x41U9zrgNifPSS9lZm0JqBP0VfYI8yr8tY5nbNq9+p9R0kFA==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" }, @@ -4762,12 +4425,12 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", - "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.5.0.tgz", + "integrity": "sha512-dKVmbJecVdB9recl8a/CU4jdpNXyjJQrIcesIkpS70s5HS02ohpnCSpMUbotPnEUzbAcLQ+S4hwZYbkBBiTcJw==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2" }, "engines": { @@ -4775,24 +4438,24 @@ } }, "node_modules/@shikijs/langs": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", - "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.5.0.tgz", + "integrity": "sha512-wwBTqwduXSz0X4v9Qa2EWeFaYJEw1clCncWjoRNQRbVDu3SPRTRWucnouYapKj3b8Q+sk/41Vbc4B5c8nuYzLA==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/primitive": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", - "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.5.0.tgz", + "integrity": "sha512-UM7ShlA8oz0OWxLLO8BmO9Ip6fVqdkt8yF0EH7nOCqHfrx1eEAzF0ZUVK7L+I8NEgeu1PEWSRlxaiPPeCb4iDg==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" }, @@ -4801,21 +4464,21 @@ } }, "node_modules/@shikijs/themes": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", - "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.5.0.tgz", + "integrity": "sha512-zGb87H3UBbpuI4yoh5UguB1XbU+2BDU3kflM7UfZ+Cy2hWo9lBtqjSVK20gmLY6ukYl040hAypGXMgud9vul8Q==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.4.3" + "@shikijs/types": "4.5.0" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", - "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.5.0.tgz", + "integrity": "sha512-drtPrtD8N0DENyD2cyt6Ajy+IWsiCLgMxODwLTpvH1UsN6a9jf90tNTPjqwHvA+0Lzu9e0txk8DjfqH1p9UJRw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -4827,14 +4490,10 @@ }, "node_modules/@shikijs/vscode-textmate": { "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", "license": "MIT" }, "node_modules/@swc/helpers": { "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -4842,8 +4501,6 @@ }, "node_modules/@tailwindcss/container-queries": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/container-queries/-/container-queries-0.1.1.tgz", - "integrity": "sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==", "license": "MIT", "peerDependencies": { "tailwindcss": ">=3.2.0" @@ -4851,8 +4508,6 @@ }, "node_modules/@tailwindcss/node": { "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", - "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", @@ -4866,8 +4521,6 @@ }, "node_modules/@tailwindcss/oxide": { "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", - "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", "license": "MIT", "engines": { "node": ">= 20" @@ -5007,8 +4660,6 @@ }, "node_modules/@tailwindcss/oxide-linux-x64-gnu": { "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", - "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", "cpu": [ "x64" ], @@ -5106,8 +4757,6 @@ }, "node_modules/@tailwindcss/vite": { "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", - "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", "license": "MIT", "dependencies": { "@tailwindcss/node": "4.3.3", @@ -5120,8 +4769,6 @@ }, "node_modules/@tanstack/query-core": { "version": "5.90.7", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.7.tgz", - "integrity": "sha512-6PN65csiuTNfBMXqQUxQhCNdtm1rV+9kC9YwWAIKcaxAauq3Wu7p18j3gQY3YIBJU70jT/wzCCZ2uqto/vQgiQ==", "license": "MIT", "funding": { "type": "github", @@ -5130,8 +4777,6 @@ }, "node_modules/@tanstack/query-devtools": { "version": "5.90.1", - "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.90.1.tgz", - "integrity": "sha512-GtINOPjPUH0OegJExZ70UahT9ykmAhmtNVcmtdnOZbxLwT7R5OmRztR5Ahe3/Cu7LArEmR6/588tAycuaWb1xQ==", "license": "MIT", "funding": { "type": "github", @@ -5140,8 +4785,6 @@ }, "node_modules/@tanstack/react-query": { "version": "5.90.7", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.7.tgz", - "integrity": "sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ==", "license": "MIT", "dependencies": { "@tanstack/query-core": "5.90.7" @@ -5156,8 +4799,6 @@ }, "node_modules/@tanstack/react-query-devtools": { "version": "5.90.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.90.2.tgz", - "integrity": "sha512-vAXJzZuBXtCQtrY3F/yUNJCV4obT/A/n81kb3+YqLbro5Z2+phdAbceO+deU3ywPw8B42oyJlp4FhO0SoivDFQ==", "license": "MIT", "dependencies": { "@tanstack/query-devtools": "5.90.1" @@ -5173,8 +4814,6 @@ }, "node_modules/@tanstack/react-table": { "version": "8.20.5", - "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz", - "integrity": "sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==", "license": "MIT", "dependencies": { "@tanstack/table-core": "8.20.5" @@ -5193,8 +4832,6 @@ }, "node_modules/@tanstack/react-virtual": { "version": "3.13.12", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", - "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", "license": "MIT", "dependencies": { "@tanstack/virtual-core": "3.13.12" @@ -5210,8 +4847,6 @@ }, "node_modules/@tanstack/table-core": { "version": "8.20.5", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz", - "integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==", "license": "MIT", "engines": { "node": ">=12" @@ -5223,8 +4858,6 @@ }, "node_modules/@tanstack/virtual-core": { "version": "3.13.12", - "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", - "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", "license": "MIT", "funding": { "type": "github", @@ -5232,9 +4865,9 @@ } }, "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", "license": "MIT", "optional": true, "dependencies": { @@ -5243,8 +4876,6 @@ }, "node_modules/@types/chai": { "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { @@ -5254,37 +4885,27 @@ }, "node_modules/@types/cookie": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "dev": true, "license": "MIT" }, "node_modules/@types/deep-eql": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/esrecurse": { "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", - "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/@types/estree": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, "node_modules/@types/hast": { "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.5.tgz", - "integrity": "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==", "license": "MIT", "dependencies": { "@types/unist": "*" @@ -5292,21 +4913,15 @@ }, "node_modules/@types/json-schema": { "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/@types/lodash": { "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", "license": "MIT" }, "node_modules/@types/lodash-es": { "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", - "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "license": "MIT", "dependencies": { "@types/lodash": "*" @@ -5314,8 +4929,6 @@ }, "node_modules/@types/lodash.throttle": { "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/lodash.throttle/-/lodash.throttle-4.1.9.tgz", - "integrity": "sha512-PCPVfpfueguWZQB7pJQK890F2scYKoDUL3iM522AptHWn7d5NQmeS/LTEHIcLr5PaTzl3dK2Z0xSUHHTHwaL5g==", "dev": true, "license": "MIT", "dependencies": { @@ -5324,8 +4937,6 @@ }, "node_modules/@types/md5": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.5.tgz", - "integrity": "sha512-/i42wjYNgE6wf0j2bcTX6kuowmdL/6PE4IVitMpm2eYKBUuYCprdcWVK+xEF0gcV6ufMCRhtxmReGfc6hIK7Jw==", "dev": true, "license": "MIT" }, @@ -5340,15 +4951,11 @@ }, "node_modules/@types/mousetrap": { "version": "1.6.15", - "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.15.tgz", - "integrity": "sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { "version": "25.6.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", - "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "devOptional": true, "license": "MIT", "peer": true, @@ -5358,8 +4965,6 @@ }, "node_modules/@types/react": { "version": "19.2.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", - "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "devOptional": true, "license": "MIT", "dependencies": { @@ -5368,8 +4973,6 @@ }, "node_modules/@types/react-dom": { "version": "19.2.2", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", - "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "devOptional": true, "license": "MIT", "peerDependencies": { @@ -5378,8 +4981,6 @@ }, "node_modules/@types/react-is": { "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-19.2.0.tgz", - "integrity": "sha512-NP2xtcjZfORsOa4g2JwdseyEnF+wUCx25fTdG/J/HIY6yKga6+NozRBg2xR2gyh7kKYyd6DXndbq0YbQuTJ7Ew==", "dev": true, "license": "MIT", "dependencies": { @@ -5388,41 +4989,29 @@ }, "node_modules/@types/retry": { "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "license": "MIT" }, "node_modules/@types/semver": { "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "dev": true, "license": "MIT" }, "node_modules/@types/statuses": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", - "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", "dev": true, "license": "MIT" }, "node_modules/@types/tough-cookie": { "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true, "license": "MIT" }, "node_modules/@types/unist": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, "node_modules/@types/uuid": { "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "dev": true, "license": "MIT" }, @@ -5632,8 +5221,6 @@ }, "node_modules/@typescript/typescript-linux-x64": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", - "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", "cpu": [ "x64" ], @@ -5774,8 +5361,6 @@ }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.3.0.tgz", - "integrity": "sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ==", "dev": true, "license": "MIT", "engines": { @@ -5787,8 +5372,6 @@ }, "node_modules/@vitejs/plugin-react": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.2.tgz", - "integrity": "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==", "dev": true, "license": "MIT", "dependencies": { @@ -5813,8 +5396,6 @@ }, "node_modules/@vitest/browser": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-5.0.0.tgz", - "integrity": "sha512-JC9FG5xIRxPHXJPcdCaluIJcEoeM0IwGQ3xneuJk09LXKHRNs40BqWDWymQikbb20yOpYvzpKzmYgPRuSzKmvg==", "dev": true, "license": "MIT", "dependencies": { @@ -5837,8 +5418,6 @@ }, "node_modules/@vitest/browser-playwright": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-5.0.0.tgz", - "integrity": "sha512-N+gED9y4/8pypaHjz/x0ah3CjoBr+N0hWWT+Gq4VXtMzyB+rUIdHni0ulzpD1j4H77iWy5Jg8PRMlVn6kjxo6g==", "dev": true, "license": "MIT", "dependencies": { @@ -5861,8 +5440,6 @@ }, "node_modules/@vitest/browser/node_modules/magic-string": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz", - "integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==", "dev": true, "license": "MIT", "dependencies": { @@ -5871,8 +5448,6 @@ }, "node_modules/@vitest/mocker": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.0.tgz", - "integrity": "sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==", "dev": true, "license": "MIT", "dependencies": { @@ -5899,8 +5474,6 @@ }, "node_modules/@vitest/mocker/node_modules/magic-string": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz", - "integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==", "dev": true, "license": "MIT", "dependencies": { @@ -5909,8 +5482,6 @@ }, "node_modules/@vitest/pretty-format": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-5.0.0.tgz", - "integrity": "sha512-PVRNuB3wpReb4SQEs4zTKM4KWFhQ5pw3spE8naoDJNB5T5aWRzGKHwXcLUllr0WeOTXpB6bSr3CJLo5+7XQSSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5922,8 +5493,6 @@ }, "node_modules/@vitest/spy": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.0.tgz", - "integrity": "sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==", "dev": true, "license": "MIT", "funding": { @@ -5932,8 +5501,6 @@ }, "node_modules/@vitest/ui": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-5.0.0.tgz", - "integrity": "sha512-h2FIFwggCY2GxUd2UdQoYNVQkOIqEQLPhNREcl3FUiRsdzQep7NWwYbSmhGEA9nFLPDq5pXzRMcBZQU8Py83sg==", "dev": true, "license": "MIT", "dependencies": { @@ -5953,8 +5520,6 @@ }, "node_modules/@vitest/utils": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-5.0.0.tgz", - "integrity": "sha512-dO++xL3vDfvhTAVimfkuQUA3k+JClIF1i1vAkPqpcGAthRmeWnXmHB7YPViPvgCwviX8u7Y5W1u2N//AaQr3fw==", "dev": true, "license": "MIT", "dependencies": { @@ -5968,14 +5533,10 @@ }, "node_modules/@xterm/addon-fit": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.11.0.tgz", - "integrity": "sha512-jYcgT6xtVYhnhgxh3QgYDnnNMYTcf8ElbxxFzX0IZo+vabQqSPAjC3c1wJrKB5E19VwQei89QCiZZP86DCPF7g==", "license": "MIT" }, "node_modules/@xterm/xterm": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-6.0.0.tgz", - "integrity": "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg==", "license": "MIT", "workspaces": [ "addons/*" @@ -5983,15 +5544,11 @@ }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", "dev": true, "license": "BSD-2-Clause" }, "node_modules/accepts": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dev": true, "license": "MIT", "dependencies": { @@ -6004,8 +5561,6 @@ }, "node_modules/acorn": { "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "peer": true, @@ -6018,8 +5573,6 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peer": true, @@ -6029,8 +5582,6 @@ }, "node_modules/ajv": { "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "peer": true, @@ -6047,8 +5598,6 @@ }, "node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { @@ -6057,22 +5606,16 @@ }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true, "license": "MIT" }, "node_modules/asn1js": { "version": "3.0.10", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", - "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", "license": "BSD-3-Clause", "dependencies": { "pvtsutils": "^1.3.6", @@ -6085,8 +5628,6 @@ }, "node_modules/assertion-error": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { @@ -6095,8 +5636,6 @@ }, "node_modules/balanced-match": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "peer": true, @@ -6106,8 +5645,6 @@ }, "node_modules/body-parser": { "version": "1.20.8", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.8.tgz", - "integrity": "sha512-JNcyFQ64OiijEkPzUBTCe+hyPXUD/3LEldGQ6iF5LR1w00mx9o7xtDWHXBY2iItjdCFGoilOLNQbH943ut7pHA==", "dev": true, "license": "MIT", "dependencies": { @@ -6131,8 +5668,6 @@ }, "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -6141,8 +5676,6 @@ }, "node_modules/body-parser/node_modules/http-errors": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6162,15 +5695,11 @@ }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/body-parser/node_modules/qs": { "version": "6.16.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz", - "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -6186,8 +5715,6 @@ }, "node_modules/body-parser/node_modules/statuses": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { @@ -6196,8 +5723,6 @@ }, "node_modules/brace-expansion": { "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "peer": true, @@ -6210,8 +5735,6 @@ }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { @@ -6223,8 +5746,6 @@ }, "node_modules/bytes": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", "engines": { @@ -6233,8 +5754,6 @@ }, "node_modules/cac": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cac/-/cac-7.0.0.tgz", - "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", "dev": true, "license": "MIT", "engines": { @@ -6243,8 +5762,6 @@ }, "node_modules/call-bind": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "license": "MIT", "dependencies": { @@ -6262,8 +5779,6 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6276,8 +5791,6 @@ }, "node_modules/call-bound": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { @@ -6293,8 +5806,6 @@ }, "node_modules/call-me-maybe": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", "dev": true, "license": "MIT" }, @@ -6310,8 +5821,6 @@ }, "node_modules/chai": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", "engines": { @@ -6340,8 +5849,6 @@ }, "node_modules/charenc": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "license": "BSD-3-Clause", "engines": { "node": "*" @@ -6349,8 +5856,6 @@ }, "node_modules/ci-info": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -6365,14 +5870,10 @@ }, "node_modules/classnames": { "version": "2.5.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", - "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", "license": "MIT" }, "node_modules/cli-width": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "dev": true, "license": "ISC", "engines": { @@ -6381,8 +5882,6 @@ }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "license": "ISC", "dependencies": { @@ -6396,8 +5895,6 @@ }, "node_modules/cliui/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -6412,8 +5909,6 @@ }, "node_modules/cliui/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6425,22 +5920,16 @@ }, "node_modules/cliui/node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/cliui/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { @@ -6449,8 +5938,6 @@ }, "node_modules/cliui/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -6464,8 +5951,6 @@ }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -6482,8 +5967,6 @@ }, "node_modules/clsx": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", "engines": { "node": ">=6" @@ -6501,8 +5984,6 @@ }, "node_modules/commander": { "version": "14.0.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", - "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, "license": "MIT", "peer": true, @@ -6512,8 +5993,6 @@ }, "node_modules/content-disposition": { "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6525,8 +6004,6 @@ }, "node_modules/content-type": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "license": "MIT", "engines": { @@ -6535,15 +6012,11 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/cookie": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "dev": true, "license": "MIT", "engines": { @@ -6552,21 +6025,19 @@ }, "node_modules/cookie-es": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-3.1.1.tgz", - "integrity": "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==", "license": "MIT" }, "node_modules/cookie-signature": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true, "license": "MIT" }, + "node_modules/crelt": { + "version": "1.0.7", + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { @@ -6580,8 +6051,6 @@ }, "node_modules/crypt": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "license": "BSD-3-Clause", "engines": { "node": "*" @@ -6589,15 +6058,11 @@ }, "node_modules/csstype": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "devOptional": true, "license": "MIT" }, "node_modules/date-fns": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", "license": "MIT", "funding": { "type": "github", @@ -6606,8 +6071,6 @@ }, "node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "peer": true, @@ -6625,22 +6088,16 @@ }, "node_modules/decimal.js": { "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "license": "MIT" }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT", "peer": true }, "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { @@ -6657,8 +6114,6 @@ }, "node_modules/depd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", "engines": { @@ -6676,8 +6131,6 @@ }, "node_modules/destroy": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", "engines": { @@ -6687,8 +6140,6 @@ }, "node_modules/detect-libc": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -6709,8 +6160,6 @@ }, "node_modules/dom-serializer": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "license": "MIT", "peer": true, "dependencies": { @@ -6724,8 +6173,6 @@ }, "node_modules/dom-serializer/node_modules/entities": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", "peer": true, "engines": { @@ -6737,8 +6184,6 @@ }, "node_modules/domelementtype": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "funding": [ { "type": "github", @@ -6750,8 +6195,6 @@ }, "node_modules/domhandler": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "license": "BSD-2-Clause", "peer": true, "dependencies": { @@ -6766,8 +6209,6 @@ }, "node_modules/domutils": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "license": "BSD-2-Clause", "peer": true, "dependencies": { @@ -6781,8 +6222,6 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "license": "MIT", "dependencies": { @@ -6796,15 +6235,11 @@ }, "node_modules/ee-first": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { @@ -6813,8 +6248,6 @@ }, "node_modules/enhanced-resolve": { "version": "5.24.5", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", - "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -6826,8 +6259,6 @@ }, "node_modules/entities": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "license": "BSD-2-Clause", "peer": true, "engines": { @@ -6839,8 +6270,6 @@ }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", "engines": { @@ -6849,8 +6278,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", "engines": { @@ -6859,15 +6286,11 @@ }, "node_modules/es-module-lexer": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", - "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", "dependencies": { @@ -6879,8 +6302,6 @@ }, "node_modules/escalade": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -6889,15 +6310,11 @@ }, "node_modules/escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "peer": true, @@ -6910,8 +6327,6 @@ }, "node_modules/eslint": { "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz", - "integrity": "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==", "dev": true, "license": "MIT", "peer": true, @@ -6967,8 +6382,6 @@ }, "node_modules/eslint-plugin-playwright": { "version": "2.10.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.10.4.tgz", - "integrity": "sha512-l0V/VxyqfFbtqCTxj5AdRn3Q6S/hIW4nKBnKZVleVbZ24N2My6Usj//ytX3dKKqAoSbvKck9YtSytfdZ5qjLuA==", "dev": true, "license": "MIT", "dependencies": { @@ -6983,8 +6396,6 @@ }, "node_modules/eslint-plugin-react-hook-form": { "version": "0.3.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hook-form/-/eslint-plugin-react-hook-form-0.3.1.tgz", - "integrity": "sha512-+KHoQvjGa6gxxDaVTDPXmqOL+tJ2fWTBggBQTafoVTTe41xLnq94+ZXpb7oTDDRMP97UN908iIX3mNwQqnRxHw==", "dev": true, "license": "MIT", "dependencies": { @@ -6996,8 +6407,6 @@ }, "node_modules/eslint-scope": { "version": "9.1.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", - "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -7016,8 +6425,6 @@ }, "node_modules/eslint-visitor-keys": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -7030,8 +6437,6 @@ }, "node_modules/espree": { "version": "11.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", - "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -7049,8 +6454,6 @@ }, "node_modules/esquery": { "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "peer": true, @@ -7063,8 +6466,6 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -7077,8 +6478,6 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -7088,8 +6487,6 @@ }, "node_modules/estree-walker": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { @@ -7098,8 +6495,6 @@ }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -7109,8 +6504,6 @@ }, "node_modules/etag": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", "engines": { @@ -7119,8 +6512,6 @@ }, "node_modules/expect-type": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", - "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -7129,8 +6520,6 @@ }, "node_modules/express": { "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, "license": "MIT", "dependencies": { @@ -7176,8 +6565,6 @@ }, "node_modules/express/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -7186,46 +6573,34 @@ }, "node_modules/express/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT", "peer": true }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/fflate": { "version": "0.8.3", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", - "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", "dev": true, "license": "MIT" }, "node_modules/file-entry-cache": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "peer": true, @@ -7238,8 +6613,6 @@ }, "node_modules/filesize": { "version": "10.1.6", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", - "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", "license": "BSD-3-Clause", "engines": { "node": ">= 10.4.0" @@ -7247,8 +6620,6 @@ }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { @@ -7260,8 +6631,6 @@ }, "node_modules/finalhandler": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7279,8 +6648,6 @@ }, "node_modules/finalhandler/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -7289,15 +6656,11 @@ }, "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "peer": true, @@ -7314,8 +6677,6 @@ }, "node_modules/find-yarn-workspace-root": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7324,8 +6685,6 @@ }, "node_modules/flat-cache": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "peer": true, @@ -7339,15 +6698,11 @@ }, "node_modules/flatted": { "version": "3.4.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", - "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", "dev": true, "license": "ISC" }, "node_modules/forwarded": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, "license": "MIT", "engines": { @@ -7356,8 +6711,6 @@ }, "node_modules/framer-motion": { "version": "11.18.2", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", - "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==", "license": "MIT", "dependencies": { "motion-dom": "^11.18.1", @@ -7383,8 +6736,6 @@ }, "node_modules/fresh": { "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, "license": "MIT", "engines": { @@ -7393,8 +6744,6 @@ }, "node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7408,15 +6757,14 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "license": "ISC", "peer": true }, "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -7429,8 +6777,6 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", "funding": { @@ -7439,8 +6785,6 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "license": "ISC", "engines": { @@ -7449,8 +6793,6 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7474,8 +6816,6 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", "dependencies": { @@ -7488,9 +6828,6 @@ }, "node_modules/glob": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", "peer": true, "dependencies": { @@ -7509,8 +6846,6 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "peer": true, @@ -7523,15 +6858,11 @@ }, "node_modules/glob/node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT", "peer": true }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "license": "MIT", "peer": true, "dependencies": { @@ -7540,8 +6871,6 @@ }, "node_modules/glob/node_modules/minimatch": { "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "license": "ISC", "peer": true, "dependencies": { @@ -7553,8 +6882,6 @@ }, "node_modules/globals": { "version": "17.6.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", - "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", "dev": true, "license": "MIT", "engines": { @@ -7566,8 +6893,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", "engines": { @@ -7579,14 +6904,10 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/graphql": { "version": "16.9.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", - "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", "dev": true, "license": "MIT", "engines": { @@ -7595,8 +6916,6 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { @@ -7608,8 +6927,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", "engines": { @@ -7621,8 +6938,6 @@ }, "node_modules/hasown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7670,15 +6985,11 @@ }, "node_modules/headers-polyfill": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", - "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", "dev": true, "license": "MIT" }, "node_modules/html-dom-parser": { "version": "5.1.8", - "resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-5.1.8.tgz", - "integrity": "sha512-MCIUng//mF2qTtGHXJWr6OLfHWmg3Pm8ezpfiltF83tizPWY17JxT4dRLE8lykJ5bChJELoY3onQKPbufJHxYA==", "funding": [ { "type": "github", @@ -7694,8 +7005,6 @@ }, "node_modules/html-react-parser": { "version": "5.2.17", - "resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-5.2.17.tgz", - "integrity": "sha512-m+K/7Moq1jodAB4VL0RXSOmtwLUYoAsikZhwd+hGQe5Vtw2dbWfpFd60poxojMU0Tsh9w59mN1QLEcoHz0Dx9w==", "funding": [ { "type": "github", @@ -7736,8 +7045,6 @@ }, "node_modules/htmlparser2": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -7756,8 +7063,6 @@ }, "node_modules/htmlparser2/node_modules/entities": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "license": "BSD-2-Clause", "peer": true, "engines": { @@ -7769,8 +7074,6 @@ }, "node_modules/http-errors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7786,8 +7089,6 @@ }, "node_modules/husky": { "version": "9.1.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { @@ -7802,8 +7103,6 @@ }, "node_modules/iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", "dependencies": { @@ -7815,8 +7114,6 @@ }, "node_modules/ignore": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "peer": true, @@ -7826,8 +7123,6 @@ }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "peer": true, @@ -7837,9 +7132,6 @@ }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "license": "ISC", "peer": true, "dependencies": { @@ -7849,21 +7141,15 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/inline-style-parser": { "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT", "peer": true }, "node_modules/intl-messageformat": { "version": "10.7.17", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.17.tgz", - "integrity": "sha512-0Ugaf65B2J76rb31drgNF1l6bGEDkbIiYc2Glx6jaZINHnwa5kDRGy8KXYuA+/8P4G0c9prAFhfVhQJJfzUuvQ==", "license": "BSD-3-Clause", "dependencies": { "@formatjs/ecma402-abstract": "2.3.5", @@ -7874,15 +7160,11 @@ }, "node_modules/ip-num": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ip-num/-/ip-num-1.5.1.tgz", - "integrity": "sha512-QziFxgxq3mjIf5CuwlzXFYscHxgLqdEdJKRo2UJ5GurL5zrSRMzT/O+nK0ABimoFH8MWF8YwIiwECYsHc1LpUQ==", "dev": true, "license": "MIT" }, "node_modules/ipaddr.js": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "license": "MIT", "engines": { @@ -7891,14 +7173,10 @@ }, "node_modules/is-buffer": { "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "license": "MIT" }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "peer": true, @@ -7908,8 +7186,6 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "peer": true, @@ -7922,8 +7198,6 @@ }, "node_modules/is-network-error": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", "license": "MIT", "engines": { "node": ">=16" @@ -7934,15 +7208,11 @@ }, "node_modules/is-node-process": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", - "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", "dev": true, "license": "MIT" }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { @@ -7951,22 +7221,16 @@ }, "node_modules/isarray": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/jiti": { "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -7974,8 +7238,6 @@ }, "node_modules/js-yaml": { "version": "4.3.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", - "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "dev": true, "funding": [ { @@ -7997,24 +7259,18 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT", "peer": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT", "peer": true }, "node_modules/json-stable-stringify": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz", - "integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==", "dev": true, "license": "MIT", "dependencies": { @@ -8032,16 +7288,12 @@ }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/jsonfile": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8053,8 +7305,6 @@ }, "node_modules/jsonify": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", "dev": true, "license": "Public Domain", "funding": { @@ -8063,8 +7313,6 @@ }, "node_modules/keyv": { "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "peer": true, @@ -8074,8 +7322,6 @@ }, "node_modules/klaw-sync": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8084,8 +7330,6 @@ }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "peer": true, @@ -8099,8 +7343,6 @@ }, "node_modules/lightningcss": { "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -8233,6 +7475,9 @@ "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8253,6 +7498,9 @@ "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8268,11 +7516,12 @@ }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8288,11 +7537,12 @@ }, "node_modules/lightningcss-linux-x64-musl": { "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -8348,8 +7598,6 @@ }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "peer": true, @@ -8365,40 +7613,28 @@ }, "node_modules/lodash": { "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash-es": { "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", - "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "license": "MIT" }, "node_modules/lodash.get": { "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true, "license": "MIT" }, "node_modules/lodash.isequal": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", "dev": true, "license": "MIT" }, "node_modules/lodash.throttle": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", "license": "MIT" }, "node_modules/magic-string": { "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -8406,8 +7642,6 @@ }, "node_modules/match-sorter": { "version": "6.3.4", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz", - "integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.8", @@ -8416,8 +7650,6 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", "engines": { @@ -8426,8 +7658,6 @@ }, "node_modules/md5": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "license": "BSD-3-Clause", "dependencies": { "charenc": "0.0.2", @@ -8458,8 +7688,6 @@ }, "node_modules/media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "license": "MIT", "engines": { @@ -8468,8 +7696,6 @@ }, "node_modules/merge-descriptors": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, "license": "MIT", "funding": { @@ -8478,8 +7704,6 @@ }, "node_modules/methods": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, "license": "MIT", "engines": { @@ -8560,9 +7784,9 @@ "license": "MIT" }, "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.3.tgz", + "integrity": "sha512-oxB2Ik03hI0gv+VNn9tnh1t1YEe9MDPptViAEgfdf3YQHsn0pzGTgCdlSCJXcwhqm8phaEuM7zeEu3QQzVBrPg==", "funding": [ { "type": "GitHub Sponsors", @@ -8577,8 +7801,6 @@ }, "node_modules/micromatch": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -8591,8 +7813,6 @@ }, "node_modules/mime": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, "license": "MIT", "bin": { @@ -8604,8 +7824,6 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", "engines": { @@ -8614,8 +7832,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", "dependencies": { @@ -8627,8 +7843,6 @@ }, "node_modules/minimatch": { "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "peer": true, @@ -8644,8 +7858,6 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", "funding": { @@ -8654,8 +7866,6 @@ }, "node_modules/motion": { "version": "11.16.2", - "resolved": "https://registry.npmjs.org/motion/-/motion-11.16.2.tgz", - "integrity": "sha512-Q73vRcFCLTfKdIq8CllBi72zvntKEnaFaE3Wh0y0cWxeQUAw7VymVg8eZpLADZku7SNvk4GhZJqnIVl8eGepiw==", "license": "MIT", "dependencies": { "framer-motion": "^11.16.2", @@ -8680,8 +7890,6 @@ }, "node_modules/motion-dom": { "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", - "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", "license": "MIT", "dependencies": { "motion-utils": "^11.18.1" @@ -8689,20 +7897,14 @@ }, "node_modules/motion-utils": { "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", - "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", "license": "MIT" }, "node_modules/mousetrap": { "version": "1.6.5", - "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", - "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==", "license": "Apache-2.0 WITH LLVM-exception" }, "node_modules/mrmime": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, "license": "MIT", "engines": { @@ -8711,15 +7913,11 @@ }, "node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/msw": { "version": "2.7.5", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.7.5.tgz", - "integrity": "sha512-00MyTlY3TJutBa5kiU+jWiz2z5pNJDYHn2TgPkGkh92kMmNH43RqvMXd8y/7HxNn8RjzUbvZWYZjcS36fdb6sw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -8763,15 +7961,11 @@ }, "node_modules/msw/node_modules/path-to-regexp": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "dev": true, "license": "MIT" }, "node_modules/msw/node_modules/type-fest": { "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -8783,8 +7977,6 @@ }, "node_modules/mute-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "dev": true, "license": "ISC", "engines": { @@ -8793,8 +7985,6 @@ }, "node_modules/nanoid": { "version": "3.3.18", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", - "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "funding": [ { "type": "github", @@ -8811,16 +8001,12 @@ }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/negotiator": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "license": "MIT", "engines": { @@ -8829,8 +8015,6 @@ }, "node_modules/object-inspect": { "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -8842,8 +8026,6 @@ }, "node_modules/object-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", "engines": { @@ -8852,8 +8034,6 @@ }, "node_modules/obug": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", - "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", @@ -8866,8 +8046,6 @@ }, "node_modules/on-finished": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", "dependencies": { @@ -8879,8 +8057,6 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", "peer": true, "dependencies": { @@ -8906,16 +8082,12 @@ }, "node_modules/openapi-types": { "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", "dev": true, "license": "MIT", "peer": true }, "node_modules/optionator": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "peer": true, @@ -8933,15 +8105,11 @@ }, "node_modules/outvariant": { "version": "1.4.3", - "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", - "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", "dev": true, "license": "MIT" }, "node_modules/oxfmt": { "version": "0.55.0", - "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.55.0.tgz", - "integrity": "sha512-jSj2wCTakwgPMxkfiVZX0jf+nX+Nz6xlyAZjqNE0qXTFdCBPYlP6JAN+ODjmealw7DXBjOzYbdsqwBMAZnPZ6A==", "dev": true, "license": "MIT", "dependencies": { @@ -8992,8 +8160,6 @@ }, "node_modules/oxlint": { "version": "1.70.0", - "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.70.0.tgz", - "integrity": "sha512-D6JgHtzkhRwvEC+A0Nw5AEc5bk8x5i1pHzvZIEf/a0C4hOzmAACNGtkDGPyFaxxX3ZVGxCPeig3P3rMM8XU3/g==", "dev": true, "license": "MIT", "bin": { @@ -9041,8 +8207,6 @@ }, "node_modules/oxlint-tsgolint": { "version": "0.23.0", - "resolved": "https://registry.npmjs.org/oxlint-tsgolint/-/oxlint-tsgolint-0.23.0.tgz", - "integrity": "sha512-3mBv3CoPbh8dFbzfDGIWa2ytZjn2v+3EX4aKRXjIhsoGFzG8GCjfRirz3rwZf1wYbZzsNLTSgpw8VjQuWdp/jA==", "dev": true, "license": "MIT", "bin": { @@ -9059,8 +8223,6 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "peer": true, @@ -9076,8 +8238,6 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "peer": true, @@ -9093,8 +8253,6 @@ }, "node_modules/p-map": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.2.tgz", - "integrity": "sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==", "license": "MIT", "engines": { "node": ">=18" @@ -9105,8 +8263,6 @@ }, "node_modules/p-retry": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", "license": "MIT", "dependencies": { "@types/retry": "0.12.2", @@ -9122,8 +8278,6 @@ }, "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, "license": "MIT", "engines": { @@ -9132,8 +8286,6 @@ }, "node_modules/patch-package": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", - "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", "dev": true, "license": "MIT", "dependencies": { @@ -9162,8 +8314,6 @@ }, "node_modules/patch-package/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { @@ -9178,8 +8328,6 @@ }, "node_modules/patch-package/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { @@ -9195,8 +8343,6 @@ }, "node_modules/patch-package/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9208,15 +8354,11 @@ }, "node_modules/patch-package/node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/patch-package/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { @@ -9225,8 +8367,6 @@ }, "node_modules/patch-package/node_modules/is-docker": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, "license": "MIT", "bin": { @@ -9241,8 +8381,6 @@ }, "node_modules/patch-package/node_modules/is-wsl": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "license": "MIT", "dependencies": { @@ -9254,8 +8392,6 @@ }, "node_modules/patch-package/node_modules/open": { "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "dev": true, "license": "MIT", "dependencies": { @@ -9271,8 +8407,6 @@ }, "node_modules/patch-package/node_modules/slash": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true, "license": "MIT", "engines": { @@ -9281,8 +8415,6 @@ }, "node_modules/patch-package/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { @@ -9294,8 +8426,6 @@ }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "peer": true, @@ -9305,8 +8435,6 @@ }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { @@ -9315,28 +8443,20 @@ }, "node_modules/path-to-regexp": { "version": "0.1.13", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", - "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "dev": true, "license": "MIT" }, "node_modules/pathe": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -9348,8 +8468,6 @@ }, "node_modules/playwright": { "version": "1.61.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.0.tgz", - "integrity": "sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9367,8 +8485,6 @@ }, "node_modules/playwright-core": { "version": "1.61.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.0.tgz", - "integrity": "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -9378,25 +8494,8 @@ "node": ">=18" } }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/pngjs": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", - "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", "dev": true, "license": "MIT", "engines": { @@ -9405,8 +8504,6 @@ }, "node_modules/postcss": { "version": "8.5.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", - "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", "funding": [ { "type": "opencollective", @@ -9433,8 +8530,6 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "peer": true, @@ -9444,8 +8539,6 @@ }, "node_modules/prettier": { "version": "3.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", - "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "license": "MIT", "peer": true, "bin": { @@ -9460,8 +8553,6 @@ }, "node_modules/prettier-plugin-tailwindcss": { "version": "0.6.14", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.14.tgz", - "integrity": "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==", "license": "MIT", "engines": { "node": ">=14.21.3" @@ -9556,8 +8647,6 @@ }, "node_modules/proxy-addr": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, "license": "MIT", "dependencies": { @@ -9570,15 +8659,11 @@ }, "node_modules/psl": { "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true, "license": "MIT" }, "node_modules/punycode": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -9587,8 +8672,6 @@ }, "node_modules/pvtsutils": { "version": "1.3.6", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", - "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", "license": "MIT", "dependencies": { "tslib": "^2.8.1" @@ -9596,8 +8679,6 @@ }, "node_modules/pvutils": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", - "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", "license": "MIT", "engines": { "node": ">=16.0.0" @@ -9605,8 +8686,6 @@ }, "node_modules/qs": { "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -9621,15 +8700,11 @@ }, "node_modules/querystringify": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true, "license": "MIT" }, "node_modules/range-parser": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", "engines": { @@ -9638,8 +8713,6 @@ }, "node_modules/raw-body": { "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", "dependencies": { @@ -9654,8 +8727,6 @@ }, "node_modules/raw-body/node_modules/http-errors": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9675,8 +8746,6 @@ }, "node_modules/raw-body/node_modules/statuses": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { @@ -9685,8 +8754,6 @@ }, "node_modules/react": { "version": "19.2.7", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", - "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -9694,8 +8761,6 @@ }, "node_modules/react-aria": { "version": "3.44.0", - "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.44.0.tgz", - "integrity": "sha512-2Pq3GQxBgM4/2BlpKYXeaZ47a3tdIcYSW/AYvKgypE3XipxOdQMDG5Sr/NBn7zuJq+thzmtfRb0lB9bTbsmaRw==", "license": "Apache-2.0", "dependencies": { "@internationalized/string": "^3.2.7", @@ -9748,8 +8813,6 @@ }, "node_modules/react-dom": { "version": "19.2.7", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", - "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" @@ -9760,8 +8823,6 @@ }, "node_modules/react-error-boundary": { "version": "4.0.13", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", - "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5" @@ -9772,8 +8833,6 @@ }, "node_modules/react-hook-form": { "version": "7.72.1", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.72.1.tgz", - "integrity": "sha512-RhwBoy2ygeVZje+C+bwJ8g0NjTdBmDlJvAUHTxRjTmSUKPYsKfMphkS2sgEMotsY03bP358yEYlnUeZy//D9Ig==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -9788,14 +8847,10 @@ }, "node_modules/react-is": { "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", - "integrity": "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==", "license": "MIT" }, "node_modules/react-merge-refs": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-2.1.1.tgz", - "integrity": "sha512-jLQXJ/URln51zskhgppGJ2ub7b2WFKGq3cl3NYKtlHoTG+dN2q7EzWrn3hN3EgPsTMvpR9tpq5ijdp7YwFZkag==", "license": "MIT", "funding": { "type": "github", @@ -9804,15 +8859,11 @@ }, "node_modules/react-property": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.2.tgz", - "integrity": "sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==", "license": "MIT", "peer": true }, "node_modules/react-router": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-8.3.0.tgz", - "integrity": "sha512-qyPMvW83jGIct3yiieisxdk9M745anqhpIMKN5m1t6yBMfgVPpt77aHOqs5fUlEJRMCGffg9BaQLH9oPVOL7xQ==", "license": "MIT", "dependencies": { "cookie-es": "^3.1.1" @@ -9832,8 +8883,6 @@ }, "node_modules/react-stately": { "version": "3.32.2", - "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.32.2.tgz", - "integrity": "sha512-pDSrbCIJtir4HeSa//PTqLSR7Tl7pFC9usmkkBObNKktObQq3Vdgkf46cxeTD1ov7J7GDdR3meIyjXGnZoEzUg==", "license": "Apache-2.0", "dependencies": { "@react-stately/calendar": "^3.5.4", @@ -9866,8 +8915,6 @@ }, "node_modules/reflect-metadata": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "license": "Apache-2.0" }, "node_modules/regex": { @@ -9896,8 +8943,6 @@ }, "node_modules/remeda": { "version": "2.30.0", - "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.30.0.tgz", - "integrity": "sha512-TcRpI1ecqnMer3jHhFtMerGvHFCDlCHljUp0/9A4HxHOh5bSY3kP1l8nQDFMnWYJKl3MSarDNY1tb0Bs/bCmvw==", "license": "MIT", "dependencies": { "type-fest": "^4.41.0" @@ -9905,8 +8950,6 @@ }, "node_modules/remeda/node_modules/type-fest": { "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" @@ -9917,14 +8960,10 @@ }, "node_modules/remove-accents": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", - "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==", "license": "MIT" }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", "engines": { @@ -9933,8 +8972,6 @@ }, "node_modules/requireindex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz", - "integrity": "sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==", "dev": true, "license": "MIT", "engines": { @@ -9943,21 +8980,15 @@ }, "node_modules/requires-port": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, "license": "MIT" }, "node_modules/reselect": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz", - "integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==", "license": "MIT" }, "node_modules/retry": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "license": "MIT", "engines": { "node": ">= 4" @@ -9965,8 +8996,6 @@ }, "node_modules/rolldown": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", - "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", "license": "MIT", "dependencies": { "@oxc-project/types": "=0.133.0", @@ -9998,8 +9027,6 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { @@ -10019,21 +9046,15 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/scheduler": { "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, "node_modules/semver": { "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -10044,8 +9065,6 @@ }, "node_modules/send": { "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "dependencies": { @@ -10069,8 +9088,6 @@ }, "node_modules/send/node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { @@ -10079,15 +9096,11 @@ }, "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", "engines": { @@ -10096,8 +9109,6 @@ }, "node_modules/serve-static": { "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "dependencies": { @@ -10112,8 +9123,6 @@ }, "node_modules/set-function-length": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { @@ -10130,15 +9139,11 @@ }, "node_modules/setprototypeof": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true, "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { @@ -10150,8 +9155,6 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { @@ -10159,17 +9162,17 @@ } }, "node_modules/shiki": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", - "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.5.0.tgz", + "integrity": "sha512-OcRW72ngQvc+MSVWBRIovC/BTW589iUE/Vxav7VeM4RcY9MUjqB+IR6ILG1k9nuW6LiG/nct9uma4/MBtnZbmQ==", "license": "MIT", "dependencies": { - "@shikijs/core": "4.4.3", - "@shikijs/engine-javascript": "4.4.3", - "@shikijs/engine-oniguruma": "4.4.3", - "@shikijs/langs": "4.4.3", - "@shikijs/themes": "4.4.3", - "@shikijs/types": "4.4.3", + "@shikijs/core": "4.5.0", + "@shikijs/engine-javascript": "4.5.0", + "@shikijs/engine-oniguruma": "4.5.0", + "@shikijs/langs": "4.5.0", + "@shikijs/themes": "4.5.0", + "@shikijs/types": "4.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" }, @@ -10179,8 +9182,6 @@ }, "node_modules/side-channel": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", - "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10199,8 +9200,6 @@ }, "node_modules/side-channel-list": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "dev": true, "license": "MIT", "dependencies": { @@ -10216,8 +9215,6 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { @@ -10235,8 +9232,6 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { @@ -10255,15 +9250,11 @@ }, "node_modules/siginfo": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/signal-exit": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", "engines": { @@ -10275,8 +9266,6 @@ }, "node_modules/simplebar-core": { "version": "1.2.6", - "resolved": "https://registry.npmjs.org/simplebar-core/-/simplebar-core-1.2.6.tgz", - "integrity": "sha512-H5NYU+O+uvqOH5VXw3+lgoc1vTI6jL8LOZJsw4xgRpV7uIPjRpmLPdz0TrouxwKHBhpVLzVIlyKhaRLelIThMw==", "license": "MIT", "dependencies": { "@types/lodash-es": "^4.17.6", @@ -10286,8 +9275,6 @@ }, "node_modules/simplebar-react": { "version": "3.2.6", - "resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-3.2.6.tgz", - "integrity": "sha512-8jDiBuVCG86JmOrsmkA+4q77iFAEbhU9EX62PohLisg3dnxdLXFFhkxnx2Es3Cxt8IlZFlJsF9GaobFL3ukwiA==", "license": "MIT", "dependencies": { "simplebar-core": "^1.2.6" @@ -10298,8 +9285,6 @@ }, "node_modules/sirv": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", - "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "dev": true, "license": "MIT", "dependencies": { @@ -10311,10 +9296,21 @@ "node": ">=18" } }, + "node_modules/smol-toml": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.9.0.tgz", + "integrity": "sha512-hpd+HLON7HdZXqYchMM/+LaTTbdK0AU3NngIJ4KVyWbY9bfQqdL9cD+4yf6dUoU2Ap4VsU0JkQi6FxAI1B2mXQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, "node_modules/source-map-js": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -10332,15 +9328,11 @@ }, "node_modules/stackback": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", "engines": { @@ -10349,15 +9341,11 @@ }, "node_modules/std-env": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", - "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", "dev": true, "license": "MIT" }, "node_modules/strict-event-emitter": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", - "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", "dev": true, "license": "MIT" }, @@ -10377,8 +9365,6 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -10388,10 +9374,12 @@ "node": ">=8" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "license": "MIT" + }, "node_modules/style-to-js": { "version": "1.1.21", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", - "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "peer": true, "dependencies": { @@ -10400,8 +9388,6 @@ }, "node_modules/style-to-object": { "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", "license": "MIT", "peer": true, "dependencies": { @@ -10410,8 +9396,6 @@ }, "node_modules/swagger-parser": { "version": "10.0.3", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", "dev": true, "license": "MIT", "dependencies": { @@ -10423,14 +9407,10 @@ }, "node_modules/tabbable": { "version": "6.4.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", - "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", "license": "MIT" }, "node_modules/tagged-tag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", - "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", "dev": true, "license": "MIT", "engines": { @@ -10442,14 +9422,10 @@ }, "node_modules/tailwindcss": { "version": "4.3.3", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", - "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", "license": "MIT" }, "node_modules/tapable": { "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "license": "MIT", "engines": { "node": ">=6" @@ -10461,8 +9437,6 @@ }, "node_modules/tinybench": { "version": "6.1.4", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.1.4.tgz", - "integrity": "sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==", "dev": true, "license": "MIT", "engines": { @@ -10471,8 +9445,6 @@ }, "node_modules/tinyexec": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", - "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", "dev": true, "license": "MIT", "engines": { @@ -10481,8 +9453,6 @@ }, "node_modules/tinyglobby": { "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -10497,8 +9467,6 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", "engines": { "node": ">=12.0.0" @@ -10514,8 +9482,6 @@ }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "engines": { "node": ">=12" @@ -10526,8 +9492,6 @@ }, "node_modules/tinypool": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz", - "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==", "dev": true, "license": "MIT", "engines": { @@ -10536,8 +9500,6 @@ }, "node_modules/tinyrainbow": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", - "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", "dev": true, "license": "MIT", "engines": { @@ -10546,8 +9508,6 @@ }, "node_modules/tmp": { "version": "0.2.7", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", - "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", "engines": { @@ -10556,8 +9516,6 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10569,8 +9527,6 @@ }, "node_modules/toidentifier": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", "engines": { @@ -10579,8 +9535,6 @@ }, "node_modules/totalist": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", "engines": { @@ -10589,8 +9543,6 @@ }, "node_modules/tough-cookie": { "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -10605,8 +9557,6 @@ }, "node_modules/tough-cookie/node_modules/universalify": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, "license": "MIT", "engines": { @@ -10625,20 +9575,14 @@ }, "node_modules/ts-pattern": { "version": "5.8.0", - "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.8.0.tgz", - "integrity": "sha512-kIjN2qmWiHnhgr5DAkAafF9fwb0T5OhMVSWrm8XEdTFnX6+wfXwYOFjeF86UZ54vduqiR7BfqScFmXSzSaH8oA==", "license": "MIT" }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tsyringe": { "version": "4.10.0", - "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", - "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", "license": "MIT", "dependencies": { "tslib": "^1.9.3" @@ -10649,14 +9593,10 @@ }, "node_modules/tsyringe/node_modules/tslib": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD" }, "node_modules/tunnel-rat": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz", - "integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==", "license": "MIT", "dependencies": { "zustand": "^4.3.2" @@ -10664,8 +9604,6 @@ }, "node_modules/tunnel-rat/node_modules/zustand": { "version": "4.5.6", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.6.tgz", - "integrity": "sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ==", "license": "MIT", "dependencies": { "use-sync-external-store": "^1.2.2" @@ -10692,8 +9630,6 @@ }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "peer": true, @@ -10706,8 +9642,6 @@ }, "node_modules/type-fest": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.2.0.tgz", - "integrity": "sha512-xxCJm+Bckc6kQBknN7i9fnP/xobQRsRQxR01CztFkp/h++yfVxUUcmMgfR2HttJx/dpWjS9ubVuyspJv24Q9DA==", "dev": true, "license": "(MIT OR CC0-1.0)", "dependencies": { @@ -10722,8 +9656,6 @@ }, "node_modules/type-is": { "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", "dependencies": { @@ -10736,8 +9668,6 @@ }, "node_modules/typescript": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", - "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10771,8 +9701,6 @@ }, "node_modules/undici-types": { "version": "7.19.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", - "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "devOptional": true, "license": "MIT", "peer": true @@ -10847,8 +9775,6 @@ }, "node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -10857,8 +9783,6 @@ }, "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "license": "MIT", "engines": { @@ -10867,8 +9791,6 @@ }, "node_modules/unxhr": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", - "integrity": "sha512-6cGpm8NFXPD9QbSNx0cD2giy7teZ6xOkCUH3U89WKVkL9N9rBrWjlCwhR94Re18ZlAop4MOc3WU1M3Hv/bgpIw==", "license": "MIT", "peer": true, "engines": { @@ -10877,14 +9799,10 @@ }, "node_modules/uplot": { "version": "1.6.32", - "resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.32.tgz", - "integrity": "sha512-KIMVnG68zvu5XXUbC4LQEPnhwOxBuLyW1AHtpm6IKTXImkbLgkMy+jabjLgSLMasNuGGzQm/ep3tOkyTxpiQIw==", "license": "MIT" }, "node_modules/uplot-react": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/uplot-react/-/uplot-react-1.2.4.tgz", - "integrity": "sha512-mDe/mqD9KtXeHDR8llSJaUFpDcEJvYpHNS+cyUhJ2qvkbT9GPKod1BVXG+hNegRqYiV1ldsFBlI5+OKSi/yPNA==", "license": "MIT", "engines": { "node": ">=8.10" @@ -10896,8 +9814,6 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -10907,8 +9823,6 @@ }, "node_modules/url-parse": { "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10918,8 +9832,6 @@ }, "node_modules/use-debounce": { "version": "10.0.4", - "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.4.tgz", - "integrity": "sha512-6Cf7Yr7Wk7Kdv77nnJMf6de4HuDE4dTxKij+RqE9rufDsI6zsbjyAxcH5y2ueJCQAnfgKbzXbZHYlkFwmBlWkw==", "license": "MIT", "engines": { "node": ">= 16.0.0" @@ -10930,8 +9842,6 @@ }, "node_modules/use-sync-external-store": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -10939,8 +9849,6 @@ }, "node_modules/utils-merge": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", "engines": { @@ -10949,8 +9857,6 @@ }, "node_modules/uuid": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", - "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -10962,8 +9868,6 @@ }, "node_modules/validator": { "version": "13.15.26", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", - "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==", "dev": true, "license": "MIT", "engines": { @@ -10972,8 +9876,6 @@ }, "node_modules/vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", "engines": { @@ -11010,8 +9912,6 @@ }, "node_modules/vite": { "version": "8.0.16", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", - "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", @@ -11087,8 +9987,6 @@ }, "node_modules/vite-node": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-6.0.0.tgz", - "integrity": "sha512-oj4PVrT+pDh6GYf5wfUXkcZyekYS8kKPfLPXVl8qe324Ec6l4K2DUKNadRbZ3LQl0qGcDz+PyOo7ZAh00Y+JjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11108,10 +10006,22 @@ "url": "https://opencollective.com/antfu" } }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "engines": { "node": ">=12" @@ -11122,8 +10032,6 @@ }, "node_modules/vitest": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.0.tgz", - "integrity": "sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -11205,8 +10113,6 @@ }, "node_modules/vitest-browser-react": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/vitest-browser-react/-/vitest-browser-react-2.3.0.tgz", - "integrity": "sha512-S5vdGHHA93j2Z6dbmIJI1wtxT3AXPTRlmC1Meo+ekG011yNnEutMAnHrwyj8qFlGhgBYA8ENGK6+o1Q+vnFz6A==", "dev": true, "license": "MIT", "funding": { @@ -11230,8 +10136,6 @@ }, "node_modules/vitest/node_modules/magic-string": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.2.3.tgz", - "integrity": "sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==", "dev": true, "license": "MIT", "dependencies": { @@ -11240,8 +10144,6 @@ }, "node_modules/vitest/node_modules/picomatch": { "version": "4.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", - "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", "engines": { @@ -11251,10 +10153,12 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { @@ -11269,8 +10173,6 @@ }, "node_modules/why-is-node-running": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { @@ -11286,8 +10188,6 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "peer": true, @@ -11297,15 +10197,11 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC", "peer": true }, "node_modules/ws": { "version": "8.21.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", - "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "dev": true, "license": "MIT", "engines": { @@ -11326,8 +10222,6 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", "engines": { @@ -11336,8 +10230,6 @@ }, "node_modules/yaml": { "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "devOptional": true, "license": "ISC", "bin": { @@ -11352,8 +10244,6 @@ }, "node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "dependencies": { @@ -11371,8 +10261,6 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", "engines": { @@ -11381,15 +10269,11 @@ }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/yargs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { @@ -11398,8 +10282,6 @@ }, "node_modules/yargs/node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -11413,8 +10295,6 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "peer": true, @@ -11427,8 +10307,6 @@ }, "node_modules/yoctocolors-cjs": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", - "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", "dev": true, "license": "MIT", "engines": { @@ -11440,8 +10318,6 @@ }, "node_modules/z-schema": { "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -11461,8 +10337,6 @@ }, "node_modules/z-schema/node_modules/commander": { "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, "license": "MIT", "optional": true, @@ -11472,8 +10346,6 @@ }, "node_modules/zod": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -11481,8 +10353,6 @@ }, "node_modules/zustand": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz", - "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==", "license": "MIT", "engines": { "node": ">=12.20.0" diff --git a/package.json b/package.json index 1676890b1..33589fa64 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,11 @@ "private": true, "dependencies": { "@base-ui/react": "^1.1.0", + "@codemirror/autocomplete": "^6.20.3", + "@codemirror/commands": "^6.11.0", + "@codemirror/language": "^6.12.4", + "@codemirror/state": "^6.7.1", + "@codemirror/view": "^6.43.9", "@floating-ui/react": "^0.26.23", "@headlessui/react": "^2.2.9", "@oxide/design-system": "^6.7.1", @@ -77,6 +82,7 @@ "react-stately": "^3.32.2", "remeda": "^2.30.0", "semver": "^7.7.3", + "shiki": "^4.5.0", "simplebar-react": "^3.2.6", "ts-pattern": "^5.8.0", "tslib": "^2.7.0", @@ -112,6 +118,7 @@ "oxlint": "^1.70.0", "oxlint-tsgolint": "^0.23.0", "patch-package": "^8.0.0", + "smol-toml": "^1.9.0", "tailwindcss": "^4.3.3", "type-fest": "^5.2.0", "typescript": "^7.0.2", diff --git a/test/e2e/images.e2e.ts b/test/e2e/images.e2e.ts index a8f269c86..c60eada6e 100644 --- a/test/e2e/images.e2e.ts +++ b/test/e2e/images.e2e.ts @@ -125,7 +125,7 @@ test('can copy an image ID to clipboard', async ({ page, browserName }) => { // eslint-disable-next-line playwright/no-skipped-test test.skip( browserName === 'webkit', - 'navigator.clipboard.readText() works locally in Safari but not in CI.' + 'navigator.clipboard.readText() is forbidden in Safari.' ) await page.goto('/images') diff --git a/test/e2e/oxql.e2e.ts b/test/e2e/oxql.e2e.ts index 71fcf490a..a81459dbc 100644 --- a/test/e2e/oxql.e2e.ts +++ b/test/e2e/oxql.e2e.ts @@ -9,6 +9,7 @@ import { expect, test, type Page, type Locator } from '@playwright/test' import { oxqlQueries } from './oxql-queries' +import { clipboardText, expectToast } from './utils' const runQuery = async (page: Page, query?: string) => { if (query !== undefined) await page.getByRole('textbox').fill(query) @@ -17,12 +18,22 @@ const runQuery = async (page: Page, query?: string) => { const loading = page.getByLabel('Chart loading') await expect(loading).toBeVisible() await expect(loading).toBeHidden() - await expect(page.getByText('Query failed')).toBeHidden() + await expect(page.getByRole('alert')).toBeHidden() +} + +/** + * CodeMirror ignores Enter for `interactionDelay` (75ms) after the completion + * list opens, so a keypress the user made before seeing the tooltip can't + * accept an option. + */ +const acceptCompletion = async (page: Page) => { + await page.waitForTimeout(150) + await page.keyboard.press('Enter') } test.beforeEach(async ({ page }) => { - await page.goto('/system/oxql') - await expect(page.getByRole('heading', { name: 'OxQL Explorer' })).toBeVisible() + await page.goto('/system/metrics-explorer') + await expect(page.getByRole('heading', { name: 'Metrics Explorer' })).toBeVisible() }) test('unaligned multi-table query renders a chart per series', async ({ page }) => { @@ -87,7 +98,7 @@ test('joined query renders a chart per instance with a legend line per metric', }) test('"Drop first point" appears only for cumulative-derived charts', async ({ page }) => { - const dropFirst = page.getByLabel('Drop first point') + const dropFirst = page.getByLabel('Drop first data point') // a plain gauge is never cumulative, so there's no giant first point to drop await runQuery(page, oxqlQueries.basicTctl) @@ -121,45 +132,198 @@ test('results list is virtualized', async ({ page }) => { await expect.poll(getFirstRenderedIndex).not.toBe(0) }) -test('picking an example populates the query and renders a chart', async ({ page }) => { - await page.getByRole('button', { name: 'Try an example' }).click() - await page.getByRole('menuitem', { name: 'Power shelf fan speeds' }).click() - await expect(page.getByRole('textbox')).toHaveValue(/get hardware_component:fan_speed/) +test('picking an example populates the query and runs it', async ({ page }) => { + await page.getByRole('button', { name: 'Power shelf fan speeds' }).click() + // the editor is a contenteditable, so assert on text rather than value + await expect(page.getByRole('textbox')).toContainText('get hardware_component:fan_speed') - await runQuery(page) + // the query runs automatically, no need to click "Run query" + const loading = page.getByLabel('Chart loading') + await expect(loading).toBeVisible() + await expect(loading).toBeHidden() await expect(page.getByRole('figure').first()).toBeVisible() }) -test('empty query is blocked by client-side validation', async ({ page }) => { +test('chart title opens timeseries docs', async ({ page }) => { + await page.getByRole('button', { name: 'Power shelf fan speeds' }).click() + await page + .getByRole('button', { name: 'hardware_component:fan_speed details' }) + .first() + .click() + + const modal = page.getByRole('dialog', { name: 'Timeseries details' }) + await expect(modal).toBeVisible() + // read-only modal focuses its title instead of the docs link at the bottom + await expect(modal.getByRole('heading', { name: 'Timeseries details' })).toBeFocused() + await expect( + modal.getByRole('heading', { name: 'hardware_component:fan_speed' }) + ).toBeVisible() + // descriptions come from the snapshot, not the schema endpoint + await expect( + modal.getByText('A fan speed measurement, in rotations per minute') + ).toBeVisible() + await expect(modal.getByText('f32', { exact: true })).toBeVisible() + await expect(modal.getByText('rpm', { exact: true })).toBeVisible() + await expect(modal.getByText('hubris_archive_id')).toBeVisible() + await expect(modal.getByRole('link', { name: 'Timeseries schemas' })).toHaveAttribute( + 'href', + 'https://docs.oxide.computer/guides/metrics/timeseries-schemas#_hardware_componentfan_speed' + ) +}) + +test('joined chart title has docs for each timeseries', async ({ page }) => { + await page.getByRole('button', { name: 'Bytes sent & received per sled' }).click() + await expect( + page.getByRole('heading', { name: 'sled_data_link:bytes_sent' }).first() + ).toBeVisible() + await expect( + page.getByRole('heading', { name: 'sled_data_link:bytes_received' }).first() + ).toBeVisible() + + await page + .getByRole('button', { name: 'sled_data_link:bytes_received details' }) + .first() + .click() + const received = page.getByRole('dialog', { name: 'Timeseries details' }) + await expect( + received.getByRole('heading', { name: 'sled_data_link:bytes_received' }) + ).toBeVisible() + await expect(received.getByText('Number of bytes received on the link')).toBeVisible() + await expect(received.getByText('Number of bytes sent on the link')).toBeHidden() + await page.keyboard.press('Escape') + await expect(received).toBeHidden() + + await page + .getByRole('button', { name: 'sled_data_link:bytes_sent details' }) + .first() + .click() + const sent = page.getByRole('dialog', { name: 'Timeseries details' }) + await expect( + sent.getByRole('heading', { name: 'sled_data_link:bytes_sent' }) + ).toBeVisible() + await expect(sent.getByText('Number of bytes sent on the link')).toBeVisible() +}) + +test('editor completions walk from target to metric', async ({ page }) => { const textbox = page.getByRole('textbox') - await textbox.fill('') - await page.getByRole('button', { name: 'Run query' }).click() + await textbox.click() + await page.keyboard.type('get hardware') - await expect(textbox).toHaveAttribute('aria-invalid', 'true') - await expect(page.getByText('Enter a query').first()).toBeVisible() - await expect(page.getByRole('figure')).toHaveCount(0) + const options = page.getByRole('listbox').getByRole('option') + await expect(async () => { + // ctrl-space explicitly re-requests completions in case the schema list + // hadn't loaded when typing started + await page.keyboard.press('Control+Space') + await expect(options.first()).toBeVisible({ timeout: 1000 }) + }).toPass() + + // the first half of a name completes on its own, so this is the target, not + // hardware_component:fan_speed + await expect(options).toHaveText(['hardware_component4 metrics']) + + // accept with the keyboard rather than clicking: the info tooltip can + // overlap the option and intercept pointer events + await acceptCompletion(page) + await expect(textbox).toContainText('get hardware_component:') + + // accepting a target reopens the list on that target's metrics + await expect(options.getByText('fan_speed', { exact: true })).toBeVisible() + await page.keyboard.type('fan') // narrow until fan_speed is the top match + await acceptCompletion(page) + await expect(textbox).toContainText('get hardware_component:fan_speed') +}) + +test('results can be copied as JSON', async ({ page }) => { + await runQuery(page, oxqlQueries.basicTctl) + + // result summary is visible + await expect(page.getByText('1 timeseries', { exact: true })).toBeVisible() + + await page.getByRole('button', { name: 'Results actions' }).click() + await page.getByRole('menuitem', { name: 'Copy as JSON' }).click() + await expectToast(page, 'Results copied as JSON') +}) + +test('copied JSON actually matches the response body', async ({ page, browserName }) => { + // eslint-disable-next-line playwright/no-skipped-test + test.skip( + browserName === 'webkit', + 'navigator.clipboard.readText() is forbidden in Safari.' + ) + + const response = page.waitForResponse('**/v1/system/timeseries/query') + // the most likely error here is a failure to restore snake case, so + // histograms are a decent test (they always include start_times) + await runQuery(page, oxqlQueries.bytesSentAndReceived) + const raw = await response.then((r) => r.json()) + + await page.getByRole('button', { name: 'Results actions' }).click() + await page.getByRole('menuitem', { name: 'Copy as JSON' }).click() + + expect(JSON.stringify(JSON.parse(await clipboardText(page)))).toBe(JSON.stringify(raw)) }) test('a query the backend rejects surfaces an error instead of a chart', async ({ page, }) => { - await page.getByRole('textbox').fill('junk junk junk!') + const textbox = page.getByRole('textbox') + await textbox.fill('junk junk junk!') await page.getByRole('button', { name: 'Run query' }).click() - await expect(page.getByText('Query failed')).toBeVisible() + // the server's parse error is shown below the editor, minus the caret + // line, which assumes a monospace terminal + const error = page.getByRole('alert') + await expect(error).toContainText('Error at 1:1') + await expect(error).toContainText('Expected: error at 1:1') + await expect(error).not.toContainText('^') + // and the editor border turns red + await expect(textbox).toHaveAttribute('aria-invalid', 'true') await expect(page.getByRole('figure')).toHaveCount(0) }) -test('pages reads the initial query from the URL', async ({ page }) => { - await page.goto(`/system/oxql?query=${encodeURIComponent(oxqlQueries.basicTctl)}`) - await expect(page.getByRole('textbox')).toHaveValue(oxqlQueries.basicTctl) +test('parse errors underline the offending spot in the editor', async ({ page }) => { + const textbox = page.getByRole('textbox') + await textbox.fill('get sled_data_link:bytes_sent | oops') + await page.getByRole('button', { name: 'Run query' }).click() + + await expect(page.getByRole('alert')).toBeVisible() + + // the error underline has no semantic representation, so target the class + const underlined = page.locator('.oxql-error-underline') + await expect(underlined).toHaveText('oops') + // guard against the mark existing but the CSS not applying + await expect(underlined).toHaveCSS('text-decoration-line', 'underline') + + // editing the query invalidates the position, clearing the underline + await textbox.pressSequentially('x') + await expect(underlined).toBeHidden() }) test('pages writes the query to the URL after a successful run', async ({ page }) => { - await page.goto('/system/oxql') + // a successful run writes the query to the URL await runQuery(page, oxqlQueries.basicTctl) - await expect .poll(() => new URL(page.url()).searchParams.get('query')) .toBe(oxqlQueries.basicTctl) }) + +test('page loads queries from the URL when set', async ({ page }) => { + await page.goto(`${page.url()}?query=${encodeURIComponent(oxqlQueries.basicTctl)}`) + // the editor is a contenteditable, so assert line by line rather than on value + const textbox = page.getByRole('textbox') + await expect(textbox).toContainText('get hardware_component:amd_cpu_tctl') + await expect(textbox).toContainText('| filter timestamp > @now() - 1m') +}) + +test('cursor sits at the start of the line when the query is empty', async ({ page }) => { + // CodeMirror draws its own cursor because Firefox puts the native caret in + // the wrong spot when the line contains nothing but the placeholder widget. + // The cursor has no semantic representation, so target the class. + await page.getByRole('textbox').click() + const cursor = await page.locator('.cm-cursor').boundingBox() + const placeholder = await page.locator('.cm-placeholder').boundingBox() + + // the cursor sits where the placeholder text starts, give or take its own width + expect(Math.abs(cursor!.x - placeholder!.x)).toBeLessThan(2) + expect(Math.abs(cursor!.y - placeholder!.y)).toBeLessThan(1) +}) diff --git a/test/e2e/utilization.e2e.ts b/test/e2e/utilization.e2e.ts index b3cbd56f6..10dc62d68 100644 --- a/test/e2e/utilization.e2e.ts +++ b/test/e2e/utilization.e2e.ts @@ -49,7 +49,7 @@ test.describe('System utilization', () => { // eslint-disable-next-line playwright/no-skipped-test test.skip( browserName === 'webkit', - 'navigator.clipboard.readText() works locally in Safari but not in CI.' + 'navigator.clipboard.readText() is forbidden in Safari.' ) await page.goto('/system/utilization') await clickRowAction(page, 'maze-war', 'Copy silo ID') diff --git a/test/e2e/utils.ts b/test/e2e/utils.ts index f1bfc3ee3..c0f32ed3a 100644 --- a/test/e2e/utils.ts +++ b/test/e2e/utils.ts @@ -208,8 +208,7 @@ export async function closeToast(page: Page) { } /** - * This will not work in Firefox, which only supports reading from the clipboard in extensions. - * See [MDN: readText](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText#browser_compatibility). + * This will not work in Safari, which forbids clipboard reading without a user interaction. */ export const clipboardText = async (page: Page) => page.evaluate(() => navigator.clipboard.readText()) diff --git a/test/visual/regression.e2e.ts b/test/visual/regression.e2e.ts index 810c1efc1..aa2577414 100644 --- a/test/visual/regression.e2e.ts +++ b/test/visual/regression.e2e.ts @@ -261,11 +261,11 @@ test.describe('Visual Regression', { tag: '@visual' }, () => { for (const [name, query] of Object.entries(oxqlQueries)) { test(`oxql ${name}`, async ({ page }) => { - await page.goto('/system/oxql', { waitUntil: 'networkidle' }) + await page.goto('/system/metrics-explorer', { waitUntil: 'networkidle' }) await page.getByRole('textbox').fill(query) await page.getByRole('button', { name: 'Run query' }).click() await expect(page.locator('figure').first()).toBeVisible() - await expect(page).toHaveScreenshot(`oxql-${name}.png`, fullPage) + await expect(page).toHaveScreenshot(`metrics-explorer-${name}.png`, fullPage) }) } }) diff --git a/tools/generate_api_client.sh b/tools/generate_api_client.sh index 688d8597d..608be03de 100755 --- a/tools/generate_api_client.sh +++ b/tools/generate_api_client.sh @@ -38,6 +38,9 @@ for f in Api.ts msw-handlers.ts validate.ts; do mv "$GEN_DIR/$f.tmp" "$GEN_DIR/$f" done +# skips fetching if already generated for this commit +node tools/generate_timeseries_metadata.ts + npm run fmt cat > $GEN_DIR/OMICRON_VERSION < +} + +async function fetchOk(url: string, headers?: Record) { + const response = await fetch(url, { headers }) + if (!response.ok) throw new Error(`${response.status} fetching ${url}`) + return response +} + +// a token is optional, but avoids the low unauthenticated rate limit +const ghHeaders: Record = process.env.GITHUB_TOKEN + ? { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` } + : {} + +const listing: { name: string; download_url: string }[] = await fetchOk( + `https://api.github.com/repos/oxidecomputer/omicron/contents/${SCHEMA_DIR}?ref=${sha}`, + ghHeaders +).then((r) => r.json()) + +const tomlFiles = listing.filter((f) => f.name.endsWith('.toml')) +const schemas = await Promise.all( + tomlFiles.map(async (f) => { + const text = await fetchOk(f.download_url).then((r) => r.text()) + return { + file: path.basename(f.name, '.toml'), + ...(parse(text) as unknown as SchemaToml), + } + }) +) + +const latestFields = (fields: SchemaToml['fields'], { versions }: Versioned) => + versions[versions.length - 1].fields.map((name) => ({ + name, + fieldType: fields[name].type, + description: fields[name].description, + })) + +// Target fields are shared by every metric on the target, so they're stored +// once per target instead of being repeated on each timeseries. Targets are +// keyed by schema file because two files can define different targets with +// the same name (e.g., virtual_machine). +const targets = R.pipe( + schemas, + R.sortBy((s) => s.file), + R.mapToObj(({ file, target, fields }) => [ + file, + { description: target.description, fields: latestFields(fields, target) }, + ]) +) + +const timeseries = R.pipe( + schemas, + R.flatMap(({ file, target, metrics, fields }) => + metrics.map((metric) => ({ + name: `${target.name}:${metric.name}`, + target: file, + description: metric.description, + units: metric.units, + datumType: metric.datum_type, + fields: latestFields(fields, metric), + })) + ), + R.sortBy((t) => t.name), + R.mapToObj(({ name, ...rest }) => [name, rest]) +) + +fs.writeFileSync( + OUT_FILE, + `/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * Copyright Oxide Computer Company + */ + +// generated by tools/generate_timeseries_metadata.ts from the oximeter schema +// TOML files in omicron. do not update manually. see docs/update-pinned-api.md + +import type { DatumType, FieldSchema, Units } from './Api' + +export const omicronVersion = '${sha}' + +type Field = Omit + +export const targets: Partial> = + ${JSON.stringify(targets)} + +export const timeseries: Partial< + Record< + string, + { + /** key into \`targets\` */ + target: string + description: string + units: Units + datumType: DatumType + fields: Field[] + } + > +> = ${JSON.stringify(timeseries)} +` +) + +console.info( + `wrote ${Object.keys(timeseries).length} timeseries from ${tomlFiles.length} files to ${path.relative(ROOT, OUT_FILE)}` +)